您当前的位置:首页 > 电脑百科 > 数据库 > 百科

分布式锁主动续期的入门级实现

时间:2023-03-07 13:47:00  来源:微信公众号  作者:架构染色

一、背景

在《​​# 分布式锁上-初探​​》中有提到一个分布式锁应具备的功能特点中有避免死锁这一条:

如果某个客户端获得锁之后处理时间超过最大约定时间,或者持锁期间内发生了故障导致无法主动释放锁,其持有的锁也能够被其他机制正确释放,并保证后续其它客户端也能加锁,整个处理流程继续正常执行。

简单解释一下:

  1. 客户端抢到分布式锁之后开始执行任务,执行完毕后再释放分布式锁。
  2. 持锁后因客户端异常未能把锁释放,会导致锁成为永恒锁。
  3. 为了避免这种情况,在创建锁的时候给锁指定一个过期时间。
  4. 到期之后锁会被自动删除掉,这个角度看是对锁资源的一种保护。

二、理还乱?

逻辑看很简单,也很清晰,但任何事情都有两面性,自动删除自然有理,但肯定也有弊端。如果要把锁的功能做的健壮,总要从不断地自我质疑、自我反思中,理顺思路,寻找答案,我认为这属于自省式学习,以后也想尝试这种模式,一起来试试吧:

  • 问题:锁过期了会被删掉,可是任务没结束怎么办?如果锁被释放的时候,任务尚未执行完毕,那就可能导致其它客户端又抢到锁,任务被重复执行。
  • 问题:把锁的过期时间定得长一点?逻辑听起来没错,如果你能确定任务的最大耗时,那没问题;大部分情况都很难确定任务的最大耗时该是多少。
  • 问题:锁的过期时间定多长合适?反正会被释放,过期时间定的足够长吧;如果锁使用的频率很高,加了锁程序有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嘛?

 

图片

  • 不能用?风险是什么?


