我正在读红色电子图书关于信号量的章节。下面是使用redis实现信号量的python代码
def acquire_semaphore(conn, semname, limit, timeout=10):
identifier = str(uuid.uuid4())
now = time.time()
pipeline = conn.pipeline(True)
pipeline.zremrangebyscore(semname, '-inf', now - timeout)
pipeline.zadd(semname, identifier, now)
pipeline.zrank(semname, identifier)
if pipeline.execute()[-1] < limit:
return identifier
conn.zrem(semname, identifier)
return None这个基本的信号量工作得很好--它很简单,而且非常快。但是,如果我们有多个主机,那么依赖于每个进程访问相同的系统时间来获取信号量可能会导致问题。对于我们的具体用例来说,这不是一个大问题,但是如果我们有两个系统A和B,其中A甚至比B快10毫秒,那么如果A得到最后一个信号量,B试图在10毫秒内得到一个信号量,B实际上会在A不知道的情况下“窃取”A的信号量。
我不明白这是什么意思:如果A ran even 10 milliseconds faster than B那么B would actually “steal” A’s semaphore without A knowing it.
我的想法是:A的时间是10:10:10:200,B的时间是10:10:10:190和A有信号量。然后B试图在10毫秒内获得信号量(现在B的本地时间是10:10:10:200)。B将删除过期项目并添加它。B怎么能steal A的信号量?同时,如果A的时间是10:59,B的时间是11:02,则当B由于时差而删除A的信号量时是可能的。但这不是书上描述的情况。
发布于 2018-07-30 15:45:16
如果B比A慢10 ms,则B的分数小于A,因为我们使用本地时间作为排序集的分数。
因此,B的秩,即pipeline.zrank(semname, identifier),小于A的秩,A的秩小于limit,即if pipeline.execute()[-1] < limit:。B认为它得到了信号量,即return identifier。事实上,它从A.
https://stackoverflow.com/questions/51595786
复制相似问题