Redis分布式锁实现方案

一、什么是分布式锁,与本地锁有什么区别

本地锁: 解决同一进程内多个线程操作同一资源的问题。

分布式锁: 解决多个进程同时操作同一资源的问题。

二、Redis的SETNX

Redis之所以能实现分布式锁,得益于Redis的单线程处理模式,将并发请求转为队列模式,不用担心并发线程安全问题。

用 Redis 实现分布式锁的几种方案,我们都是用 SETNX 命令(设置 key 等于某 value)。只是高阶方案传的参数个数不一样,以及考虑了异常情况。

SETNXset If not exist的简写。意思就是当 key 不存在时,设置 key 的值,存在时,什么都不做。

redis-cli客户端,中设置成功则会返回OK,否则返回nil。

127.0.0.1:6379> set name 222 nx

OK

127.0.0.1:6379> set name 222 nx

(nil)

127.0.0.1:6379> del name

(integer) 1

127.0.0.1:6379> set name 222 nx

OK

三、实现方案

方案一:

 问题:  setnx占好位,业务代码异常或者程序在页面过程中宕机。没有执行删除锁逻辑,这就造成了死锁

解决: 设置锁的自动过期,即使没有删除,会自动删除。

方案二:

问题: setnx设置好,正要去设置过期时间,宕机。又死锁了。

解决: 设置过期时间和占位必须是原子的。redis支持使用setnx ex命令。

 方案三:

问题: 由于业务时间很长,锁自己过期了,直接删除,有可能把别人正在持有的锁删除了。

解决: 占锁的时候,值指定为uuid,每个人匹配是自己的锁才删除。

方案四:

问题: 在查询和删除锁之间,锁自动过期,将会把别人的锁误删掉。

解决 查询锁和删除锁必须保证原子性。使用redis+Lua脚本完成。

 方案五:

问题: 业务逻辑执行时间超过了默认的过期时间,锁被自动释放,导致多个线程同时持有锁的情况。

解决 Redisson看门狗的分布式锁。

 方案六:Redisson

Redisson是java中的一个工具包,这个包已经实现了上述的lua脚本执行保证原子性、锁的唯一标识判定等。除此之外,Redisson有一个看门狗机制,来自动对锁续期。

redisson在获取锁之后,会维护一个看门狗线程,在每一个锁设置的过期时间的1/3处,如果线程还没执行完任务,则不断延长锁的有效期。

那万一业务的机器宕机了呢?如果宕机了,那看门狗线程就执行不了了,就续不了期,到期将自动释放锁。

问题: 业务逻辑进入死循环,导致锁无法被释放。

解决 干死杠精!!。

四、前面redis分布式锁存在的问题

前面两种redis分布式锁的实现方式,如果从“高可用”的层面来看,仍然是有所欠缺,也就是说当 redis 是单点的情况下,当发生故障时,则整个业务的分布式锁都将无法使用。

为了提高可用性,我们可以使用主从模式或者哨兵模式,但在这种情况下仍然存在问题,在主从模式或者哨兵模式下,正常情况下,如果加锁成功了,那么master节点会异步复制给对应的slave节点。但是如果在这个过程中发生master节点宕机,主备切换,slave节点从变为了 master节点,而锁还没从旧master节点同步过来,这就发生了锁丢失,会导致多个客户端可以同时持有同一把锁的问题。

那么,如何避免这种情况呢?redis 官方给出了基于多个 redis 集群部署的高可用分布式锁解决方案:RedLock。官方也给出了很多语言的实现: 

详细内容待学习补充。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值