Tags:分布式锁   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
在Redis中如何实现分布式锁的防死锁机制?
在Redis中实现分布式锁是一个常见的需求,可以通过使用Redlock算法来防止死锁。Redlock算法是一种基于多个独立Redis实例的分布式锁实现方案,它通过协调多个Redis实例之间的锁...【详细内容】
2024-02-20  Search: 分布式锁  点击:(49)  评论:(0)  加入收藏
手动撸一个 Redis 分布式锁
大家好呀,我是楼仔。今天第一天开工,收拾心情,又要开始好好学习,好好工作了。对于使用 Java 的小伙伴,其实我们完全不用手动撸一个分布式锁,直接使用 Redisson 就行。但是因为这些...【详细内容】
2024-02-19  Search: 分布式锁  点击:(40)  评论:(0)  加入收藏
Redis分布式锁常见坑点分析
日常开发中,基于 Redis 天然支持分布式锁,大家在线上分布式项目中都使用过 Redis 锁。本文主要针对日常开发中加锁过程中某些异常场景进行讲解与分析。本文讲解示例代码都在 h...【详细内容】
2023-12-11  Search: 分布式锁  点击:(111)  评论:(0)  加入收藏
一文详解分布式锁的看门狗机制
我们今天来看看这个 Redis 的看门狗机制,毕竟现在还是有很多是会使用 Redis 来实现分布式锁的,我们现在看看这个 Redis 是怎么实现分布式锁的,然后我们再来分析这个 Redis 的看...【详细内容】
2023-11-29  Search: 分布式锁  点击:(217)  评论:(0)  加入收藏
全新的分布式锁,功能简单且强大
作者:donnie4w链接:https://my.oschina.net/donnie4w/blog/10114233前言:分布式锁是分布式系统中一个极为重要的工具。目前有多种分布式锁的设计方案,比如借助 redis,mq,数据库,zoo...【详细内容】
2023-10-30  Search: 分布式锁  点击:(268)  评论:(0)  加入收藏
Redis分布式锁失效,数据是否仍存在于内存中?
正文大家好,我是小米,欢迎来到小米的技术分享!今天,我要和大家一起探讨一个有趣而又深奥的话题:Redis分布式锁失效了,数据还存在Redis内存中吗?这个问题在面试中经常被提出,也是我们...【详细内容】
2023-10-11  Search: 分布式锁  点击:(321)  评论:(0)  加入收藏
Redis魔法:点燃分布式锁的奇妙实现
分布式锁是一种用于在分布式系统中控制对共享资源的访问的锁。它与传统的单机锁不同,因为它需要在多个节点之间协调以确保互斥访问。本文将介绍什么是分布式锁,以及使用Redis...【详细内容】
2023-10-11  Search: 分布式锁  点击:(248)  评论:(0)  加入收藏
分布式锁,原来这么简单!
作者 | 蔡柱梁审校 | 重楼目录 分布式锁介绍 如何实现分布式锁 实现分布式锁1 分布式锁介绍现在的服务往往都是多节点,在一些特定的场景下容易产生并发问题,比如扣减库存,送完...【详细内容】
2023-09-22  Search: 分布式锁  点击:(234)  评论:(0)  加入收藏
lua+redis:分布式锁解决方案分享
介绍当我们涉及到多进程或多节点的分布式系统时,传统的单机锁机制不再足够应对并发控制的需求。这是因为在分布式环境中,多个进程或节点同时访问共享资源,传统锁无法有效地协调...【详细内容】
2023-09-13  Search: 分布式锁  点击:(342)  评论:(0)  加入收藏
分布式锁的3种实现!
分布式锁是一种用于保证分布式系统中多个进程或线程同步访问共享资源的技术。同时它又是面试中的常见问题,所以我们本文就重点来看分布式锁的具体实现(含实现代码)。在分布式系...【详细内容】
2023-09-13  Search: 分布式锁  点击:(311)  评论:(0)  加入收藏
▌简易百科推荐
向量数据库落地实践
本文基于京东内部向量数据库vearch进行实践。Vearch 是对大规模深度学习向量进行高性能相似搜索的弹性分布式系统。详见: https://github.com/vearch/zh_docs/blob/v3.3.X/do...【详细内容】
2024-04-03  京东云开发者    Tags:向量数据库   点击:(5)  评论:(0)  加入收藏
原来 SQL 函数是可以内联的!
介绍在某些情况下,SQL 函数(即指定LANGUAGE SQL)会将其函数体内联到调用它的查询中,而不是直接调用。这可以带来显著的性能提升,因为函数体可以暴露给调用查询的规划器,从而规划器...【详细内容】
2024-04-03  红石PG  微信公众号  Tags:SQL 函数   点击:(5)  评论:(0)  加入收藏
如何正确选择NoSQL数据库
译者 | 陈峻审校 | 重楼Allied Market Research最近发布的一份报告指出,业界对于NoSQL数据库的需求正在持续上升。2022年,全球NoSQL市场的销售额已达73亿美元,预计到2032年将达...【详细内容】
2024-03-28    51CTO  Tags:NoSQL   点击:(14)  评论:(0)  加入收藏
为什么数据库连接池不采用 IO 多路复用?
这是一个非常好的问题。IO多路复用被视为是非常好的性能助力器。但是一般我们在使用DB时,还是经常性采用c3p0,tomcat connection pool等技术来与DB连接,哪怕整个程序已经变成以...【详细内容】
2024-03-27  dbaplus社群    Tags:数据库连接池   点击:(13)  评论:(0)  加入收藏
八个常见的数据可视化错误以及如何避免它们
在当今以数据驱动为主导的世界里,清晰且具有洞察力的数据可视化至关重要。然而,在创建数据可视化时很容易犯错误,这可能导致对数据的错误解读。本文将探讨一些常见的糟糕数据可...【详细内容】
2024-03-26  DeepHub IMBA  微信公众号  Tags:数据可视化   点击:(7)  评论:(0)  加入收藏
到底有没有必要分库分表,如何考量的
关于是否需要进行分库分表,可以根据以下考量因素来决定: 数据量和负载:如果数据量巨大且负载压力较大,单一库单一表可能无法满足性能需求,考虑分库分表。 数据增长:预估数据增长...【详细内容】
2024-03-20  码上遇见你  微信公众号  Tags:分库分表   点击:(15)  评论:(0)  加入收藏
在 SQL 中写了 in 和 not in,技术总监说要炒了我……
WHY?IN 和 NOT IN 是比较常用的关键字,为什么要尽量避免呢?1、效率低项目中遇到这么个情况:t1表 和 t2表 都是150w条数据,600M的样子,都不算大。但是这样一句查询 ↓select *...【详细内容】
2024-03-18  dbaplus社群    Tags:SQL   点击:(6)  评论:(0)  加入收藏
应对慢SQL的致胜法宝:7大实例剖析+优化原则
大促备战,最大的隐患项之一就是慢SQL,对于服务平稳运行带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,在日常开发中如何避免出现慢SQL,出现了慢SQL应该按照什...【详细内容】
2024-03-14  京东云开发者    Tags:慢SQL   点击:(5)  评论:(0)  加入收藏
过去一年,我看到了数据库领域的十大发展趋势
作者 | 朱洁策划 | 李冬梅过去一年,行业信心跌至冰点2022 年中,红衫的一篇《适应与忍耐》的报告,对公司经营提出了预警,让各个公司保持现金流,重整团队,想办法增加盈利。这篇报告...【详细内容】
2024-03-12    InfoQ  Tags:数据库   点击:(27)  评论:(0)  加入收藏
SQL优化的七个方法,你会哪个?
一、插入数据优化 普通插入:在平时我们执行insert语句的时候,可能都是一条一条数据插入进去的,就像下面这样。INSERT INTO `department` VALUES(1, '研发部(RD)', &#39...【详细内容】
2024-03-07  程序员恰恰  微信公众号  Tags:SQL优化   点击:(20)  评论:(0)  加入收藏
站内最新
站内热门
站内头条