缓存双写一致性的套路

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

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

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交互,减轻了数据库的压力,具有较好的吞吐性,显然这种方式适用于大量写操作的场景。

总结

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

相关推荐
追逐时光者2 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_2 小时前
敏捷开发流程-精简版
前端·后端
苏打水com2 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
学Linux的语莫3 小时前
机器学习数据处理
java·算法·机器学习
earthzhang20213 小时前
【1007】计算(a+b)×c的值
c语言·开发语言·数据结构·算法·青少年编程
西瓜er3 小时前
JAVA:Spring Boot 集成 FFmpeg 实现多媒体处理
java·spring boot·ffmpeg
间彧3 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧3 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧3 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧3 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端