Skip to content

业务背景

在数据库的上层引入缓存,可以提高服务性能。但是由于一些原因,会出现缓存和数据库中的数据不一致。

  • 并发操作缓存,旧数据覆盖了新的缓存
  • 服务异常宕机,未及时更新缓存

一致性?

  • 强一致性:数据更新实时生效,性能较低
  • 弱一致性:数据更新延迟生效,性能较高

Cache-Aside Pattern

也叫边缘缓存模式;

另外有个 Read/Write Through,和上述的区别是增加了 Cache Provider,屏蔽了程序与数据库之间的交互细节。

问:写请求为什么是删除缓存,而不是更新呢?

当更新数据库和更新缓存最终顺序不一致,就会更新脏数据到缓存中。

问:写请求为什么是先更新数据,而不是先删除缓存呢?

当 A 的请求处在 B 删除缓存和更新数据库两个操作的中间,就会写入脏数据到缓存中。

延时双删

Cache Aside Pattern也不能完全保证一致性;

当更新数据库和删除缓存,刚好在查询数据写入到缓存的中间,那么由于数据库已经更新,写入缓存的就是脏数据。

出现的概率较低。通常查询耗时都比更新耗时短,而且还要考虑缓存命中率。

业界给出的方案是延时双删策略,尽可能保证一致性(延时时长)。

可以异步延时删除缓存提高性能(延时队列)

binlog(MySQL)

如果数据库用的MySQL,那么可以基于binlog机制异步删除缓存。阿里的开源组件canal非常适合这个场景,采集数据的变化发送到消息队列中,无业务代码侵入

总结

  • 强一致性会损耗性能,通常采用最终一致性
  • 重试应对失败场景,通常会基于消息队列做异步重试
  • 少即是多,非必要情况下不需要应用增加系统复杂度

参考

基于 MIT 许可发布