Redis高级系列-缓存双写一致性

Redis高级系列-缓存双写一致性

1. 什么叫做缓存双写一致性?

Redis缓存双写一致性是指在更新数据库数据后,同时更新缓存数据以保持数据一致性的策略,总的来说,就是写入redis写入数据库的数据要保持一致

2. 缓存双写一致性有那些解决方案?

2.1 Cache Aside Pattern(旁路缓存模式)

旁路缓存模式,字面意思理解:缓存是旁路,缓存相对与应用程序和数据库是旁路,应用程序可以直接绕过缓存访问数据库

在Cache Aside模式中,应用程序首先从缓存中读取数据,如果缓存中不存在,则从数据库中读取数据,并将数据写入缓存中。在更新数据时,应用程序首先更新数据库中的数据,然后删除缓存中的数据。当下一次请求到来时,应用程序会从数据库中读取最新的数据,并将其写入缓存中

那为什么要先更新数据库在删除缓存了?我们再看看几种更新策略

策略是否是多线程场景现象
先删除缓存再更新数据库删除缓存成功但数据库更新失败应用程序从数据库中读到旧值
缓存删除成功但数据库再更新中…有并发读请求并发读请求从数据库读到旧值,并回写到redis,导致后续都从redis读取到旧值
先更新数据库再删除缓存数据库更新成功,但缓存删除失败应用程序从redis读取到旧值
数据库更新成功,但缓存再删除中…有并发读请求并发读请求读取到旧值
先更新缓存再更新数据库更新缓存成功但更新数据库失败缓存和数据库数据不一致(不推荐,一般数据库作为兜底方案)
更新缓存成功但数据库再更新中缓存和数据库数据不一致(不推荐,一般数据库作为兜底方案)
先更新数据库再更新缓存更新数据库成功但缓存更新失败应用程序读取到旧值
更新数据库成功但缓存再更新中…有并发读请求并发读请求读取到旧值
延迟双删

经过我们对Cache Aside Pattern四种方案的八种场景进行仔细分析,我们大体上确定了先更数据库再删缓存的方案。但是这种方案也并不完美,假设我们更新数据库成功了,删除缓存失败了,那么同样会出现一致性问题。为了解决这种场景下的一致性问题,我们进一步引入了延迟双删方案来解决。

  • 为什么要做两次缓存删除呢?

从上图“延迟双删”中我们可以很清晰地看到,数据库的更新是在首次的缓存删除成功后进行的,这样就有效避地免了“先更数据库再删缓存”方案中可能出现的数据库更新成功缓存删除失败导致的一致性问题。第二次的缓存删除是为了避免在执行更新数据库操作完成之前其它线程读取数据库并更新缓存而导致的一致性问题。

  • 为什么第二次缓存删除又要延迟执行呢?

试想,如果我们不做第二次的延迟删除,而是更新数据库后立即删除会出什么问题?有没有可能其它读请求线程在更新数据库之前读取了数据,并在第二次立即删除缓存之后更新了缓存。很明显,延迟删除就是为了让可能存在的其它读请求线程尽可能地在更新完缓存后再执行缓存删除操作。这样一通操作后,数据库是最新的数据了,缓存里没有数据,后面的读请求线程又可以拿到数据库的最新数据写入缓存了。

  • 延迟删除具体需要延迟多长时间?

对于这个具体需要延迟多长时间,其实没有绝对的标准,唯一的标准就是根据读请求的耗时来确定,读请求越耗时,延迟时间越长。一般情况下我们设置的延迟时间为1秒。

重试删除

在上面的延迟双删方案中,如果我们思考,其实还是有诸多问题的。比如:在延迟双删的读写场景中,如果第二次缓存删除失败了,同样会出现一致性问题。那么删除失败了,重试几次不就好了吗?基于这个思想我们进一步引入了重试删除方案来解决

重试删除确实很大程度上解决了一致性问题,并且逻辑非常简单。唯一的不足可能就是需要引入消息队列,并且业务代码也会有一定的侵入。那么有没有既能够保证最终一致性,又能够解耦的方案呢?我们继续往下面看

binlog订阅异步删除

binlog订阅异步删除确实也能解决一致性问题,对代码也无任何侵入,但是整个架构复杂,中小项目一般都用不上。

2.2 Read Through/Write Through(读写穿透)

该策略又被称为读穿/写穿策略,和CacheAside策略的缓存数据与数据库数据为准不同,该策略的核心是用户只与缓存层交互(应用程序只与缓存或者中间层、缓存抽象层交互),由缓存层与数据库通信,写入或读取数据。

在读取数据时,通过缓存层进行读取,若缓存存在则直接返回,若不存在则由缓存层拉取数据库数据到缓存中并返回。
在写数据时,通过缓存层进行写入,若缓存存在则直接写入缓存中并同步到数据库,若不存在则写入数据库中。

使用场景

适用于读多写多的场景,数据一致性要求较高的场景。

2.3 Write Behind(后写或异步写)

Write Behind Caching是一种将缓存和数据库异步写入的缓存模式。在Write Behind Caching模式中,应用程序首先将更新操作写入缓存中,然后异步地将更新操作写入数据库中。当下一次请求到来时,应用程序会从缓存中读取数据,并将其写入数据库中。

使用场景

适用于写多读少的场景,数据一致性要求不高的场景

3. 总结

在使用Redis缓存时,应根据具体的业务场景和需求选择合适的缓存模式。Cache Aside模式简单易用,适用于读多写少的场景;Read/Write Through模式完全解耦缓存和数据库,适用于读多写多的场景;Write Behind Caching模式可以提高写入性能,适用于写多读少的场景。在实际应用中,可以根据具体的业务需求和性能要求,选择合适的缓存模式,以提高系统的性能和稳定性。

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis双写一致性是指在数据库与Redis缓存中同时进行写操作时,确保数据的一致性。在双写一致性中,存在几个常见的问题,包括缓存雪崩、缓存穿透和缓存并发竞争等。 缓存雪崩是指在某个时间点,大量缓存失效导致请求直接落到数据库上,造成数据库压力骤增。为了避免缓存雪崩,可以采用设置不同的过期时间或使用互斥锁机制来保证缓存的稳定性。 缓存穿透是指恶意或非法请求查询缓存中不存在的数据,导致大量请求落到数据库上,增加数据库的负载。为了解决缓存穿透问题,可以使用布隆过滤器等技术来过滤掉无效请求。 缓存并发竞争是指多个线程同时对同一个缓存进行写操作,可能导致数据不一致的问题。为了保证缓存一致性,可以采用延时双删策略,在写数据库之前删除一次缓存,在写完数据库后,间隔一段时间再删除一次缓存。这样可以增加缓存删除的可靠性和容错性。 另外,要保证Redis双写一致性,还可以通过配置Redis策略来进行优化和控制。根据实际情况选择合适的策略,例如使用缓存更新策略或读写分离策略等,以提高系统的性能和可靠性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [总结redis实战解决方案](https://download.csdn.net/download/zxfmamama/85931055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Redis缓存双写一致性问题](https://blog.csdn.net/wzngzaixiaomantou/article/details/126879335)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值