python-redis-lock是如何实现锁自动续期的

python-redis-lock简介

python-redis-lock是一个python的第三方库,基于Redis,封装了分布式锁的逻辑,提供了更高级的API来简化锁的获取、保持和释放过程。包括自动续期、锁超时、重入锁等功能。
相比于直接使用redis的setnx,避免了写额外代码来实现锁的复杂逻辑。

锁的续期

在使用分布式锁的情况下,如果某个服务器A的业务还未执行完(可能因为网络拥塞、数据量突然变大等各种原因),但是锁过期了,可能引发额外的问题。例如另一台服务器B发现锁释放了,于是加锁并开始执行业务,从而导致出现问题。
更有可能导致服务器A业务在执行完后去释放锁时,意外地释放了服务器B加的锁,导致服务器C进入,从而引发问题(在未使用唯一性ID表示加锁者的情况下)。
所以对锁的过期时间来续期是很有必要的,它确保了锁在业务执行完后才释放。

python-redis-lock实现自动续期的源码分析

首先在配置python-redis-lock实例时,有两个参数:expire int 和 auto_renewal boolean。
expire:锁过期时间,单位为秒。
auto_renewal:是否开启自动续期锁。
python-redis-lock实例在初始化时,针对这两个参数的源码:

class Lock(object):def __init__(self, redis_client, name, expire=None, auto_renewal=False, ...):...if expire:expire = int(expire)...self._expire = expireself._lock_renewal_interval = float(expire) * 2/3 if auto_renewal else None...

假设我们设置了一个过期时间30秒,开启自动续期的Lock实例,则self._expire=30秒,self._lock_renewal_interval=20秒。
当在代码层调用Lock.acquire方法时,判断self._lock_renewal_interval是否为空,如果不为空,则开启锁的自动续期(这里省略了一些内容,因为只关注续期的代码实现逻辑):

class Lock(object):def acquire(self, blocking=True, timeout=None):...if self._lock_renewal_interval is not None:self._start_lock_renewer()

在self._start_lock_renewer方法中,基于python的threading模块,开启了一个锁自动更新线程self._lock_renewal_thread。这个线程执行self._lock_renewer方法

def _start_lock_renewer(self):...self._lock_renewal_stop = threading.Event() # threading.Event()用于线程间的协调self._lock_renewal_thread = threading.Thread(group=None,target=self._lock_renewer,kwargs={'name': self._name,'lockref': weakref.ref(self), # 对Lock实例的弱引用'interval': self._lock_renewal_interval,'stop': self._lock_renewal_stop,},)self._lock_renewal_thread.demon = Trueself._lock_renewal_thread.start()

weakref.ref(self)创建当前类实例(self)的弱引用,并将其存储在变量 lockref 中。使用 weakref.ref 创建的弱引用不会阻止对象被垃圾回收。
在self._lock_renewer方法中,首先用了while循环来每次等待20秒(interval=20)再执行循环体:如果弱引用对象(即Lock实例本身)没有被垃圾回来,则执行续期的方法(lock.extend):

def _lock_renewer(name, lockref, interval, stop):while not stop.wait(timeout=interval):...lock: "Lock" = lockref()if lock is None:breaklock.extend(expire=lock._expire)

在self.extend方法中,执行了一个Lua脚本来更新锁的过期时间。
在满足self._name和self._signal的缓存键值存在且锁未过期的情况下,将当前锁的过期时间重置为expire(30秒)。

