开发者

Redis与数据库数据一致性的原因及解决方案

开发者 https://www.devze.com 2025-04-13 08:58 出处:网络 作者: AaronJonah
目录一、概述二、原因1、读取数据2、写数据2.1、缓存是更新还是删除2.2 先操作数据库还是先操作缓存二、解决方案1、延迟删除机制2、binlog同步删除机制3、异步重试删除机制  4、binlog解耦异步重试机制三、
目录
  • 一、概述
  • 二、原因
    • 1、读取数据
    • 2、写数据
      • 2.1、缓存是更新还是删除
      • 2.2 先操作数据库还是先操作缓存
  • 二、解决方案
    • 1、延迟删除机制
      • 2、binlog同步删除机制
        • 3、异步重试删除机制  
          • 4、binlog解耦异步重试机制
          • 三、总结

            一、概述

            Redis是一种开源、使用内存存储数据介质的键值对存储系统。redis的读写速度非常快,常用于应用与数据库之间做缓存层,能够减少数据库IO操作,提升数据库性能,并提高应用端的请求响应速度。但涉及到并发读写数据时就容易出现redis与数据库数据一致性的问题。

            二、原因

            应用对数据库的操作无外乎两个操作读操作写操作。 redis作为应用与数据库之间的缓存层,通常应用在操作数据库之前先操作redis,读操作时只有redis不存在,才会操作数据库,写操作时需要更新数据库和redis缓存。针对这两个操作流程,我们需要分编程客栈析下在什么场景下才会出现redis与数据库数据不一致的问题。

            1、读取数据

            读取数据流程如下:

            Redis与数据库数据一致性的原因及解决方案

            1. 应用程序需要从数据库读取数据时,先查询redis的缓存数据是否命中。

            2. 若命中,直接返回。若未命中,再去查询数据库。

            3. 将查询到的数据先保存到redis中,并设置过期时间,再将数据返回到应用。

            以上是常用的一个读取数据的场景,根据场景分析,只读的情况下是不会出现redis与数据库数据不一致的情况。

            2、写数据

            写数据流程一般操作流程可以分为以下4种:

            1. 先更新缓存再更新数据库。

            2. 先删除缓存再更新数据库。

            3. 先更新数据库再更新缓存。

            4javascript. 先更新数据库再删除缓存。

            根据http://www.devze.com以上4种流程分析,可以明确出两个问题,一个是缓存是更新还是删除,另外一个是先操作数据库还是先操作缓存呢。

            2.1、缓存是更新还是删除

            推荐使用删除缓存。因为缓存的更新成本太高。由于大多数情况下数据并不是直接写入缓存的,需要经过一系列复杂的计算再写入缓存的。若采用更新方式,那么每次写入数据库后,都需计算写入缓存的值,无疑是浪费性能的。删除缓存操作简单,副作用只是增加了一次cache miss,建议使用删除策略。

            2.2 先操作数据库还是先操作缓存

            2.2.1 先操作缓存

            先操作缓存的流程如下:

            Redis与数据库数据一致性的原因及解决方案

            先操作缓存的流程,就是先将缓存中数据删除,再更新数据库。

            数据不一致

            在读写并发操作的情况下,如何出现的数据不一致的问题呢。先看下并发流程:

            Redis与数据库数据一致性的原因及解决方案

            1. 线程1发起修改数据请求,会进行删除缓存操作。

            2. 接着更新数据库时出现了网络延迟。

            3. 线程1由于网络延迟还未对数据库进行修改,此时线程2执行查询请求,会去缓存中查询数据android

            4. 线程2在缓存中未查询到数据,再去查询数据库。

            5. 线程2将查询到数据旧数据放到缓存中,并将数据返回。

            6. 线程1在线程2数据查询完成后,才对数据库进行了修改。

            在这个过程中就出现了redis与数据库数据不一致的问题,只有等redis中数据过期时间到了,才能将新数据更新到缓存中。

            2.2.2 先操作数据库

            先操作数据库的流程如下:

            Redis与数据库数据一致性的原因及解决方案

            先操作数据库的流程,就是先对数据库进行修改,再将缓存中的数据进行删除。

            数据不一致

            在读写并发操作的情况下,如何出现的数据不一致的问题呢。

            Redis与数据库数据一致性的原因及解决方案

            1. 线程1发起修改数据请求,先更新数据库。

            2. 线程2在线程1更新数据库期间,发起查询请求,从缓存中获取到旧数据(脏数据)。

            3. 线程1完成数据库更新后,删除缓存中的数据。

            在这个过程中出现了短暂的数据不一致,但redis和数据库数据是最终一致性的。所以推荐先操作数据库再操作缓存。

            通过上述原因分析,可以得出在并发的读写情况下,正常使用redis与数据库不管是先操作redis还是先操作数据库,可能都会数据不一致问题。

            注意:由于redis和数据库操作不是原子的,若在redis和数据库之间加锁是可以实现数据一致,但也违背了使用redis的初衷。

            二、解决方案

             在不考虑redis操作失败的情况下,保证redis与数据库数据一致性的解决方案有4种。

            1、延迟删除机制

            该机制是在数据库数据更新后,先延迟一段时间后再次删除缓存数据。线程1写请求,线程2查询请求,通过延迟双删机制保证redis与数据库数据一致性。

            Redis与数据库数据一致性的原因及解决方案

            通过(6)步延迟一段时间后再进行redis的删除,在并发读写情况下保证redis与数据库数据一致性。具体延迟多长时间,需评估项目读数据业务逻辑耗时(即线程2从数据库读取数据到更新缓存成功的时间)。确保查询请求结束,更新请求可以删除查询请求造成的缓存脏数据。

            2、binlog同步删除机制

            通过canal组件订对binlog日志进行订阅,模仿数据库的slave数据库的备份请求,使得redis缓存数据删除,保证redis与数据库数据一致性。

            Redis与数据库数据一致性的原因及解决方案

            通过上面两种方式,在并发读写的情况下保证redis与数据库数据最终一致性。但可能存在redis删除失败的情况,一旦出现就会有redis与数据库数据不一致的问题。只有等redis中数据过期时间到了,才能将新数据更新到缓存中。

            3、异步重试删除机制  

            一旦缓存删除失败,可以通过重试机制设置重试次数保证一定删除成功。如重试3次,三次操作都失败则记录日志并发送告警,通知技术人员进行人工介入处理。在高并发环境下,重试最好使用异步方式,可以通过MQ实现这种机制。

            Redis与数据库数据一致性的原因及解决方案

            通过(6)步延迟删除缓存数据时,删除时失败,缓存中存储的还是脏数据(旧数据)。线程1的应用作为producer异步发送需要删除key到MQ。线程1的应用监听MQ,重试删除操作。

            通过重试删除机制,可以能够保证redis缓存一定能删除成功,保证redis与数据库数据一致性。但这种方式对业务代码造成侵入,代码过于耦合。

            4、binlog解耦异步重试机制

            可以使用阿里巴巴开源框架canal来实现程序解耦。通过利用canal提供的Java客户端,监听canal通知消息。当java客户端(项目)收到binlog变化的消息时,完成对缓存的处理。

            Redis与数据库数据一致性的原因及解决方案

            数据库更新后,canal订阅binlog日志,将变更的数据发送消息通知给java客户端(spring boot项目)。java客户端执行延迟删除缓存,若删除失败,java客户端作为producer异步发送需要删除key的MQ消息进行重试。客户端监听MQ消息,执行重试删除缓存操作。

            三、总结

            通过上述分析我们知道造成redis与数据库数据不一致的问题主编程客栈要在于并发情况下,读写并发操作可能会出现这个问题。通过4中解决方案,能够很好的解决redis与数据库数据一致性问题。

            到此这篇关于Redis与数据库数据一致性的原因及解决方案的文章就介绍到这了,更多相关Redis与数据库数据一致性解决内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

            0

            精彩评论

            暂无评论...
            验证码 换一张
            取 消

            关注公众号