redis分布式锁的实现

分布式 | 2020-06-21 17:48:24 | 阅读 341 次 | 评论(0)

1.在使用Redis的分布式集群的时候,我们进行操作的时候需要对抢锁,也就是对线程的操作权限

我们在Redis中可以使用SetNX命令来进行锁争抢。

sexnx(Key,value),其中的key指的是锁的唯一标识,value姑且为1。

当锁抢成功,返回1则代表锁争抢成功。当然,我们接下来需要给锁一个有效时间,否则如果宕机的时候,进程挂掉,这个锁就一直不被释放,导致资源被占用。

所以我们可以设置过期时间expire(30).

有一个问题,因为争抢锁和设置过期时间的操作是分开的,所以在极端情况下,可能会出现抢到了锁,但是没有设置过期时间(在抢锁和设置过期时间之间服务器宕机)。也会发生资源一直被占用。

所以我们需要确保我们的抢锁和设置过期时间的操作是原子性的(其实就是transaction)。

所幸,我们可以使用set(key,value,expire,NX)来进行锁争抢。

锁的争抢完成了。那么我们在写代码的时候,有必要使用代码在任务完成之后删除当前锁。这就可能出现锁误删。

所以我们需要做判断,判断当前锁是否就是自己的那个线程中的锁。(保存线程ID可以使用抢锁时候的value)。

当线程A抢锁之后设置了30S的过期时间,但是他的任务用时可能45S,在30S的时候,锁过期了。线程B抢到了锁,在B执行的过程中,A任务执行完了,他就会删除锁,此时就会把B的锁删掉。这是不可以的

但是这个不是原子性的。此时需要保证删除锁的操作也是原子性。

但是无论在什么情况下情况下,同一时间有多个线程在访问同样的代码块,这是我们不允许的。所以我们需要保证这个锁,要在任务时间内,不能被释放掉。所以我们需要开启一个守护线程。

开启一个守护线程,在我们的锁快要过期的时候,我们需要对锁进行续期,比如当剩下了1S的时候,我们可以再次设置过期时间为10S,一直循环往复。直到代码自己删除锁。

守护线程的实现是-->争抢到所以后,开启一个本地队列Task,去轮询这个Key(间隔N秒去检查这个Key的过期时间,然后根据需要去对锁进行续时),直到代码释放锁。

文章评论,共0条
游客请输入验证码
浏览40968次
最新评论