【问题标题】:Redis: Threading Locks On Multiple Nodes [Python]Redis:多个节点上的线程锁 [Python]
【发布时间】:2021-01-06 04:37:13
【问题描述】:

在使用 Python3,Redis(实际上是 FlaskFlask-Redis)时,我经常发现自己处于从 Redis DB 加载数据的情况

data = redis_client.hgetall(id)

更改一些值,然后再次存储数据

redis_client.hset(id, data)

这显然不是线程安全的,所以我添加了线程锁,使用我在这里找到的实现:

value based thread lock

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


    【解决方案1】:

    好吧,你错误地使用了 Flask-Redlock。 3000 是 TTL,表示锁会在 3 秒后自动过期,而你的睡眠时间是 10 秒。

    如果您测试您的代码,您会发现其他线程无法在 3 秒内获得锁。如果您的执行需要 N 秒而不是总是锁定 N+delta (delta > 0) 秒。 IMO 你应该添加至少 2 秒作为增量,2 秒是锁定/解锁组合的往返时间,即使你可以采取更多,因为一旦你完成使用就会解锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-23
      相关资源
      最近更新 更多