如果进程死掉,释放redis锁

Mat*_*ini 1 python concurrency locking redis celery

我正在使用 Redis 分布式锁来确保某些 celery 任务不会同时运行。为了使用 redis 管理锁,我使用 python redis库版本4.0.0(它指定任何死锁问题都应该由程序员处理)。

由于我想避免使用锁的超时参数,因为任务执行时间变化很大,所以我想知道是否有一种方法可以验证活动锁是否确实由进程拥有,并且它具有没有因为应用程序突然崩溃而无法释放而被阻止。

@shared_task(
    name='test_task',
    queue="test"
)
def test(value):
    lock_acquired = False
    try:
        lock = redis_cli.lock('test_lock', sleep=1)
        lock_acquired = lock.acquire(blocking=False)        
        if lock_acquired:
            print(f"HELLO FROM: {value}")
            sleep(15)
        else:
            print(f"LOCKED")
    except Exception as e:
        print(str(e)) 
    finally:
        if lock_acquired:
            lock.release()
Run Code Online (Sandbox Code Playgroud)

就上面的代码而言,如果应用程序在 sleep (15)期间意外崩溃,则该锁仍将在下次执行时被锁定,即使获取它的进程不再存在。我怎样才能防止这种情况发生?

蟒蛇版本:3.6.8

Redis服务器版本:Redis服务器v=4.0.9 sha=00000000:0 malloc=jemalloc-3.6.0 位=64 build=9435c3c2879311f3

芹菜==5.1.1

for*_*ack 5

因为我想避免使用锁的超时参数

为了避免即使客户端崩溃也保持锁定,您必须设置超时。

由于任务执行时间变化很大,我想知道是否有一种方法可以验证活动锁是否确实由进程拥有

您可以使用看门狗线程来监视锁。假设您设置了 5 秒的超时时间,看门狗线程会延长锁定时间,即每 3 秒更新一次 TTL。当你的任务完成后,停止看门狗线程,并删除密钥,即释放锁。

如果您的客户端崩溃,看门狗线程也会崩溃,并且不再延长锁定。当钥匙过期后,其他人可以再次持有锁。

我对Python客户端不熟悉,但我编写了一个C++客户端,它实现了上述看门狗算法。您可以参考该文档