缓存更新的另一种方法:双删策略
上一篇说到缓存的更新操作是非幂等操作,会出现并发更新的问题。那用缓存删除操作实现缓存更新行不行,您可能觉得奇怪,删除了缓存如何更新,假设读业务先读取缓存,如果发现没有就回溯到读数据库找数据,然后再更新回缓存。这种方式叫做懒加载,是在查询到数据库时,主动更新缓存。就是说删除同样能达到更新缓存的目的,为什么要用删除,因为删除操作是没状态的,无论删除多少次,它的结果都是一样的,所以是天然的幂等操作。现在问题转移到,如何在数据更新或添加时保证缓存清除干净的问题。
删除是幂等操作,直接删除不就行了吗,为什么还要保证缓存清除干净。因为懒加载的方式,也有缓存更新操作,如果写业务在更新数据库前删除缓存,还没更新完数据,此时读业务请求过来发现没有缓存,懒加载读到旧数据更新缓存,这样缓存里还是脏数据。既然不能在更新数据之前删除,那就在更新数据之后删除,但是在更新完数据库后,删除缓存失败了,怎么办,缓存里仍然是旧数据。所以要在更新数据库前后都删除缓存,这个就是缓存双删策略。
![0](https://img2022.cnblogs.com/blog/2978104/202209/2978104-20220911233313813-680061302.png)
前一个删除为了减少后一个缓存删除失败的概率,后一个删除是防止读业务懒加载读到旧数据更新缓存。但是如果后一个缓存删除失败怎样处理,有两种解决办法,一是在更新缓存时,给缓存设置过期时间,失效了会重新懒加载,最坏情况是在超时间内数据不一致,但最终还是一致的。二是业务层重试,写入消息队列,不断重试删除操作,直到成功。
存在一种极端情况,在删除缓存之后,更新数据库之前,有一个读业务获取了数据库旧数据,又在第二次缓存删除之后更新了缓存,这时缓存也会出现脏数据。这种情况要延迟第二次缓存删除,保障在脏数据写入后删除,那怎样延迟,延迟时间又不确定,如何做到万无一失,答案是做不到的,但是可以通过消息队列异步删除,达到延迟删除的目的,降低脏数据写入的概率。
用了缓存双删策略,那数据库前面没了缓存层,高并发访问下顶不住,就必须处理缓存穿透、击穿、雪崩等问题。下篇文章将讲讲缓存问题的相关处理方法