Redis分布式锁超时 导致多个任务获取锁的解决思路?

问题描述

使用Redis集群分布式锁, 并利用超时自动释放(某些原因线程死掉后依赖超时)

但是 如果一个服务a的线程A获取了LockC锁,由于网络原因, 获取锁后断网(线程A没挂,也许只是阻塞了,也没处理完)
Redis集群到了超时时间LockC被释放了

此时另一个服务b的线程B获取了LockC锁,且往下执行(假设B线程跟A处理的结果有交叉)

但过了一会, 服务a的网络又好了, 线程又继续执行,就出现了不一致问题

请问有什么思路么?


MMMHUHU
浏览 1891回答 2
2回答

qq_遁去的一_1

如果数据源处不进行修改(比如增加版本号控制),那么没有任何解决方案。因为不光网络问题。gc的stw阶段,或者page fault导致的阻塞你也是没办法控制的。即使随时随地去判断锁的状态,你仍然没办法去确定判断完后,是否会进入一次gc或者page fault。redis锁的问题在于,超时后会自动释放锁。所以可以考虑使用zk的锁,zk是基于session的锁,不会有超时时间,只会在session关闭后释放(但是仍然无法防止长时间gc导致zk检测不到心跳导致的过期)。总结来说就是,如果只是考虑到效率,而允许某些情况下同时存在两个进程获取锁,那么使用redis锁没有任何问题;如果需要正确性,那么redis的锁不是一个很好的实现,zk的锁是一个更好的思路,但是仍然存在问题,更好的方式是,数据源处进行修改,增加版本控制或者某些程度上事务(ACID)的支持(这就引入了既然数据源处已经支持了锁,我们还需要分布式锁干什么这个问题,你可以思考一下这里);如果对效率不是那么看中,比如一些异步处理,那么甚至可以用队列+单线程消费者去处理,天然的免锁。

慕盖茨4494581

在 a 碰到网络异常等情况并恢复后可以判断自己是否还是锁的持有者,如果不是则抛出异常不继续执行。同理在是否锁的时候也需要关注释放异常的情况。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java