背景
最近遇到了一个需要使用独占锁来保证业务正确性的场景,鉴于服务本身也会使用到 redis 缓存,可以直接利用 redis 提供的锁支持。
基本使用
创建锁
1 | from redis import Redis |
可以直接调用 redis 实例的 lock
方法,并指定锁的名称,超时时间和等待时间(如果未能在 blocking_timeout 内获取到锁,会抛出异常)。
使用锁
1 | lock.acquire() |
调用acquire
方法获取锁,业务逻辑执行完成后调用release
方法释放锁。
使用上下文管理器
手动获取并释放锁的使用方法比较繁琐,并且忘记调用acquire
方法或因为业务逻辑异常导致acquire
方法没有成功调用的风险。我们可以使用上下文管理器来更方便也更安全地使用 redis 锁。
1 | with client.lock(name="key",timeout=60.0,blocking_timeout=5.0): |
这本身也是 RAII(资源获取即初始化) 思想的一个应用。
封装
我们可以使用functools.partial
函数,对 redis 的 lock 使用进行一些简单的封装。
1 | from functools import partial |
我们定义了一个lock
函数,可以指定使用锁时的名称(由prefix
和key
组合而来)、超时时间、等待时间和使用的 redis 实例。
在具体的业务场景中,可以使用functools.partial
函数定义更个性化的锁。
在这个示例中,我们定义了一个a_lock
函数,指定了锁的名称前缀为A
,超时时间为 60 秒。
在使用a_lock
的时候,只需要指定key
即可。
总结
functools.partial
实用性很高,值得在业务中使用。