博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么你的缓存更新策略是先更新数据库后删除缓存,讲讲其他的情况有什么问题?...
阅读量:5975 次
发布时间:2019-06-19

本文共 1237 字,大约阅读时间需要 4 分钟。

hot3.png

问题:怎么保持缓存与数据库一致?

要解答这个问题,我们首先来看不一致的几种情况。我将不一致分为三种情况

  1. 数据库有数据,缓存没有数据;
  2. 数据库有数据,缓存也有数据,数据不相等;
  3. 数据库没有数据,缓存有数据。

在讨论这三种情况之前,先说明一下我使用缓存的策略,也是大多数人使用的策略,叫做 Cache Aside Pattern。酷壳里的 缓存更新的套路 一文,很值得一读,我的策略也是从他那学来的。 简而言之,就是

  1. 首先尝试从缓存读取,读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。
  2. 需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。

因为:

  1. 读的逻辑大家都很容易理解,谈谈更新。如果不采取我提到的这种更新方法,你还能想到什么更新方法呢?大概会是:先删除缓存,然后再更新数据库。这么做引发的问题是,如果A,B两个线程同时要更新数据,并且A,B已经都做完了删除缓存这一步,接下来,A先更新了数据库,C线程读取数据,由于缓存没有,则查数据库,并把A更新的数据,写入了缓存,最后B更新数据库。那么缓存和数据库的值就不一致了。

  2. 另外有人会问,如果采用你提到的方法,为什么最后是把缓存的数据删掉,而不是把更新的数据写到缓存里。这么做引发的问题是,如果A,B两个线程同时做数据更新,A先更新了数据库,B后更新数据库,则此时数据库里存的是B的数据。而更新缓存的时候,是B先更新了缓存,而A后更新了缓存,则缓存里是A的数据。这样缓存和数据库的数据也不一致。

按照我提到的这种更新缓存的策略,理论上也是有不一致的风险的,酷壳的文章有提到,只不过概率很小,我们暂时可以不考虑,后面我们有其他手段来补救。 讨论完使用缓存的策略,我们再来看这三种不一致的情况。

  1. 对于第一种,在读数据的时候,会自动把数据库的数据写到缓存,因此不一致自动消除
  2. 对于第二种,数据最终变成了不相等,但他们之前在某一个时间点一定是相等的(不管你使用懒加载还是预加载的方式,在缓存加载的那一刻,它一定和数据库一致)。这种不一致,一定是由于你更新数据所引发的。前面我们讲了更新数据的策略,先更新数据库,然后删除缓存。因此,不一致的原因,一定是数据库更新了,但是删除缓存失败了。
  3. 对于第三种,情况和第二种类似,你把数据库的数据删了,但是删除缓存的时候失败了。

因此,最终的结论是,需要解决的不一致,产生的原因是更新数据库成功,但是删除缓存失败。 我想出的解决方案大概有以下几种:

  1. 对删除缓存进行重试,数据的一致性要求越高,我越是重试得快。
  2. 定期全量更新,简单地说,就是我定期把缓存全部清掉,然后再全量加载。
  3. 给所有的缓存一个失效期。

第三种方案可以说是一个大杀器,任何不一致,都可以靠失效期解决,失效期越短,数据一致性越高。但是失效期越短,查数据库就会越频繁。因此失效期应该根据业务来定。

转载于:https://my.oschina.net/u/3691499/blog/3027645

你可能感兴趣的文章
2018年尾总结——稳中成长
查看>>
通过jsp请求Servlet来操作HBASE
查看>>
Shell编程基础
查看>>
Shell之Sed常用用法
查看>>
Centos下基于Hadoop安装Spark(分布式)
查看>>
mysql开启binlog
查看>>
设置Eclipse编码方式
查看>>
分布式系统唯一ID生成方案汇总【转】
查看>>
并查集hdu1232
查看>>
Mysql 监视工具
查看>>
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
博客搬家了
查看>>
Python中使用ElementTree解析xml
查看>>
linux的日志服务器关于屏蔽一些关键字的方法
查看>>
mysql多实例实例化数据库
查看>>
javascript 操作DOM元素样式
查看>>
HBase 笔记3
查看>>
【Linux】Linux 在线安装yum
查看>>
Atom 编辑器系列视频课程
查看>>
[原][osgearth]osgearthviewer读取earth文件,代码解析(earth文件读取的一帧)
查看>>