【发布时间】:2021-01-06 04:37:13
【问题描述】:
在使用 Python3,Redis(实际上是 Flask 和 Flask-Redis)时,我经常发现自己处于从 Redis DB 加载数据的情况
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 直接相关的功能。
【问题讨论】:
标签: python multithreading flask networking redis