缓存双写一致性的套路

对于缓存可能很多小伙伴会有疑问,到底是更新缓存还是删除缓存? 到底是先更新数据库,再删除缓存,还是先删除缓存,再更新数据库?>

这篇文章主要分享为了达到最终一致性,针对不同的场景,一些更新缓存的套路。

Cache Aside Pattern(旁路缓存模式)


适用于读多写少的场景,应该是目前最常用的方式。

实现逻辑

  • 读请求中,先请求缓存,若缓存命中,则直接返回缓存中的数据;若缓存未命中,则查询数据库并将查询结果更新至缓存,然后返回查询出的数据。

  • 写请求中,先更新数据库,再删除缓存。

在这种方式中,读请求很好理解,相信大部分小伙伴都是这么做的。而对于写请求相信会有不同的看法,为什么不是更新缓存?

如果是更新缓存,在并发的情况下,线程A写请求,先去更新了数据库。此时,线程B也是写请求进来更新了数据库,然而线程A因为某些原因没还去更新缓存(网络延迟等)。线程B先完成了更新缓存,线程A才完成了更新缓存。这时缓存中是线程A的旧数据,数据库中是线程B的新数据。

删除缓存就没有并发问题了吗,还是有,但是出现的概率非常小

有人会问如果删除缓存失败呢,对于这种情况那就需要采取一定的补偿机制,例如通过引入消息队列,将删除失败的缓存对应的 key 放入消息队列中,在对应的消费者中获取删除失败的 key ,异步重试删除等。

Read/Write Through Pattern


Read-Through(读穿透模式)

实现逻辑

对比Cache Aside Pattern 模式中读请求,不同点在于 Read-Through 中多了一个缓存服务,访问控制层。Cache Aside 是由调用方负责把数据加载入缓存,而Read-Through 则是通过缓存服务来完成缓存层及持久化层交互

Write Through(直写模式)

实现逻辑

对比Cache Aside Pattern 模式中写请求,Write-Through 除了多了一个访问控制层,还由之前的删除缓存变成了更新缓存,那就会出现上面的并发问题。Write-Through 直写模式适合写操作较多,并且对一致性要求较高的场景,在应用 Write-Through 模式时,也需要通过一定的补偿机制来解决它的问题。

Write-Behind(异步回写模式)


实现逻辑

可以看到Write-Behind 也有一个访问控制层,最大的区别在于该模式在更新数据的时候,只更新缓存,不更新数据库,然后通过缓存会异步地批量更新数据库数据。基于这种实现方式,数据库和缓存的一致性较弱,而且可能会丢失数据。但是异步更新数据库,我们可以合并同一数据的多次操作去更新,减少了I/O交互,减轻了数据库的压力,具有较好的吞吐性,显然这种方式适用于大量写操作的场景。

总结

对于解决缓存双写一致性问题,我们最好是按照已有的套路来解决,毕竟是经过大量验证的。当然对于具体选用哪种模式,需要结合实际业务场景来考虑,不同的模式,存在不同的优缺点,缺点我们可以通过额外的机制来处理(设置缓存过期时间,补偿机制等)。

相关推荐
hie988945 分钟前
基于matlab策略迭代和值迭代法的动态规划
算法·动态规划
Coovally AI模型快速验证8 分钟前
SFTrack:面向警务无人机的自适应多目标跟踪算法——突破小尺度高速运动目标的追踪瓶颈
人工智能·神经网络·算法·yolo·计算机视觉·目标跟踪·无人机
Brduino脑机接口技术答疑9 分钟前
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
人工智能·算法·脑机接口·新手入门
想用offer打牌14 分钟前
面试官拷打我线程池,我这样回答😗
java·后端·面试
真的很上进19 分钟前
2025最全TS手写题之partial/Omit/Pick/Exclude/Readonly/Required
java·前端·vue.js·python·算法·react·html5
用户69452955217022 分钟前
国内开源版“Manus”——AiPy实测:让你的工作生活走上“智动”化
前端·后端
重庆小透明25 分钟前
【从零学习JVM|第三篇】类的生命周期(高频面试题)
java·jvm·后端·学习
linweidong25 分钟前
GO 基础语法和数据类型面试题及参考答案(下)
算法·后端面试·泛型·go面试·go面经·go求职
haciii1 小时前
深入理解数据库隔离级别与Spring Boot事务管理
spring boot·mysql
寻月隐君1 小时前
Rust + Protobuf:从零打造高效键值存储项目
后端·rust·github