分布式锁的概念

前言

在分布式系统中, 每个服务器都是一个单独的进程, 因为进程之间的执行顺序又是随机的, 很容易导致严重问题.

以买票系统为例, 如果没有分布式锁的话, 由于进程的随机性, 可能会导致一张票卖给两个人引发"超卖"问题. 所以引入分布式锁来解决:

例如当买票服务器1想进行买车次001的票时, 会先访问Redis, 寻找有没有其他服务器在买车次001的票, 如果没发现就在Redis上设置一个关于001的key. 此时如果其他服务器也想买001的票但是发现Redis上已经存在了这个key, 则不会再买票. 这样就达到了加锁的目的.

用Redis进行"加锁"的具体流程

利用Redis中的"set nx"

Redis中的"set nx"命令格式如下:

复制代码
SET key value NX

这样的效果是: 如果Redis上存在这样的Key就不会进行设置, 没有才会设置Key.

当以这样的方式进行"加锁"操作后, 我们同样需要对"锁"进行释放. 而利用del命令即可删除Key达到释放的效果.

为Key设定一个过期时间

如果一个服务器已经对Redis添加了Key, 但是这个服务器意外崩溃, 此时的"锁"还没有释放, 其他服务器只能进行等待. 为避免这一情况, 设置Key时需要添加一个"过期时间"的选项, 命令格式如下:

复制代码
SETNX key value NX EX (时间, 单位为秒)

避免这个服务器长时间占用"锁".

为服务器设置校验ID

有一种情况: 服务器1进行了set nx加锁了, 但服务器2执行了del释放了锁. 为避免这一情况, 需要对释放锁操作进行一个条件判定: 为所有服务器设置一个ID, 在释放锁时对服务器ID进行判定, 是否为加锁的服务器, 确定后再删除.

设置校验ID的流程如下(以伪代码形式说明):

引入Lua

根据上面设置服务器ID的过程中, 可以发现这个操作并非原子性的, 这就意味着可以被其他操作来"插队", 例如可能在验证的后另外一个服务器又进行了"set"操作, 当执行到del时就会释放另外一个服务器的锁了

为了解决这种问题, 采用Lua脚本的方式将这种非原子性的命令写入进去, 因为Redis在执行Lua脚本时是原子性的. 达到了事务的效果

写入Lua脚步执行的代码:

复制代码
if redis.call('get',KEYS[1]) == ARGV[1] then 
   return redis.call('del',KEYS[1]) 
else
   return 0 
end;

引入看门狗(watch dog)

在设置Key的过期时间时, 需要考虑到: 时间不能过短,防止服务器的操作未执行完就进行释放锁. 也不能设置时间过长,导致长时间占用锁,使其他服务器无法进行操作.

而引入看门狗机制可以有效解决问题: 在服务器中设置一个专门监视的线程, 如果快要到过期时间且服务器的操作还未结束, 那么将继续延长过期时间, 直到操作完成.

使用ReadLock算法

在使用Redis实现分布式锁时, 需要注意Redis节点的宕机, 这是致命性的. Redis也给出了对应办法

RedLock算法:

在Redis中使用"哨兵"机制, 实现主节点宕机,从节点晋升. 我们引入多 组 Redis 节点. 其中每⼀组 Redis 节点都包含⼀个主节点和若干从节点. 并且组和组之间存 储的数据都是⼀致的, 相互之间是 "备份" 关系(而并非是数据集合的⼀部分, 这点有别于 Redis cluster). 加锁的时候, 按照⼀定的顺序, 写多个 master 节点. 在写锁的时候需要设定操作的 "超时时间". 比如 50ms. 即如果 setnx 操作超过了 50ms 还没有成功, 就视为加锁失败.如果给某个节点加锁失败, 就⽴即再尝试下⼀个节点. 当加锁成功的节点数超过总节点数的⼀半, 视为加锁成功.

如上图, ⼀共五个节点, 三个加锁成功, 两个失败, 此时视为加锁成功. 这样的话, 即使有某些节点挂了, 也不影响锁的正确性. 而释放锁时同样需要对所有Redis服务器进行释放锁操作

相关推荐
functionflux23 分钟前
kafka-python:Python 生态中最成熟的 Kafka 客户端
分布式·python·其他·kafka
kyle~4 小时前
DDS分布式实时系统---自省机制
开发语言·分布式·机器人·c#·接口·ros2
q21030633725 小时前
kafka启动几秒后挂了,重启多次无果
分布式·kafka
凯源智能5 小时前
工商业分布式光伏箱变智能监控落地实战
分布式·箱变测控·光伏箱变测控装置·箱变监控系统·箱式变测控装置
沂水弦音6 小时前
软控 EI 系列模块优势与竞品对比分析:面向 EtherCAT 分布式 I/O 的工程选型视角
分布式·制造·工业自动化·ethercat·io模块
木心术17 小时前
在NVIDIA DGX Spark上部署NemoClaw的实际操作方案以及实际应用便利性。
大数据·分布式·spark
kuokay7 小时前
MLOps 与 AIOps 的核心概
人工智能·分布式·大模型·agent·llama
openFuyao7 小时前
openFuyao InferNex:云原生分布式 LLM 推理加速套件——从生产痛点到算力的极致释放
分布式·云原生·ai原生·openfuyao·多样化算力
咖啡星人k1 天前
MonkeyCode 开源协作指南:如何让分布式团队高效使用AI编程
分布式·开源·ai编程·monkeycode
阿坤带你走近大数据1 天前
如何保证kafka中的数据一致性
分布式·kafka