您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

适用于Python的分布式锁管理器

适用于Python的分布式锁管理器

我的第一个想法是使用Redis。但是,还有更多很棒的工具,有些甚至更轻巧,因此我的解决方案基于zmq。因此,您不必运行Redis,足以运行小型Python脚本。

让我先回顾您的要求,然后再描述解决方案。

在固定时间内将对某个资源的请求数限制为多个请求。

自动解锁

资源(自动)解锁应在少于1秒的时间内发生。

它应该被分发。我将假设,您的意思是多个消耗某些资源的分布式服务器应该能够使用,并且只拥有一个更衣室服务就可以了(结论中对此有更多的介绍)

时隙可以是一秒钟,更多秒或更短的时间。唯一的限制是Python中时间测量的精度。

如果您的资源具有每秒定义的硬限制,则应使用时隙1.0

在首次请求访问资源时,为下一个时隙设置开始时间并初始化请求计数器。

对于每个请求,请增加请求计数器(针对当前时隙)并允许该请求,除非您在当前时隙中已达到允许的最大请求数。

您使用的服务器可能分布在更多计算机上。要提供对LockerServer的访问,您将使用zmq。

zmqlocker.py:

import time
import zmq

class Locker():
    def __init__(self, max_requests=1, in_seconds=1.0):
        self.max_requests = max_requests
        self.in_seconds = in_seconds
        self.requests = 0
        Now = time.time()
        self.next_slot = Now + in_seconds

    def __iter__(self):
        return self

    def next(self):
        Now = time.time()
        if Now > self.next_slot:
            self.requests = 0
            self.next_slot = Now + self.in_seconds
        if self.requests < self.max_requests:
            self.requests += 1
            return "go"
        else:
            return "sorry"


class LockerServer():
    def __init__(self, max_requests=1, in_seconds=1.0, url="tcp://*:7777"):
        locker=Locker(max_requests, in_seconds)
        cnt = zmq.Context()
        sck = cnt.socket(zmq.REP)
        sck.bind(url)
        while True:
            msg = sck.recv()
            sck.send(locker.next())

class LockerClient():
    def __init__(self, url="tcp://localhost:7777"):
        cnt = zmq.Context()
        self.sck = cnt.socket(zmq.REQ)
        self.sck.connect(url)
    def next(self):
        self.sck.send("let me go")
        return self.sck.recv()

run_server.py:

from zmqlocker import LockerServer

svr = LockerServer(max_requests=5, in_seconds=0.8)

从命令行:

$ python run_server.py

这将在localhost的认端口7777上开始提供更衣室服务。

run_client.py:

from zmqlocker import LockerClient
import time

locker_cli = LockerClient()

for i in @R_403_1567@(100):
    print time.time(), locker_cli.next()
    time.sleep(0.1)

从命令行:

$ python run_client.py

您将看到“ go”,“ go”,“ sorry” …打印的答复。

尝试运行更多客户端。

您可以先启动客户端,然后再启动服务器。客户端将阻塞直到服务器启动,然后才能愉快地运行。

另一方面,您可能会发现资源的限制并没有您想象的那么可预测,因此请准备好使用参数来找到适当的平衡,并始终为此做好准备以应对异常情况。

还有一些空间可以优化提供“锁”的功能- 例如,如果储物柜用完了所允许的请求,但是当前时隙已经快要完成了,您可以考虑稍等一下“抱歉”,在不到一秒钟的时间内提供“进入” ”。

通过“分布式”,我们还可以了解多个一起运行的更衣室服务器。这更难做到,但也是可能的。zmq允许非常容易地连接到多个URL,因此客户端可以真正轻松地连接到多个储物柜服务器。有一个问题,如何协调更衣室服务器以不允许对资源的过多请求。zmq允许服务器间通信。一种模型可能是,每个储物柜服务器将在PUB / SUB上发布每个提供的“开始”。所有其他更衣室服务器都将被订阅,并使用每个“去”来增加其本地请求计数器(使用稍微修改的逻辑)。

python 2022/1/1 18:36:44 有237人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