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

适用于Python的分布式锁管理器,第1张

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

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

需求审查

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

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

  • 自动解锁

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

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

概念在时隙内限制请求数

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

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

监视每个时隙的请求数,直到下一个请求开始

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

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

与REQ / REP一起使用zmq

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

样例代码

zmqlocker.py:

import timeimport zmqclass 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 LockerServersvr = LockerServer(max_requests=5, in_seconds=0.8)

从命令行:

$ python run_server.py

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

运行您的客户

run_client.py:

from zmqlocker import LockerClientimport timelocker_cli = LockerClient()for i in xrange(100):    print time.time(), locker_cli.next()    time.sleep(0.1)

从命令行:

$ python run_client.py

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

尝试运行更多客户端。

一点压力测试

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

结论
  • 满足描述的要求
    • 请求数量有限
    • 无需解锁,它允许在下一个时隙可用时发出更多请求
    • 可通过网络或本地套接字使用LockerService。
  • 应该可靠,zmq是成熟的解决方案,python代码相当简单
  • 它不需要所有参与者之间的时间同步
  • 性能会很好

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

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

将其扩展到真正的分布式锁管理器

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



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5623778.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存