缓存与数据库的一致性
缓存与数据库的一致性
一般而言,缓存都需要设置过期时间,通过缓存过期实现缓存与数据库的数据一致性是最后的兜底策略。
然后根据更新数据库的先后和是更新还是删除缓存做排序,有以下四种情形。
一般是使用更新数据库,删除缓存,当然都还是有并发问题的。
- 更新缓存,更新数据库
- 如果更新数据库失败,那么其实操作还没执行成功,缓存最终还是会变回旧数据
- 如果缓存不是会被经常读取,那么这个缓存就会占用空间,还可能浪费计算资源
- 删除缓存,更新数据库
- 同样有更新数据库失败问题
- 更新数据库,更新缓存
- 同样有更新缓存问题
- 更新数据库,删除缓存
- 以数据库更新是否成功为准
- 删除缓存,减少了空间占用和计算
- 如果删除缓存失败,只能通过过期更新
删除缓存导致缓存击穿
- 机器不多,可以只用本地锁
- 机器多,需要上分布式锁
解决并发更新缓存
- 双删除:删除缓存->更新数据库->延迟一段时间->删除缓存。
这个延迟一段时间,第一是等待那些读到旧值的线程完成缓存的写入,第二可以等待mysql主从同步
解决删除缓存失败
- 本地重试:但是如果是网络问题,短时间内的网络重试没什么意义
- MQ异步重试:本地删除失败了,通过MQ的消费服异步删除,只有在redis和MQ同时故障的时候才行不通
- Mysql的binlog异步删除:通过一个服务解析binlog,去删除相应的缓存
强一致性
强一致性方案当然可以解决并发更新缓存问题。
- 分布式读写锁:让读线程等待写线程完成写入。
读多写少可能还好,读少写多的缓存没啥作用,可能要考虑是不是要去掉缓存
参考文章:
缓存与数据库的一致性
https://cellargalaxy.github.io/posts/分布式/7.缓存与数据库的一致性/