使用Redis实现分布式可重入锁

在分布式应用中经常需要用到分布式锁。
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

参考资料<>

你可能感兴趣的:(python,Redis)