当前位置: 首页 > 网络应用技术

Redis和MySQL数据一致性问题

时间:2023-03-05 23:52:39 网络应用技术

  REDIS具有高性能数据读取功能,该功能广泛用于缓存方案。一种是提高业务系统的性能。

  以Redis作为缓存组件来防止以下问题,否则可能会导致生产事故。

  在本文正式开始之前,我认为我们需要获得以下两个共识:

  目录如下:

  总结

  数据一致性是指:

  反向推动缓存与数据库不一致:

  苍凉

  为什么会出现数据一致性问题?

  当Redis用作缓存时,当数据更改时,我们需要仔细写入以确保缓存与数据库的数据一致。

  毕竟,数据库和缓存是两个系统。如果您想确保强大的一致性,则有必要引入或等于分布式一致性协议或分布式锁等。这很难实现,并且肯定会具有性能。

  如果数据的一致性要求很高,是否真的有必要引入缓存?

  使用缓存时,通常有几种缓存使用策略来改善系统性能:

  SO称为“旁路缓存”是读取应用程序系统的数据库和更新缓存操作,并且业务系统是最常用的缓存策略。

  2.1.1读取数据

  读取数据逻辑如下:

  定时图如下:

  wingrser缓存读取顺序地图

  优点的伪编码如下:

  缺点在于,数据未点击后将数据加载到缓存中,因此,数据请求响应时间称为第一个调用将增加一些费用,因为将需要其他缓存填充和数据库查询时间。

  2.1.2更新数据以在模式下编写数据时,以下过程如下。

  Wingrsen缓存写数据

  使用时,最常见的写作策略是直接将数据写入数据库,但是缓存可能与数据库不一致。

  我们应该为缓存设置到期时间,这是确保最终一致性的解决方案。

  如果到期时间太短,则该应用程序将继续从数据库中查询数据。相似地,如果到期时间太长并且缓存更新时不会失败,则缓存数据可能是脏数据。

  最常用的方法是删除缓存以使缓存数据失败。

  苍凉

  为什么不更新缓存?

  性能问题

  当缓存的成本很高时,您需要访问多种形式的联合计算。建议直接删除缓存,而不是更新缓存数据以确保一致性。

  安全问题

  在高频率场景中,查询中发现的数据可能是旧值。特定的代码兄弟将分析它。不用担心。

  当缓存未点击时,数据将从数据库加载,并将其写入缓存并返回到应用程序系统。

  尽管非常相似,但应用程序系统负责获取数据并填充数据库的缓存。

  读取将数据存储中的值获取值的责任转移到了缓存提供商。

  读取

  读取实现了焦点分离的原理。代码仅与缓存进行交互,以及缓存组件来管理自身和数据库之间的数据。

  与读取相似,在编写请求时,写入责任会将责任传输到缓存系统,并且缓存摘要层从高速缓存摘要层进行更新以更新缓存数据和数据库数据。正时流程图如下:

  写入

  主要优点是应用系统不需要考虑故障处理和重试逻辑,而是将其移交给缓存抽象层以管理实施。

  仅使用此策略的优点和缺点是毫无意义的,因为该策略必须首先编写缓存,然后编写数据库,这为书写操作带来了其他延迟。

  与合作一起使用时,可以使用成分的优点,并且可以同时保证数据一致性。无需考虑如何使高速缓存设置失败。

  写入

  该策略扭转了填充缓存的顺序。在没有击中缓存后,它并没有延迟到缓存,但是该缓存首先写入数据中,然后将数据写入缓存组件中。

  通常,不需要的优势和缺点的数据也将写入缓存,从而导致更大的缓存和更高的成本。

  这张照片似乎一目了然。实际上,不是。区别是最后一个箭头的箭头:它从实心变为线。

  这意味着缓存系统将更新数据库数据异步,并且应用程序系统仅与缓存系统进行交互。

  应用程序不需要等待数据库更新完成,从而改善了应用程序性能,因为数据库的更新是最慢的操作。

  ![图片]()

  写作

  在此策略下,缓存和数据库的一致性不强,建议不建议使用较高的一致性系统。

  最有用的业务场景是(旁路缓存)策略。在此策略下,客户对数据的阅读过程首先读取缓存,如果命中返回;在缓存中,读取操作不会导致缓存与数据库不一致。

  关键是写操作。数据库和缓存都需要修改,并且将有两个序列,这可能会导致数据不再保持一致。对于编写,我们需要考虑两个问题:

  这两个问题将被安排和合并,将有四个方案:

  下一个分析不必记住记住它。关键是,在扣除过程中,您只需要考虑以下两种情况会带来严重的问题:

  苍凉

  为什么不考虑第一次失败,第二个成功?

  你猜呀?

  现在,第一个失败了,不需要第二个。它可以在第一步直接返回到50倍和其他异常信息,也不会出现不一致的问题。

  只有第一个成功才会引起头痛。为了确保其原子质,它涉及分布式交易的类别。

  ![图片]()

  在更新数据库之前更新缓存

  如果缓存成功,并且数据库首先失败,则将导致缓存是最新数据,数据库是旧数据,然后缓存为脏数据。

  之后,其他查询会在他们询问时立即获取此数据,但是该数据库中没有存在。

  数据库不存在数据,缓存并返回客户端是毫无意义的。

  该方案是直接的。

  一切如下:如下:

  目前,我们将推断,如果这两个操作的原子性被破坏了:第一步是成功的。

  它将导致数据库是最新数据,缓存是旧数据,并且存在一个一致性问题。

  我不会绘制图片,类似于上图,并且可以调整Redis和MySQL的位置。

  同时发生的场景Xie Baige经常996,腰痛和颈部疼痛,越来越多的错误,您想按摩推动力,并让它提高编程技能。

  流行病的影响并不容易出现。高端俱乐部的技术人员正在争先恐后地接收这一命令,兄弟俩很高,兄弟俩。

  进入商店后,前台将向系统输入客户的信息。执行的初始值表明没有人存储在数据库和缓存中,然后安排技术员按摩服务。

  如下所示:

  ![图片]()

  高高并首先发送数据库,然后更新缓存

  最后,发现数据库的值=,并且缓存值=。

  98号技术人员的旧数据涵盖了高速缓存中520位技术人员的最新数据。

  因此,在高分子场景中,多个线程在编写缓存之前同时编写数据,缓存将具有旧值,并且数据库是最新值中最不一致的情况。

  该方案直接通过。

  苍凉

  如果第一步失败,则将直接返回50x异常,并且不会存在不一致的数据。

  根据前面提到的例行程序,假设第一个操作成功,第二次操作的失败会发生什么?在高并发现场会发生什么?

  第二步是编写数据库故障。现在有两个请求:编写请求A,阅读请求B。

  编写请求A的第一步在缓存之前已成功删除。数据库的写入数据失败,这将导致数据丢失。数据库保存在旧值中。

  然后我要求B进来,发现缓存不存在。从数据库中,我读取旧数据并将其写入缓存。

  高和张贴的问题![图片] ()

  首先删除,然后编写数据库

  旧数据将以这种方式出现,并且在高速缓存到期之前无法读取最多的数据。xiaocaiji最初是由第98位技术人员收到的,但是大堂经理认为没有人收到。

  该方案是通过的,因为第一步是成功的,第二步失败了,这将导致数据库是旧数据。缓存中没有数据可以继续读取数据库中的旧值以编写缓存,从而导致数据不一致,并且一次将更多的cahche。

  不管是异常还是高且发射场景,数据都会不一致。

  在前三个解决方案之后,所有解决方案都通过了。最后分析最终解决方案。

  根据“常规”,判断异常和高度引起的问题。

  该策略可以知道,如果在写作数据库阶段失败,它将直接返回到客户端异常,而无需执行缓存操作。

  因此,第一步失败不会与数据不一致。

  删除的重点是将最新数据写入数据库的第一步的重点。如果缓存失败,该怎么办?

  这两个操作可以放在一次交易中。删除缓存并失败时,数据库会回滚。

  苍凉

  在高分子场景中,这是不合适的,并且容易出现主要交易,导致死亡锁的问题。

  如果您不回头,那么数据库是新数据,缓存或旧数据,并且数据不一致。我应该怎么办?

  因此,我们必须找到一种使缓存删除成功的方法,否则我们只能等到有效期无效。

  使用重试机制。

  例如,三次,三个故障,将日志记录到数据库,并使用分布式调度组件XXL-JOB来实现后续处理。

  在高平行的场景中,最好使用异步方法重试,例如将消息发送到MQ中间件以实现异步解耦。

  或使用运河框架订阅MYSQL BINLOG日志,监视相应的更新请求,然后执行相应的缓存操作的删除。

  如果分析了较高的并发场景,则高概率读取和写入将遇到任何问题...

  ![图片]()

  首先编写数据库,然后删除

  阅读请求可能具有少量的旧数据,但是很快就会删除旧数据,最新的请求可以获取最新数据,并且问题不大。

  还有一个相对极端的情况。当缓存自动失败时,它会遇到高且次要的阅读和写作情况。假设将有两个请求,一个线程A进行查询操作和线程B更新操作,则将如下,然后在以下情况下会有情况。

  ![图片]()

  缓存突然失败

  苍凉

  兄弟代码,仍然存在不一致的情况。

  不要惊慌,这种情况的可能性很小。上述情况的必要条件是:

  通常,MySQL支架的Qps -Olone机器约为5K,而TPS约为1K(PS:TOMCAT的QPS 4K,TPS = 1K)。

  数据库读取操作远离写作操作(因此,它与阅读和写作分开),因此步骤(3)很难比步骤(2)更快。同时,必须将其与缓存无效。

  因此,使用旁路缓存策略时,请推荐它以编写操作:首先更新数据库,然后删除缓存。

  最后,对于缓存(旁路缓存)策略,数据库首先更新,然后使用缓存来分析数据一致性解决方案是什么?

  如果首先使用缓存,如何避免肮脏的数据更新数据库?

  苍凉

  使用延迟的双重删除策略。

  这次只出现仅500毫秒的肮脏数据阅读时间。关键是如何确定这个休眠时间?

  延迟时间的目的是确保读取请求结束。编写请求可以删除由读取请求引起的缓存污垢数据。

  因此,我们需要自行评估项目的数据阅读业务逻辑,并根据阅读,将数百毫秒添加到延迟时间。

  苍凉

  如果缓存删除失败,该怎么办?例如,延迟双重删除的第二个删除失败,难道不会删除肮脏的数据。

  使用重试机制来确保成功的缓存。

  例如,三次,三个故障,记录到数据库的日志并发送警告以进行人工干预。

  在高平行的场景中,最好使用异步方法重试,例如将消息发送到MQ中间件以实现异步解耦。

  重试机制

  (5)如果删除失败并且未达到最大试验数,则该消息将在删除成功之前重新输入,否则将记录到数据库和人工干预。

  该方案的缺点是它导致在业务代码中入侵,因此有下一个解决方案可以启动专门订阅数据库binlog的服务,以读取需要删除用于缓存删除操作的数据。

  Binlog异步删除

  缓存策略的最佳实践是缓存模式。涉及阅读缓存的最佳实践和编写缓存的最佳实践。

  阅读缓存的最佳实践:首先阅读缓存,然后返回热门歌曲;在不登录的情况下检查数据库,然后将其写入数据库。

  编写缓存的最佳实践:

  在上述最佳实践下,为了确保尽可能多的缓存和数据库之间的一致性,我们可以使用延迟二重删除。

  为了防止删除失败,我们使用异步重试机制来确保可以正确删除它。异步机制可以将删除消息发送到MQ消息中间件,或使用运河订阅MySQL Binlog日志监视请求以删除相应的缓存。

  因此,如果我必须保证绝对的一致性,请首先得出结论:

  无法实现绝对一致性。这取决于上限理论。应用于缓存系统的场景是非弦一致性的场景,因此它属于CAP中的AP。

  因此,我们必须走到基础理论最终一致性的末尾。

  实际上,一旦在计划中使用了缓存,通常意味着我们已经放弃了数据的强大一致性,但这也意味着我们的系统可以改善性能。

  SO称为权衡正是这种情况。

  原始:https://juejin.cn/post/7103701796429758478