def extend(self. expire=None):if expire:expire = int(expire)error = self.extend_script(client=self._client, # 对redis的连接keys=(self._name, self._signal),args=(self._id, expire))...
# self.extend_script的执行逻辑:
EXTEND_SCRIPT = b"""if redis.call("get", KEYS[1]) ~= ARGV[1] thenreturn 1elseif redis.call("ttl", KEYS[1]) < 0 thenreturn 2elseredis.call("expire", KEYS[1], ARGV[2])return 0end
"""
cls.extend_script = redis_client.register_script(EXTEND_SCRIPT)

以上就是python-redis-lock实现锁自动续期的源码逻辑。
其中用到了多线程threading、弱引用weakref和Lua脚本等相关知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/42055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

倒退型自闭症与轻度自闭症有什么区别?

作为星贝育园自闭症儿童康复中心的一名专业教师&#xff0c;我深知家长们在面对自闭症谱系障碍&#xff08;ASD&#xff09;时的种种疑问与挑战&#xff0c;尤其是关于倒退型自闭症与轻度自闭症之间的区别。今天&#xff0c;我将从专业视角出发&#xff0c;深入浅出地解析这两种…

精通Vim编辑器:Linux系统下的强大文本编辑工具

精通Vim编辑器&#xff1a;Linux系统下的强大文本编辑工具 引言 在Linux世界中&#xff0c;Vim是一个功能强大、高度可定制的文本编辑器&#xff0c;它继承自经典的vi编辑器并提供了一系列增强功能。无论是系统管理员、开发人员还是普通用户&#xff0c;掌握Vim的使用都能大幅…

游戏AI的创造思路-技术基础-强化学习(2)

上一篇中引出了深度强化学习这个大坑&#xff0c;本篇浅浅填一下~~~~ 目录 6. 深度强化学习概述 6.1. 基本概念 6.2. 发展历史 6.3. 基本公式 6.4. Python实现 6.5. 运行原理 6.5.1. 核心要素 6.5.2. 运行原理 6.5.3. 典型算法 6.5.4. Python实现代码 6.6. 优缺点 …

Segmentation fault (core dumped)

错误简介 出现 “Segmentation fault (core dumped)” 错误通常意味着程序访问了未分配的内存或者越界访问了已分配内存之外的区域。 段错误通常发生在以下情况&#xff1a; 空指针解引用&#xff1a;尝试对空指针进行操作。内存越界&#xff1a;访问了超出分配内存边界的区…

大厂面试官赞不绝口的后端技术亮点【后端项目亮点合集(2)】

本文将持续更新~~ hello hello~ &#xff0c;这里是绝命Coding——老白~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;绝命C…

提高论文发表机会:Nature Communications 最新研究教你如何巧妙回复审稿意见

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 对于科研搬砖人来说&#xff0c;在论文投稿过程中&#xff0c;如何有效回复审稿意见才能得到审稿人的认可&#xff0c;一直是一个让人困惑又带点玄学的问题。 但是&#xff0c…

vue3 按钮复制粘贴功能

1.html <div click"copy(item.envelopePassword)" > 复制口令 </div> 2.utils 创建copy.js export const copy (val: string): void > {let { isSuccessRef } useCopyToClipboard(val) as anyif (isSuccessRef) {// 轻提示showNotify("复制…

【强化学习的数学原理】课程笔记--3(蒙特卡洛方法)

目录 蒙特卡洛方法MC Basic算法sparse reward MC Greedy 算法样本使用效率MC ϵ \epsilon ϵ-Greedy 算法一些例子 蒙特卡洛方法 第二节 推导贝尔曼最优公式中的&#xff1a; q π k ( s , a ) ∑ r P ( r ∣ s , a ) r γ ∑ s ′ P ( s ′ ∣ s , a ) v π k ( s ′ ) q…

vue3 ~ pinia学习

先看两个图 一个vuex 一个pinia 根据图看出来 pinia更简单了 那么具体怎么操作呢 我们来看下~ 第一步 下载 yarn add pinia # 或者使用 npm npm install pinia 第二步 注册 创建一个 pinia 实例 (根 store) 并将其传递给应用&#xff1a; import { createApp } from v…

代码随想录算法训练Day57|LeetCode200-岛屿数量、LeetCode695-岛屿的最大面积

岛屿数量 题目描述 力扣200-岛屿数量 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此…

前端vue后端java使用easyexcel框架下载表格xls数据工具类

一 使用alibaba开源的 easyexcel框架&#xff0c;后台只需一个工具类即可实现下载 后端下载实现 依赖 pom.xml <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependen…

MATLAB-分类CPO-RF-Adaboost冠豪猪优化器(CPO)优化RF随机森林结合Adaboost分类预测(二分类及多分类)

MATLAB-分类CPO-RF-Adaboost冠豪猪优化器&#xff08;CPO&#xff09;优化RF随机森林结合Adaboost分类预测&#xff08;二分类及多分类&#xff09; 分类CPO-RF-Adaboost冠豪猪优化器&#xff08;CPO&#xff09;优化RF随机森林结合Adaboost分类预测&#xff08;二分类及多分类…

docker 设置代理,通过代理服务器拉取镜像

docker 拉取目标镜像需要通过代理服务器进行时&#xff0c;可以通过为 docker 配置全局代理来实现。 注&#xff1a;Linux 上通过临时命令 export HTTP_PROXY 设置的代理&#xff0c;对 curl 这些有用&#xff0c;但是对 docker pull 不起作用。 示例 假设您的代理服务器地址是…

Nginx目录文件作用

查看文件 [rootlocalhost nginx]# pwd /opt/nginx [rootlocalhost nginx]# ll total 4 drwx------ 2 nobody root 6 Jun 6 09:11 client_body_temp drwxr-xr-x 3 root root 4096 Feb 28 14:30 conf drwx------ 2 nobody root 6 Feb 28 14:29 fastcgi_temp drwxr-xr-x…

【web前端HTML+CSS+JS】--- HTML学习笔记01

学习链接&#xff1a;黑马程序员pink老师前端入门教程&#xff0c;零基础必看的h5(html5)css3移动端前端视频教程_哔哩哔哩_bilibili 学习文档&#xff1a; Web 开发技术 | MDN (mozilla.org) 一、前后端工作流程 WEB模型&#xff1a;前端用于采集和展示信息&#xff0c;中…

Web漏洞扫描工具AppScan与AWVS测评及使用体验

AppScan和AWVS业界知名的Web漏洞扫描工具&#xff0c;你是否也好奇到底哪一个能力更胜一筹呢&#xff1f;接下来跟随博主一探究竟吧。 1. 方案概览 第一步&#xff1a;安装一个用于评测的Web漏洞靶场&#xff08;本文采用最知名和最广泛使用的靶场&#xff0c;即OWASP Benchma…

啥?你没听过SpringBoot的FatJar?

写在最前面&#xff1a; SpringBoot是目前企业里最流行的框架之一&#xff0c;SpringBoot的部署方式多数采用jar包形式。通常&#xff0c;我们使用java -jar便可以直接运行jar文件。普通的jar只包含当前 jar的信息&#xff0c;当内部依赖第三方jar时&#xff0c;直接运行则会报…

robotframework-appiumLibrary 应用 - 实现 app 自动化

1、安装appiumLibrary第三方库 运行pip命令&#xff1a;pip install robotframework-appiumlibrary 若已安装&#xff0c;需要更新版本可以用命令&#xff1a;pip install -U robotframework-appiumlibrary 2、安装app自动化环境。 参考我的另外一篇专门app自动化环境安装的…

设计模式探索:策略模式

1. 什么是策略模式&#xff08;Strategy Pattern&#xff09; 定义 策略模式&#xff08;Strategy Pattern&#xff09;的原始定义是&#xff1a;定义一系列算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而…

打卡第4天----链表

通过学习基础,发现我的基本功还得需要再练练,思路得再更加清晰明了,这样子做算法题才能驾轻就熟。每天记录自己的进步。 一、两两交换 题目编号:24 题目描述: 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本…