掌握分布式环境缓存更新策略,提高缓存与数据库数据一致性

概述

随着时代的发展,服务系统架构也已经由最初的单体架构转变为分布式、微服务架构模式。
从数据体量上来看,各系统存储的数据量越来越大,数据的查询性能越来越低。
此时,就需要我们不断的进行优化,最常用的就是引入缓存。
而引入缓存后,我们如何保证缓存和数据库的一致性呢?

常见策略模式

常见更新策略有Cache Aside (旁路缓存)、Read/Write Through (读穿 / 写穿)、Write Behind/Back(写回)三种模式,
其中旁路缓存是目前应用最广泛的一种方式。

Cache Aside (旁路缓存)

  • 失效:应用程序先从cache取数据,没有获取到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让当前缓存失效

举例

是不是Cache Aside这个就不会有并发问题了?

不是的,比如,一个是读操作,但是没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,
然后,之前的那个读操作再把老的数据放进去,所以,会造成脏数据。

为什么这种思路存在这么明显的问题,却还具有那么广泛的应用呢?因为这个case实际上出现的概率非常低,产生这个case需要具备如下4个条件

  1. 读操作读缓存失效
  2. 有个并发的写操作
  3. 写操作比读操作更快
  4. 读操作早于写操作进入数据库,晚于写操作更新缓存

而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存。
所有的这些条件都具备的概率基本并不大。并且即使出现这个问题还有一个缓存过期时间来自动兜底。

为什么删除而不是更新缓存

现在思考一个问题,为什么是删除缓存,而不是更新缓存呢?
删除一个数据,相比更新一个数据更加轻量级,出问题的概率更小。

在实际业务中,缓存的数据可能不是直接来自数据库表,也许来自多张底层数据表的聚合。
比如商品详情信息,在底层可能会关联商品表、价格表、库存表等,如果更新了一个价格字段,
那么就要更新整个数据库,还要关联的去查询和汇总各个周边业务系统的数据,这个操作会非常耗时。

从另外一个角度,不是所有的缓存数据都是频繁访问的,更新后的缓存可能会长时间不被访问,
所以说,从计算资源和整体性能的考虑,更新的时候删除缓存,等到下次查询命中再填充缓存,是一个更好的方案。

系统设计中有一个思想叫 Lazy Loading,适用于那些加载代价大的操作,删除缓存而不是更新缓存,就是懒加载思想的一个应用。

Read/Write Through (读穿 / 写穿)

在这种情况下,应用程序将缓存视为主数据存储。应用程序不再和数据库交互,而是由缓存和数据库交互,相当于更新数据库的操作由缓存自己代理了。

  • 失效:应用程序先从cache取数据,没有获取到,则cache从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据更新到缓存中,还将数据更新到数据库。

Read Through

当应用程序向缓存询问数据时,例如键X,并且X尚未在缓存中,
,缓存会从数据库中源加载X。

Write Through

Write Behind/Back(写回)

在这种缓存策略中,先更新缓存,然后在设定的一段时间后异步更新数据库。
此策略特别适合写多的场景,因为发生写操作的时候, 只需要更新缓存,就立马返回了。
Write-behind缓存提高了系统性能,因为用户(通常)不必等待对数据库的更改,但是异步机制会增加数据延迟不一致的风险。

结语

总结

三种缓存模式优缺点:

Cache Aside 更新模式实现起来比较简单,但是需要维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。

Read/Write Through 更新模式只需要维护一个数据存储(缓存),但是实现起来要复杂一些。

Write Behind Caching 更新模式和Read/Write Through 更新模式类似,区别是Write Behind Caching 更新模式的数据持久化操作是异步的,
但是Read/Write Through 更新模式的数据持久化操作是同步的。

参考文章

https://coolshell.cn/articles/17416.html
https://www.cnblogs.com/xiaolincoding/p/16493675.html

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
使用分布式缓存时,可以采取以下方法来保证数据的读写一致性: 1. 缓存更新策略:在进行写操作时,需要及时更新缓存中的数据。可以通过以下几种策略来实现: - Cache-Aside(旁路缓存):在写操作时,先更新数据库,然后再手动更新或使缓存失效,下次读取时从数据库中获取最新数据并放入缓存。 - Write-Through(直写缓存):在写操作时,先更新数据库,然后再直接更新缓存中的数据。 - Write-Back(回写缓存):在写操作时,先更新缓存中的数据,然后异步或定期批量将更新数据写回数据库。 2. 缓存失效策略:为了保证数据一致性,需要在写操作时及时使缓存失效,以便下次读取时从数据库中获取最新数据。可以根据业务需求和数据更新频率设置合适的缓存失效时间或手动使缓存失效。 3. 分布式锁:在某些场景下,如果多个客户端同时进行写操作,可能会导致数据不一致。可以使用分布式锁来保证只有一个客户端能够进行写操作,从而保证数据一致性。常见的分布式锁实现包括基于数据库的悲观锁、基于缓存的乐观锁、分布式锁服务(如ZooKeeper、Redisson)等。 4. 缓存预热:在应用启动时,可以预先加载一部分热点数据缓存中,以提高访问性能并减少对数据库的压力。这样可以保证初始时缓存中的数据数据库数据保持一致。 5. 监控和报警:通过监控缓存的命中率、失效率、更新频率等指标,可以及时发现和解决缓存读写一致性的问题。同时设置合适的报警机制,以便快速响应并解决潜在的问题。 需要根据具体业务场景和系统需求选择适合的缓存策略和技术,并综合考虑性能、一致性和可用性等方面的权衡。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

merlin.feng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值