gpt4 book ai didi

python - Python的分布式锁管理器

转载 作者:太空狗 更新时间:2023-10-29 18:00:15 27 4
gpt4 key购买 nike

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

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

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

不幸的是,似乎有一个分钟。锁定时间为 1 秒,相对不可靠。在多项测试中,解锁 1 秒锁需要 1 到 3 秒。

是否有经过良好测试的 python 接口(interface)可以用于此目的?

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

最佳答案

我的第一个想法是使用 Redis。但是有更多很棒的工具,有些甚至更轻巧,所以我的解决方案建立在 zmq 之上。因此,您不必运行 Redis,运行小型 Python 脚本就足够了。

需求审查

在描述解决方案之前,让我先看看您的要求。

  • 限制在固定时间段内对某些资源的请求数。

  • 自动解锁

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

  • 它应该被分发。我会假设,你的意思是多个分布式服务器消耗一些资源应该能够并且只有一个储物柜服务就可以了(更多关于它的结论)

概念

限制时间段内的请求数

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

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

在下一个开始之前监控每个时隙的请求数

第一次请求访问您的资源时,设置下一个时间段的开始时间并初始化请求计数器。

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

使用带有 REQ/REP 的 zmq 服务

您的消费服务器可以分布在更多计算机上。要提供对 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()

运行你的服务器:

运行服务器.py:

from zmqlocker import LockerServer

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

从命令行:

$ python run_server.py

这将在本地主机的默认端口 7777 上开始提供储物柜服务。

运行你的客户端

run_client.py:

from zmqlocker import LockerClient
import time

locker_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 上发布每个提供的“go”。所有其他储物柜服务器都将被订阅,并使用每个“go”来增加它们的本地请求计数器(逻辑略有修改)。

关于python - Python的分布式锁管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23036990/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com