缓存不一致问题
缓存更新的4种策略
-
1.给缓存设置过期时间。这样缓存和数据库能保持最终一致性。
-
2.先更新数据库,再更新缓存。问题:1.线程A更新了数据库,线程B再更新了数据库。线程B更新了缓存,线程A更新了缓存。最终结果是缓存以线程A更新的为准,数据库以线程B更新的为准,出现了不一致。2.更新了数据库就去更新缓存,实际上可能这些缓存不是热点数据,且这些缓存需要复杂的计算生成,浪费了性能。3.更新了数据库,然后更新缓存的时候程序出问题了中止了,那么也会造成数据不一致问题。
-
3.先删除缓存,再更新数据库。问题:同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:(1)A进行写操作,删除缓存(2)B查询发现缓存不存在(3)B去数据库查询得到旧值(4)B将旧值写入缓存(5)A将新值写入数据库。
解决方案:延时双删除,伪代码如下
public void write(String key,Object data){
redis.delKey(key);
db.updateData(data);
// 延时一秒的目的是,让读线程B更新完缓存,线程A再去删除。
Thread.sleep(1000);
redis.delKey(key);
}
- 4.先更新数据库,再删除缓存。
假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生
(1)缓存刚好失效
(2)请求A查询数据库,得一个旧值
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存
延时删除可以解决这个问题,即让读线程把业务走完再去删除。
删除也可能有失败的情况,需要启用重试机制。
删除失败后,丢入消息队列,由另外的线程从队列中获取去删除。