首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python的分布式锁管理器

Python的分布式锁管理器
EN

Stack Overflow用户
提问于 2014-04-12 22:39:42
回答 5查看 12.2K关注 0票数 12

我有一堆服务器,其中有多个实例,它们访问的资源对每秒的请求有很大的限制。

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

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

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

我是否可以使用python接口对其进行很好的测试?

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-04-22 18:39:21

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

需求审查

在描述解决方案之前,让我回顾一下您的需求。

  • 将某些资源的请求数量限制为固定时间内的若干请求。
  • 自动解锁
  • 资源(自动)解锁的时间应在1秒以内。
  • 应分发。我将假设,您的意思是多个分布式服务器使用一些资源应该是可以的,只要有一个储物柜服务就行了(关于它的更多信息,请看结论)。

概念

限制时隙内的请求数量

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

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

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

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

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

使用REQ/REP使用zmq服务

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

样本代码

zmqlocker.py:

代码语言:javascript
复制
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:

代码语言:javascript
复制
from zmqlocker import LockerServer

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

从命令行:

代码语言:javascript
复制
$ python run_server.py

这将开始在本地主机上的默认端口7777上提供锁存器服务。

管理你的客户

run_client.py:

代码语言:javascript
复制
from zmqlocker import LockerClient
import time

locker_cli = LockerClient()

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

从命令行:

代码语言:javascript
复制
$ python run_client.py

你会看到“去”,“去”,“对不起”.打印答复。

试着运行更多的客户。

一点压力测试

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

结论

  • 所描述的需求已满足
    • 请求数量有限
    • 不需要解锁,只要有下一个时隙,就允许更多的请求。
    • LockerService可通过网络或本地套接字获得。

  • 它应该是可靠的,zmq是成熟的解决方案,python代码相当简单。
  • 它不需要所有参与者之间的时间同步。
  • 表现会很好

另一方面,您可能会发现,您的资源限制并不像您假设的那样可预测,所以要准备好使用参数来找到适当的平衡,并且总是为这方面的异常做好准备。

也有一些优化提供“锁”的空间--例如,如果储物柜用完了允许的请求,但是当前的时隙已经几乎完成,您可能会考虑用“对不起”等待一会儿,在第二次提供“开始”一小部分之后。

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

通过“分布式”,我们也可以理解多个储物柜服务器一起运行。这是比较困难的,但也是可能的。zmq允许非常容易地连接到多个urls,因此客户端可以非常容易地连接到多个锁存服务器。有一个问题,如何协调储物柜服务器不允许太多的请求你的资源。zmq允许服务器间通信.一种模式可能是,每个储物柜服务器都会在PUB/SUB上发布每个提供的"go“。所有其他的锁存服务器都将被订阅,并使用每个"go“来增加它们的本地请求计数器(稍微修改了一些逻辑)。

票数 20
EN

Stack Overflow用户

发布于 2022-06-15 17:11:01

实现这一点的最低努力方式是使用可锁

它提供了低级别的锁语义,并附带了一个Python客户端。重要的是,您不需要设置任何数据库或服务器,它通过在可锁定服务器上存储锁来工作。

锁有可变的TTL,但您也可以提前释放它们:

代码语言:javascript
复制
$ pip install lockable-dev
代码语言:javascript
复制
from lockable import Lock

my_lock = Lock('my-lock-name')

# acquire the lock
my_lock.acquire()

# release the lock
my_lock.release()
票数 2
EN

Stack Overflow用户

发布于 2014-04-23 23:54:52

对于我的集群,我将ZooKeeper与python库一起用于队列和锁。

为您的目的从kazoo api文档中修改的示例:http://kazoo.readthedocs.org/en/latest/api/recipe/lock.html

代码语言:javascript
复制
zk = KazooClient()
lock = zk.Lock("/lockpath", "my-identifier")
if lock.acquire(timeout=1):

   code here

   lock.release()

但我记得,ZooKeeper至少需要三个节点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23036990

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档