分布式锁的概念

前言

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

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

例如当买票服务器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服务器进行释放锁操作

相关推荐
无心水1 小时前
【任务调度:框架】11、分布式任务调度进阶:高可用、幂等性、性能优化三板斧
人工智能·分布式·后端·性能优化·架构·2025博客之星·分布式调度框架
cga19478 小时前
【RabbitMQ】超详细Windows系统下RabbitMQ的安装配置
windows·分布式·rabbitmq
西门吹雪分身10 小时前
分布式架构之CAP与数据库分片架构
数据库·分布式·架构·分库分表
1104.北光c°12 小时前
我理解的Leaf号段模式:美团分布式ID生成系统
java·开发语言·笔记·分布式·github·leaf
天涯明月199314 小时前
服务网格完全指南:从基础概念到生产实践
java·服务器·数据库·分布式·微服务
筱顾大牛14 小时前
Redission快速入门---分布式锁
java·redis·分布式·缓存
江不清丶15 小时前
Kafka重平衡(Rebalance)深度解析:原理、影响与优化策略
分布式·kafka
Coder_Boy_1 天前
分布式系统核心技术完整梳理(含分库分表、分布式事务、熔断补偿)
jvm·分布式·spring·中间件
摇滚侠1 天前
Java 项目教程《黑马商城-MQ 篇》,分布式架构项目,从开发到部署
java·分布式·架构
蜜獾云1 天前
Kafka(4)-kafka生产环境规划部署
分布式·kafka