面试题-redis缓存与数据库一致性问题

问题

不管是先写库,再删除缓存;还是先删缓存,再写库,都有可能出现数据不一致的情况

因为写和读是并发的,没法保证顺序,如果删了缓存,还没有来得及写库,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。如果先写了库,再删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。 如果是redis集群,或者主从模式,写主读从,由于redis复制存在一定的时间延迟,也有可能导致数据不一致。

thread-A  thread-B操作相同数据

thread-A  redis del(dataA)
thread-A  mysql update(dataA)
thread-B  redis del(dataB)
thread-B  mysql update(dataB)
thread-B  redis set(dataB)
thread-A  redis set(dataA)

此时缓存最终的结果 是 dataA,但是按照hread-A  thread-B执行顺序,正确结构应该是dataB,这种场景下就需要我们考虑进行双写一致性.

 

解决方案

串行化 我们利用MQ将所有“读数据库” + “写缓存”的步骤串行化。第一步先读缓存,如果缓存没读到,则去读DB,之后再异步将数据标识写入MQ(这里MQ与写流程的MQ是同一个),接下来就消费MQ,解析MQ消息来读库获取相应的数据刷新缓存。

双删加超时 在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。这样最差的情况是在超时时间内存在不一致,当然这种情况极其少见,可能的原因就是服务宕机。此种情况可以满足绝大多数需求。

使用canal解析binlog Mysql通过binlog同步redis  https://blog.csdn.net/u010743397/article/details/97258672

 

双删一致性

thread-A  redis del(dataA)
thread-A  mysql update(dataA)
thread-A  sleep(200ms)
thread-A  redis del(dataA)
thread-A  redis update(dataA)

1、先淘汰缓存,更新数据库

2、延时200ms

3、再次淘汰缓存,从数据库更新最新的数据缓存

这个200ms具体该休眠多久根据自己的项目的读写数据业务逻辑的耗时而定。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值