如何保证Redis缓存与数据库的双写一致性

面试当中总会被问到如何保证 Redis 缓存和数据库一致性?但依旧有很多的疑问:到底是更新缓存还是删除缓存?到底选择先更新数据库,再删除缓存,还是先删除缓存,再更新数据库?

什么是缓存双写不一致

当更新完数据库之后,为了保障缓存的有效性,要及时更新缓存中的信息。 当多个线程同时对缓存和数据库进行更新操作时,就可能会出现缓存和数据库双写不一致的问题。即数据库和缓存的更新结果数据不一致。

双写不一致的详细情况

  • 并发读写导致的不一致,如A线程查询完数据库,结果在更新缓存操作之前卡顿了,此时另B线程对数据库做了更新操作,然后A程继续执行更新缓存的操作,就会出现缓存不一致的问题,前面执行的线程更新的数据和当前数据库存在的数据不一致。

  • 并发写导致的不一致,当AB两个线程同时对数据库和缓存进行写入操作的时候,如果A线程在更新完数据库,准备更新缓存的时候卡顿了,此时B线程也执行了一次更新数据库和缓存的操作。然后B线程执行完毕之后,A线程继续了更新缓存的操作。最终结果是缓存的数据是来自A线程,数据库中的数据来自B线程,此时并发写造成了缓存和数据的双写不一致。

解决方案

  • 对于并发几率很小的数据(如个人维度的订单数据,用户数据)。这种就不用考虑这个问题,很少会发生缓存不一致。可以给缓存数据加上一个过期时间,每个一段时间触发一次读的主动更新操作。

  • 并发写不一致可以采用先更新数据库再删除缓存的方式,删除是幂等操作(对于分布式系统是一个非常好的特性),多线程请求Update,可能由于不可预知的原因,导致数据脏写,造成数据不一致;删除简单:简单优于复杂,不需要考虑加锁。

  • 并发读写情况导致的数据库和缓存不一致的问题,可以采用延时删除的策略,但是这种策略也避免不了某些特殊的情况。即如果延时删除的时间不够,那么也会出现和上图一致的情况。

  • 为了防止小概率被其他读线程在当前写线程删除缓存之后,缓存旧的数据,可以采用在删除缓存数据之后睡眠一段时间再次进行删除,保证其他读线程更新的旧的缓存数据也失效。这种方案也完全解决不了上述不一致的问题,可能会出现线程死亡等情况。这种方案睡眠也会带来一定的性能问题。

  • 可以通过加上分布式读写锁保证并发读写或者写写的时候按着顺序排好队。读读的时候相当于无锁。

  • 也可以用阿里开源的canal通过监听数据库的binlog日志及时去修改缓存,但是引入中间件会增加系统的复杂度。

最终有效的解决方案

针对缓存双写不一致问题的解决方案,具体问题具体分析,没有完美的,只有适合的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值