首页 > 编程问答 >Python 的分布式锁管理器

Python 的分布式锁管理器

时间:2024-07-24 16:27:24浏览次数:10  
标签:python python-2.7 locking distributed-lock

我有一堆具有多个实例的服务器,这些实例访问的资源对每秒的请求有硬性限制。

我需要一种机制来锁定所有正在运行的服务器和实例对此资源的访问。

有我在github上找到的一个restful分布式锁管理器: https://github.com/thefab/restful-distributed-lock-manager

不幸的是,似乎有一分钟。锁定时间为1秒,比较不可靠。在几次测试中,解锁 1 秒的锁需要 1 到 3 秒的时间。

有没有经过充分测试的 Python 接口可以用于此目的?

编辑:我需要在 1 秒内自动解锁的东西第二。在我的代码中锁永远不会被释放。


可以使用 Redis 或 ZooKeeper 等外部存储系统来实现分布式锁。这些系统提供了低级基元,可用于构建可靠的分布式锁。

使用 Redis 实现分布式锁

import redis
import time
import uuid

class DistributedLock:
    def __init__(self, redis_client, lock_key, timeout=1):
        self.redis_client = redis_client
        self.lock_key = lock_key
        self.timeout = timeout
        self.lock_value = str(uuid.uuid4())

    def acquire(self):
        """
        尝试获取锁。

        如果在超时内获取锁,则返回 True,否则返回 False。
        """
        end_time = time.time() + self.timeout
        while time.time() < end_time:
            if self.redis_client.setnx(self.lock_key, self.lock_value):
                # 成功获取锁
                self.redis_client.expire(self.lock_key, self.timeout)
                return True
            time.sleep(0.01)
        return False

    def release(self):
        """
        释放锁。

        仅当锁由当前实例持有时才释放锁。
        """
        # 使用 Lua 脚本确保仅当值为预期值时才删除密钥
        unlock_script = """
        if redis.call("get", KEYS[1]) == ARGV[1] then
            return redis.call("del", KEYS[1])
        else
            return 0
        end
        """
        self.redis_client.eval(unlock_script, 1, self.lock_key, self.lock_value)

# 示例用法
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)
distributed_lock = DistributedLock(redis_client, 'my_resource_lock')

if distributed_lock.acquire():
    try:
        # 访问受保护的资源
        print("获得了锁,访问受保护的资源...")
        time.sleep(0.5)  # 模拟处理时间
    finally:
        distributed_lock.release()
else:
    print("无法获取锁,跳过...")

说明:

  • 该代码使用 Redis 的 setnx 命令来尝试以原子方式设置一个密钥。如果该密钥尚不存在,则此命令将设置该密钥并返回 True,否则返回 False。
  • expire 命令用于设置密钥的超时时间,确保即使在获取锁的客户端崩溃的情况下该锁也会被释放。
  • release 方法中,使用 Lua 脚本确保仅当锁由当前实例持有(即,值为预期值)时才删除该锁。这可以防止客户端意外删除其他客户端获取的锁。
  • 此实现提供了一个 1 秒的超时时间,确保如果在 acquire 方法中无法获取锁,该方法将在 1 秒后返回。可以根据需要调整此超时时间。

使用 ZooKeeper 实现分布式锁

还可以使用 kazoo 库在 Python 中使用 ZooKeeper 实现分布式锁。

from kazoo.client import KazooClient
from kazoo.recipe.lock import Lock

# 创建与 ZooKeeper 的连接
zk = KazooClient(hosts='localhost:2181')
zk.start()

# 创建锁对象
lock = Lock(zk, '/my_resource_lock')

# 尝试获取锁
if lock.acquire(timeout=1):
    try:
        # 访问受保护的资源
        print("获得了锁,访问受保护的资源...")
        time.sleep(0.5)  # 模拟处理时间
    finally:
        lock.release()
else:
    print("无法获取锁,跳过...")

