使用Python3时, Redis
(实际上 Flask
以及 Flask-Redis
),我经常发现自己处于这样一种情况:我用
data = redis_client.hgetall(id)
更改一些值,然后使用
redis_client.hset(id, data)
这显然不是线程安全的,所以我使用我在这里找到的实现添加了线程锁:
基于值的线程锁
import threading
namespace_lock = threading.Lock()
namespace = {}
counters = {}
def aquire_lock(value):
with namespace_lock:
if value in namespace:
counters[value] += 1
else:
namespace[value] = threading.Lock()
counters[value] = 1
namespace[value].acquire()
def release_lock(value):
with namespace_lock:
if counters[value] == 1:
del counters[value]
lock = namespace.pop(value)
else:
counters[value] -= 1
lock = namespace[value]
lock.release()
# sample usage
def foo(id):
aquire_lock(id)
data = redis_client.hgetall(id)
# ...
redis_client.hset(id, data)
release_lock(id)
当在一个节点上运行多个线程时,这种方法工作得很好,但是当在一个节点平衡器后面运行多个节点时,锁的信息不会在它们之间共享。
锁定访问权限的通常策略是什么 Redis
资源,当多个节点访问同一个数据库时?
到目前为止我已经试过了 Redlock
(实际上 Flask-Redlock
),是什么导致了这样的代码:
from flask_redlock import RedisLock
redis_lock = RedisLock()
redis_lock.init_app(app)
with redis_lock.lock(f'{id}.lock', 3000, retry=10, interval=0.2) as lock:
if not lock:
return 'busy!'
# Code Execution Part
time.sleep(10)
但这允许我在 sleep
第一道螺纹的加工方法。因此,我得出结论,它可能只保护与 Redis
.
1条答案
按热度按时间b1zrtrql1#
好吧,你用错了红瓶。3000是ttl,这意味着锁将在3秒后自动过期,而您的睡眠时间是10秒。
如果测试代码,您会发现其他线程无法在3秒内获得锁。如果执行需要n秒,则总是锁定n+delta(delta>0)秒。在我看来,你应该加上至少2秒作为增量,2秒是锁定/解锁组合的往返时间,甚至你可以采取更多的假设你会解锁锁一旦你完成使用。