004-基于Redis的分布式锁

文章介绍了分布式锁在多机场景中的作用,以及如何通过原子操作保证加锁和解锁的完整性。Redisson通过Lua脚本实现原子操作和锁续期,同时讨论了未获取锁的线程处理和主从失效问题。为了提高性能,文章提出了锁粒度细化和分段策略。
摘要由CSDN通过智能技术生成

分布式锁

什么用

多机场景下对一个资源加锁,单机锁已经没办法控制了

怎么加

分布式锁一般要考虑的就是
一般还是采用

try {
加锁(key, lockId, 超时时间)
} finally {
解锁(key, lockId)
}

原子操作问题

比如加锁和设置超时时间必须要原子操作
解锁和判断是否是自己加的锁也需要有原子性

判断是否是自己加的锁常用的方案就是进入代码就创建一个UUID(lockId)
解锁的时候先判断是自己加的锁再解锁

锁续期问题

如果所设置的超时时间结束了还是没有操作完业务
还是会出现问题,所以就需要考虑锁的续期问题

Redisson实现

原子操作

Lua脚本实现
好处:

  1. 减少网络开销
  2. 原子性:脚本执行中间不会执行其他命令
  3. 事务功能

锁续期

启动后台线程每隔10s检查是否还持有锁
如果有则延长锁时间

没有获取锁自旋

Lua脚本获取锁剩余时间
while(true)
刷新剩余时间
然后 信号量等待剩余时间

源码

引入redisson

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.6.5</version>
</dependency>
加锁

在这里插入图片描述
是否存在lockKey
不存在则:设置Hash,key:lockKey,filedKey:UUID+threadId,value:1
并设置超时时间
最后返回null
在这里插入图片描述
默认超时时间为:
在这里插入图片描述

获取锁线程续期

在这里插入图片描述
在这里插入图片描述
进入方法后延时10s执行
根据lockKey,UUID+threadId判断锁是否存在
如果存在则续期后返回1(Java:true)重新调用续期方法

未获取锁线程

在这里插入图片描述

在这里插入图片描述
返回锁的ttl(剩余有效时间)
在这里插入图片描述
获取Semaphore进入超时时间的等待

单纯的等待其实是不行的,就是虽然超时时间还没到但是锁住的线程已经处理完了
那这个时候等待的线程应该被唤醒
在这里插入图片描述
redis的订阅功能
订阅:SUBSCRIBE channel
发布:PUBLISH channel message

那什么时候唤醒呢?其实就是解锁的时候发布
那拿到发布的消息后怎么消费呢?
其实就在创建的时候设置消费处理
在这里插入图片描述
在这里插入图片描述

解锁逻辑

在这里插入图片描述
我们可以看到如果还存在key和key+filedKey
则删除key
然后给订阅者发布解锁消息(内容为:0)

主从失效问题

主接点加锁时但是没有同步给从节点的时候主节点挂了
此时锁失效

性能优化

缩小锁的粒度
分段:大的资源拆分成小的资源后加锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值