Redis 实战——不公平信号量
Redis in action - unfair semaphore
我正在阅读 Redis in action e-book chapter about semaphores。这是使用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
This basic semaphore works well—it’s simple, and it’s very fast. But
relying on every process having access to the same system time in
order to get the semaphore can cause problems if we have multiple
hosts. This isn’t a huge problem for our specific use case, but if we
had two systems A and B, where A ran even 10 milliseconds faster than
B, then if A got the last semaphore, and B tried to get a semaphore
within 10 milliseconds, B would actually “steal” A’s semaphore without
A knowing it.
我没听懂是什么意思:if A ran even 10 milliseconds faster than B
then 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 的信号量。但是书中描述的情况并非如此。
如果B比A慢10毫秒,那么B的分数比A小,因为我们使用本地时间作为sorted set的分数。
所以B的排名,即pipeline.zrank(semname, identifier)
,小于A的排名,即小于limit
,即if pipeline.execute()[-1] < limit:
。 B认为它得到了信号量,即return identifier
。事实上,它窃取了 A 的信号量
我正在阅读 Redis in action e-book chapter about semaphores。这是使用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
This basic semaphore works well—it’s simple, and it’s very fast. But relying on every process having access to the same system time in order to get the semaphore can cause problems if we have multiple hosts. This isn’t a huge problem for our specific use case, but if we had two systems A and B, where A ran even 10 milliseconds faster than B, then if A got the last semaphore, and B tried to get a semaphore within 10 milliseconds, B would actually “steal” A’s semaphore without A knowing it.
我没听懂是什么意思:if A ran even 10 milliseconds faster than B
then 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 的信号量。但是书中描述的情况并非如此。
如果B比A慢10毫秒,那么B的分数比A小,因为我们使用本地时间作为sorted set的分数。
所以B的排名,即pipeline.zrank(semname, identifier)
,小于A的排名,即小于limit
,即if pipeline.execute()[-1] < limit:
。 B认为它得到了信号量,即return identifier
。事实上,它窃取了 A 的信号量