在分布式应用中经常需要用到分布式锁。
redis使用set命令来实现分布式锁
SET key value [EX seconds] [PX milliseconds] [NX|XX]
直接使用该命令构建的redis分布式锁是不像jdk的reentrantlock具有可重入性的,使用线程的ThreadLocal变量存储当前持有锁的计数,可以实现redis分布式锁的可重入性。
另外Redis分布式锁有超时的问题,不要用于耗时较长的任务.如果真的有耗时较长的任务需要锁,建议使用数据库的乐观锁来解决。
import redis
import threading
HOST = '127.0.0.1'
PORT = '6379'
PASSWORD = ''
pool = redis.ConnectionPool(host=HOST, port=PORT, password=PASSWORD, max_connections=1024)
conn = redis.Redis(connection_pool=pool)
locks = threading.local()
locks.redis = {
}
def key_for(user_id):
return "account_{}".format(user_id)
def _lock(client, key):
print("redis lock ")
return bool(client.set(name=key, value="1", nx=True, ex=5))
def _unlock(client, key):
print("redis un lock")
client.delete(key)
def lock(client, user_id):
key = key_for(user_id)
if key in locks.redis:
locks.redis[key] += 1
return True
ok = _lock(client, key)
if not ok:
return False
locks.redis[key] = 1
return True
def unlock(client, user_id):
key = key_for(user_id)
if key in locks.redis:
locks.redis[key] -= 1
if locks.redis[key] <= 0:
del locks.redis[key]
_unlock(client, key)
return True
return False
print(lock(conn, "codehole"))
print(lock(conn, "codehole"))
print(unlock(conn, "codehole"))
print(unlock(conn, "codehole"))
输出
输出
redis lock
True
True
unlock
True
redis un lock
True
参考资料<