广告位联系
返回顶部
分享到

python-redis-lock实现锁自动续期的源码逻辑

python 来源:互联网 作者:佚名 发布时间:2024-07-14 08:40:37 人浏览
摘要

python-redis-lock简介 python-redis-lock是一个python的第三方库,基于Redis,封装了分布式锁的逻辑,提供了更高级的API来简化锁的获取、保持和释放过程。包括自动续期、锁超时、重入锁等功能。 相比

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实例在初始化时,针对这两个参数的源码:

1

2

3

4

5

6

7

8

9

class Lock(object):

    def __init__(self, redis_client, name, expire=None, auto_renewal=False, ...):

        ...

        if expire:

            expire = int(expire)

        ...

        self._expire = expire

        self._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是否为空,如果不为空,则开启锁的自动续期(这里省略了一些内容,因为只关注续期的代码实现逻辑):

1

2

3

4

5

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方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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 = True

    self._lock_renewal_thread.start()

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

1

2

3

4

5

6

7

def _lock_renewer(name, lockref, interval, stop):

    while not stop.wait(timeout=interval):

        ...

        lock: "Lock" = lockref()

        if lock is None:

            break

        lock.extend(expire=lock._expire)

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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] then

        return 1

    elseif redis.call("ttl", KEYS[1]) < 0 then

        return 2

    else

        redis.call("expire", KEYS[1], ARGV[2])

        return 0

    end

"""

cls.extend_script = redis_client.register_script(EXTEND_SCRIPT)

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


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • python执行shell并获取结果
    在Python中执行Shell命令并获取其结果,通常可以使用subprocess模块。这个模块允许我们启动新的进程,连接到它们的输入/输出/错误管道,并获
  • Python利用pandas处理CSV文件的用法

    Python利用pandas处理CSV文件的用法
    一、pandas简介 pandas是一个第三方数据分析库,其集成了大量的数据分析工具,可以方便的处理和分析各类数据。这是一个第三方库,使用下
  • Python远程控制Windows服务器的方法
    开篇小故事 故事要从一只猫说起。 小明是一名 Python 开发者,他有一只聪明的小猫咪叫皮皮。有一天,小明正在服务器上部署项目,突然想
  • 使用python生成各种常见条形码及二维码

    使用python生成各种常见条形码及二维码
    条形码和二维码是现代信息交换和数据存储的重要工具,它们将信息以图形的形式编码,便于机器识别和数据处理,被广泛应用于物流、零
  • python的virtualenv虚拟环境常见问题和命令
    常用的venv命令 在Python中,venv是一个用于创建和管理虚拟环境的模块。虚拟环境可以帮助你在项目之间隔离不同的Python包和依赖关系。以下
  • Python中的变量和数据类型使用方式
    变量和数据类型是Python中非常基础的概念,下面是详细介绍: 1. 变量 变量是用于存储数据的容器,可以在程序中多次使用。在Python中,变量
  • Python遍历字典删除元素的五种方法
    在Python中,直接遍历字典并在遍历过程中删除元素可能会导致运行时错误,因为字典在迭代时并不支持修改其大小。但是,我们可以通过一
  • python-redis-lock实现锁自动续期的源码逻辑
    python-redis-lock简介 python-redis-lock是一个python的第三方库,基于Redis,封装了分布式锁的逻辑,提供了更高级的API来简化锁的获取、保持和释放
  • Python引用不确定的函数
    在Python中,引用不确定的函数通常意味着我们可能在运行时才知道要调用哪个函数,或者我们可能想根据某些条件动态地选择不同的函数来
  • 提升Python Web应用性能的10个关键技巧
    提升Python Web应用性能的10个关键技巧 Python作为一种强大的编程语言,在Web开发领域也有着广泛的应用。通过结合Python的灵活性和一些高性能
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计