分布式锁主动续期的入门级实现-自省 | 简约而不简单
一、背景
如果某个客户端获得锁之后处理时间超过最大约定时间,或者持锁期间内发生了故障导致无法主动释放锁,其持有的锁也能够被其他机制正确释放,并保证后续其它客户端也能加锁,整个处理流程继续正常执行。
简单解释一下:
- 客户端抢到分布式锁之后开始执行任务,执行完毕后再释放分布式锁。
- 持锁后因客户端异常未能把锁释放,会导致锁成为永恒锁。
- 为了避免这种情况,在创建锁的时候给锁指定一个过期时间。
- 到期之后锁会被自动删除掉,这个角度看是对锁资源的一种保护。
二、理还乱?
逻辑看很简单,也很清晰,但任何事情都有两面性,自动删除自然有理,但肯定也有弊端。如果要把锁的功能做的健壮,总要从不断地自我质疑、自我反思中,理顺思路,寻找答案,我认为这属于自省式学习,以后也想尝试这种模式,一起来试试吧:
问题:锁过期了会被删掉,可是任务没结束怎么办?
如果锁被释放的时候,任务尚未执行完毕,那就可能导致其它客户端又抢到锁,任务被重复执行。
问题:把锁的过期时间定的长一点?
逻辑听起来没错,如果你能确定任务的最大耗时,那没问题;大部分情况都很难确定任务的最大耗时该是多少。
问题:锁的过期时间定多长合适?
反正会被释放,过期时间定的足够长吧;如果锁使用的频率很高,加了锁程序有bug释放不掉,服务端岂不是要出现大量的垃圾数据?思来想去,对一个健壮的分布式锁来说,过期时间设置太长了不合适,设置太短了也不合适。
问题:怎么平衡?
不长不短,主动延期!持锁期间,酌情推后锁的过期时间,以基于Redis的分布式锁来说,就需要调用 API 重置锁 key 的过期时间。当前线程持锁后在执行任务期间不能再调用 API 重试锁 key 的过期时间。
问题:谁来调用API呢?
需要使用其他的线程来执行续期。
问题:给每个锁配一个线程?
可以,如果使用分布式锁的场景中没有什么并发,一个客户端也就那么三两个锁同时存在,那就没问题。每个锁抢锁成功后,开启一个线程,在线程中通过循环给锁续期。
public void run() {while (true) {// 续租action.run();} } 复制代码
问题:多久执行一次续期?
有一些常规处理是续租间隔默认采用过期时间的1/3。若把锁的过期时间设定为与实际耗时相差不大,这样通过一两次续租基本就满足了大部分的情况。
问题:为什么要触发一次续期操作呢,这不浪费资源吗?
采用过期时间1/3间隔,若用户定义锁3秒过期,那每秒钟都有一个续期指令,有没有觉得也不太合适。
问题:要不要避免续期指令太频繁?
避免续期指令太频繁调用是有必要的,也可以增加一个续期的最小间隔时间,比如最少是5秒。可由用户自己控制续期周期,没必要一定要发起续期调用。比如任务执行大多在5秒钟,那么就把锁定为7秒,续期时间定在6秒,那么6秒内任务结束了就不用续期,即不必把过期时间定的太长,也不必执行一两次续期操作。
问题:续租的间隔怎么实现?
线程内间隔控制通常是通过 sleep() 方法,稍微精准一点的话,单位使用毫秒。
public void run() {while (true) {// 1、间隔TimeUnit.MILLISECONDS.sleep(sleepTime);// 2、续租action.run();} } 复制代码
问题:线程要关闭吧?
释放锁的时候要主动关闭负责续期的线程,所以线程的循环里要有一个变量来控制退出 while 循环
public void run() {while (isRunning) {// 1、间隔TimeUnit.MILLISECONDS.sleep(sleepTime);// 2、续租action.run();} } 复制代码
问题:变量是跨线程访问,如何保证跨线程的可见性呢?
在变量上增加 volatile 关键字。
private volatile boolean isRunning = true;void cancel(){//控制线程退出this.isRunning = true; } 复制代码
问题:如果续期线程里在 sleep(),那就一直等 sleep() 结束?
如果等到 sleep() 结束,就挺浪费资源的
问题:能不能快速结束 sleep() 状态?
可以,通过 interrupt(),需留意,被打断的时候会抛异常 InterruptedException
void cancel(){//控制线程退出this.isRunning = true;//中断线程this.interrupt(); } 复制代码
到这里,似乎都理顺了。
三、新的思考
问题:如果同时有成百上千个锁呢?
同时有成百上千个线程在工作,你若认为没问题,不存在,那ok,不用继续看下一篇。
那怎么办呢?
可以用
Executors.newScheduledThreadPool
,里边有scheduleAtFixedRate
阿里 Java 代码规范不允许用Execurots嘛?
不能用?风险是什么?你没看累嘛?
累了吧,下一篇再聊,休息休息。
四、最后说一句
我是石页兄,如果这篇文章对您有帮助,或者有所启发的话,欢迎关注笔者的微信公众号【 架构染色 】进行交流和学习。您的支持是我坚持写作最大的动力
分布式锁主动续期的入门级实现-自省 | 简约而不简单相关推荐
- 简约而不简单!分布式锁入门级实现主动续期-自省
一.背景 一个分布式锁应具备的功能特点中有避免死锁这一条: 如果某个客户端获得锁之后处理时间超过最大约定时间,或者持锁期间内发生了故障导致无法主动释放锁,其持有的锁也能够被其他机制正确释放,并保证后续 ...
- 面试官问我,Redis分布式锁如何续期?懵了。
作者:肥朝,来自:肥朝(ID:feichao_java) 前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的老粉丝 ...
- Redis分布式锁的原理以及如何续期
面试问题 Redis锁的过期时间小于业务的执行时间该如何续期? 问题分析 首先如果你之前用Redis的分布式锁的姿势正确,并且看过相应的官方文档的话,这个问题So easy.我们来看 很多同学在用分布 ...
- Redis分布式锁(图解 - 秒懂 - 史上最全)
文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...
- 阿里二面:redis分布式锁过期了但业务还没有执行完,怎么办
面试官:你们系统是怎么实现分布式锁的? 我:我们使用了redis的分布式锁.具体做法是后端接收到请求后加入一个分布式锁,如果加锁成功,就执行业务,如果加锁失败就等待锁或者拒绝请求.业务执行完成后释放锁 ...
- 基于Redis的分布式锁和Redlock算法
来自:后端技术指南针 1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手 ...
- 分布式锁的实现【转载】
一.前言 经常遇到这样的情况,项目中需要使用分布式锁,发现没有完整的产品可以使用,就临时写个分布式锁,花费许多时间和精力来开发和测试一个简单的分布式锁,实现部分功能就使用了.后面遇到这种情况,又去重新 ...
- 【2020尚硅谷Java大厂面试题第三季 04】Redis 9种数据类型使用场景,分布式锁演变步骤,lua脚本,redis事务,Redisson,Redis内存占用,删除策略,内存淘汰策略,手写LRU
1.安装redis6.0.8 2023 02 02 为:redis-7.0.8.tar.gz 2.redis传统五大数据类型的落地应用 3.知道分布式锁吗?有哪些实现方案?你谈谈对redis分布式锁的 ...
- java 通过redis实现倒计时_突破Java面试(42) - Redis amp; ZooKeeper两种分布式锁实现的优劣...
0 Github 1 面试题 一般实现分布式锁都有哪些方式?使用redis如何设计分布式锁?使用zk来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高? 2 考点分析 一般先问问你zk,然后 ...
最新文章
- input中v-model和value不能同时调用时解决方案
- 敏捷开发:软件与文档
- python正则表达式--分组、后向引用、前(后)向断言
- u盘安装ubuntu_简单实用的ubuntu18.04安装
- Cross_validation.train_test_split 中 stratify这个参数的意义是什么?
- VTK修炼之道20:图像基本操作_图像类型转换
- [CVPR2019]:专门为卷积神经网络设计的训练方法:RePr
- 理发店收银系统php,【毕业论文】基于php+mysql美发店收银系统设计与实现.doc
- total是什么牌子的电脑_干货!如何用Python在笔记本电脑上分析100GB数据(上)...
- c语言学习-编程实现以下功能,读入两个数(d1,d2)和一个运算符(o),计算d1 o d2的值
- 买的首套房开发商指定的银行是5.88的利率,朋友都说利率有点高,怎样才能省点钱呢?
- DR、BDR和DROther的关系之通俗演绎
- 应用安全-安全设备-Waf系列-软Waf-D盾
- 《数据结构》 李春葆 第一章-绪论
- php生成值班表,EXCEL表制作自动排列值班表【excel值班表表格制作教程】
- 2019公共课的【考研平均分】和难度系数公布!
- Oracle中SCOTT用户的 emp、dept、bonus、salgrade表的意思及其属性的意思
- [THUWC 2017]在美妙的数学王国中畅游
- 新浪押宝微博拖累利润 开支增长近2730万美元
- 【pwsh】按键自动切换中文输入法