0
点赞
收藏
分享

微信扫一扫

【改进延时双删的一些思考】

dsysama 2022-01-31 阅读 78

改进延时双删的一些思考

延时双删的问题

延时双删也不能保证完全数据一致——第二次删除失败就可能不一致了。

我思考了一个方法可以保证始终数据一致。

改进方法

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 新增Redis 键 useCacheFlag = 1;
  2. 查询时,先查useCacheFlag,如果为 1,则查询缓存。否则查询 DB。如果useCacheFlag = 1,不更新缓存。

更新数据过程

  1. 在一个Redis事务中:删除缓存,并set useCacheFlag = 0。事务成功才下一步,否则一直重试。

  2. 修改 DB,在修改完成前,缓存都一直为空。此时查询全部走 DB,且useCacheFlag = 0时,不更新到缓存。即使 DB 更新失败也没关系,重试。

  3. 在一个 Redis 事务中,更新缓存,再设置useCacheFlag = 1。事务不成功一直重试。

整个过程 DB 和缓存数据都是一致的,不管更新 DB 失败,还是Redis 事务失败,数据都是始终一致的。Redis 事务失败可能只执行部分。且不会回滚。

异常情况

最坏的情况,应用服务器和 Redis服务器都可能宕机。
Redis 宕机,只可能导致查数据库,或一直重试,没问题。

应用如果宕机,在 1,2步完成之前宕机,都没关系。如果第二部完成了宕机,会导致一直查数据库,而缓存作废了,因为useCacheFlag = 0。

解决方法:
新增 Redis 变量 queryTime 记录数据库查询的时间

在查询数据库时,如果queryTime ==null,set Redis 变量 queryTime=本次查询的时间。
如果queryTime 不为空,就不更新queryTime。

比较 queryTime 和 当前时间,超过 3 分钟(根据业务时间调整),认为缓存废弃已经时间过长,重新开始使用缓存:
此时 在一个Redis 事务中
1、先更新 DB 查询值到缓存
2、set useCacheFlag = 1
3、并清空queryTime
如果失败,重试

以上思路如果问题,请帮忙指出!感谢!

举报

相关推荐

0 条评论