我在redis中的一个流水线/事务中遇到了一些奇怪的行为,这让我怀疑代码实际上是在一个事务中执行的:
class RedisThread:
KEY = "threading_test"
def __init__(self, id:int):
self._redis = Redis(host="localhost", port=6379, db=0)
self._id = id
self._redis.delete(self.KEY)
def __call__(self, *args,**kwargs):
results = []
for i in range(3):
# Transaction
pipe = self._redis.pipeline(transaction=True)
# ZADD current time as score
pipe.zadd(self.KEY, {f"{self._id}-{i}": time.time()})
# ZRANK
pipe.zrank(self.KEY, f"{self._id}-{i}")
# Commit and get result of ZRANK
results.append(str(pipe.execute()[1]))
print(", ".join(results))
threads = [
threading.Thread(target=RedisThread(1)),
threading.Thread(target=RedisThread(2)),
threading.Thread(target=RedisThread(3)),
threading.Thread(target=RedisThread(4)),
threading.Thread(target=RedisThread(5)),
]
for t in threads:
t.start()
for t in threads:
t.join()
当我运行此代码时,结果如下:
1, 5, 9
3, 6, 10
0, 3, 13
4, 11, 12
1, 4, 13
请注意,线程之间存在重复的值。因为我正在做一个zrank,并且我添加到集合中的值(通过zadd)是基于时间的(因此值总是在增加),所以我不应该看到任何重复的,但是有重复的。。。
1条答案
按热度按时间oxcyiej71#
redis事务是原子的。问题是你用
time()
作为得分。因为程序运行得很快,所以
time()
对于多个调用可能返回相同的结果。换句话说,在排序集中设置具有相同分数的成员。如果成员的分数相同,则按词典顺序排列。
现在,让我们看看为什么会有重复的值:
thread1的第二个事务在thread2的第一个事务之后执行,并且
1-1
小于2-0
按词典顺序。所以当thread1的第二个事务执行时,1-1
将在之前插入2-0
,这就是为什么他们都获得了这个级别:1
.