Redis缓存一致问题(延迟双删)

今天遇到一个线上问题,很有意思,也很难得。之前就有学习到一致性的解决问题,今天终于来了一个上线案例了,好在并发场景并不得多。~~

场景:

拼车子单再确认接单的过程中,会生成对应司机的形成单号,并最终落库。落库的时候,用到了Redis实现的延迟双删,保证缓存与数据库保持一致;另一个线程操作表中相同的记录行,记录该订单免抽佣。两个线程共用一把分布式锁。按道理看,一个线程执行完,保存数据,释放锁,另一个线程才会操作相同数据行,没什么问题。问题是还有一个线程3,简单画个图。

线程表格图
线程\时间轴(格子不能表示时间长短,只能表示时间顺序)ABCDEFGHIJKLM
线程1查缓存(无)查库(旧)存缓存(旧)返回数据
线程2获取分布式锁查库(旧)逻辑处理提交事务(新1)删除缓存释放分布式锁延迟删除缓存(200ms)
线程3获取分布式锁查缓存(旧)业务处理提交事务(新2)删除缓存释放分布式锁延迟删除缓存(200ms)

上述三个线程并发,主要问题是线程2更细数据库,并删除缓存后,线程1把旧的数据保存到缓存。导致线程3用旧的数据处理业务逻辑并保存到了数据库。

简单分析:

        线程2和线程3共享分布式锁,所以相互隔离,没有问题。问题出现在线程1的F列持有旧的缓存,更新进了Redis。在线程2延迟删除缓存没操作时,被线程3用到了缓存数据。多个线程并发操作一行数据的修改和缓存的存储就会有这个问题。

解决:

1.线程3查缓存(旧)改成查数据库。虽然并发问题是不可避免的,但是数据库事务为我们做了这些,考虑到每条订单记录修改量不大可以直接查库。

2.考虑到项目处理订单数据都是状态机processor中处理,也就是修改数据过程中都是持有分布式锁的。那么可以考虑释放分布式锁之前,手动把最新的数据放入缓存。

总结

        遇到问题还是要具体分析的,每一种解决方案都不是完美的,但每种解决方案都有最适合他的场景。上面我们选用的方案1。其中还可以考虑延迟删除缓存的时间,我们业务设置的200ms,这种想法只能缩小并发问题,不能根本上解决。

小伙伴可以多多评论,给我打开更多的思路,相互学习。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值