# 关闭 ZooKeeper 连接
zk.stop()

说明:

  • 该代码使用 kazoo.recipe.lock.Lock 类在 ZooKeeper 中创建一个锁。
  • acquire 方法尝试获取锁,并可选地采用超时参数。
  • release 方法释放锁。

这些是使用 Redis 和 ZooKeeper 在 Python 中实现分布式锁的一些方法。可以根据的特定需求和约束选择最适合的方法。

标签:python,python-2.7,locking,distributed-lock
From: 23036990

相关文章

  • 如何在Python中提示self变量的类型
    通常不需要关心Python类成员函数中的self变量,但我正在实现一个装饰器,看起来像defextractor(depends:List[Text]=None,provides:List[Text]=None)->Callable[[ExtractorFunction],Extracto......
  • 将 Python 类型提示限制为元组中的值
    我的方法之一采用status中使用的filter()参数。此参数与定义如下的模型字段相关:STATUS_CHOICES=((1,_("draft")),(2,_("private")),(3,_("published")),)classMyModel(Model):status=models.PositiveSmallIntegerFi......
  • 在python中查找区间数据的中位数
    我正在探索不同的python库,我想知道如何找到分组数据集的近似中值。这里有一个表格供参考。年龄频率1-1012310-203502......
  • 比较Python中的字符串统一特殊字符
    也许我可以使用更好的英语,但我想要的是忽略单词中的重音(和类似的),所以:renè、rené、rene'和rene应该是相同的,所以应该mañana和manana或even-distribuited和evendistribuited,可能还有sho......
  • 如何使用 Python 脚本从客户账单电子邮件中获取订单 ID - WooCommerce API
    我想创建一个python脚本,返回只知道客户的账单电子邮件的订单。我尝试这样做,但返回所有最近的订单:fromwoocommerceimportAPIwcapi=API(url="https://siteexample.com",consumer_key="ck_xxx",consumer_secret="cs_xxx",version="wc/v3")......
  • python基础理论小总结
    1.python语言的特性Python是一门解释型语言,简单清晰,开源免费,跨平台,有大量第三方库辅助开发,支持面向对象与自动垃圾回收,方便与其他编程语言相互调用。Python在数据采集、人工智能、WEB后台开发、自动化运维、测试等方向应用广泛。2.解释型语言和编译型语言的区别执行方式不......
  • python编码规范
    本篇讲的是代码格式化的问题,解决格式化的方法在最下方,不想看内容的,滑到最下方就好了。一、变量的命名规则1.组成:字母、数字、下划线2.不可以以数字开头3.不建议使用下划线开头4.命名需见名知意5.不要与关键字重名。如何查找所有关键字?importkeywordprint(keyword.k......
  • Python爬虫开发中的常用库与框架安装指南
    在Python爬虫开发中,选择合适的库和框架可以大大提高开发效率和爬虫的性能。本文将介绍一些常用的解析库、请求库、储存库、Web库、App爬取库以及爬虫框架,并展示如何使用pip命令进行安装。一、解析库1.BeautifulSoupBeautifulSoup是一个用于从HTML或XML文件中提取数据的Pyth......
  • 如何在Python中的指定项目之后添加新项目到嵌套列表?
    给定的列表是这样的。list1=[10,20,[300,400,[5000,6000],500],30,40]预期输出是这样的。我知道这是一个非常基本的问题,但我很困惑。输出:[10,20,[300,400,[5000,6000,7000],500],30,40]我希望有人能帮助我解决这个问题。并解释了嵌套列表的插入功......
  • python带界面实现word文档比对功能
    python实现word文档比对的功能较简单,笔者这里将其界面话,可以指定输入比对的文档,相似度,最小相似参数等。输出的结果以word的形式保存,重复部分会标出,基本实现了商业软件的功能。先看界面这里不废话了,直接给出全部源码,觉得好的点个赞。程序打包的话,自己百度。fromtkinterimp......