redis缓存、数据库双写不一致

Cache Aside Pattern模式

读的时候

先读缓存,缓存没有的话,再读取数据库,然后取出数据后放入缓存,同时返回响应

更新的时候

删除缓存,然后再更新数据库(之所以删除缓存而不是更新,其实是一个懒加载的思想,避免频繁更新,降低开销,同时也可以避免更新缓存成功后在更新数据库时异常带来的问题)

缓存、数据库双写不一致

场景1: 先修改数据库,再修改/删除缓存,如果修改/删除缓存失败了,导致数据库中是新数据,缓存中是旧数据,数据出现不一致

解决思路

删除缓存,再修改数据库,如果修改数据库失败,那么数据库中是旧数据,缓存中是空的,也不会存在不一致的问题(因为读的时候缓存没有会去数据库中读取,然后更新到缓存中)

场景2: 在更新一个库存同时在读取库存的缓存时,由于并发此时出现数据库和缓存数据不一致的问题。例如库存初始为100,同时发生修改库存和查询库存两个请求,最终导致缓存中库存为100,数据库中库存为99,如下图:

Mon 06 Mon 13 Mon 20 删除缓存 数据库更新为99 缓存中不存在 数据库为100 缓存中为100 修改库存 查询库存

解决思路

  • 延时双删,更新完数据库之后,再sleep一段时间,然后再次删除缓存
  • 程序中维护相应的内存队列,将请求按照一个标识值放到队列里,进行串行化操作
  • 采用redis设置写锁同时设置失效时间避免死锁
  • 使用zookeeper分布式锁

个人觉得如果系统不是严格要求缓存+数据库数据一致性的话,最好不要采用后面这三种方案,因为核心思路都是请求串行化,会导致系统吞吐量大幅度降低

总结

针对缓存不是更新,而应该是删除。删除缓存有两种方式:

  • 先删除缓存,再更新数据库。解决方案是使用延迟双删
  • 先更新数据库,再删除缓存。解决方案是消息队列或者数据库binlog同步,需要注意的是引入消息队列会增加系统复杂性,不推荐直接使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值