[ redis基于python分布式锁 ]


基于Python

import time
import uuid
from multiprocessing import Process
import redis

redis_client = redis.Redis(host='42.193.152.252', port='6379', db='0', password='Ww550076')

# 加锁
def acquire_lock(lock_name, args, acquite_timeout=30, time_out=120):
    '''
    lock_name 锁名字
    args 为进程名字
    acquite_timeout 客户端获取锁--循环执行时间
    time_out 分布式锁过期时间
    '''
    identifier = str(uuid.uuid4())
    end = time.time() + acquite_timeout
    lock_names = 'lock_name:' + lock_name
    print(f"进入加锁进程{str(args)} end_time:{end}")
    while time.time() < end:  # 客户端执行时间
        if redis_client.setnx(lock_names, identifier):  # 设置key的值设置为value
            print('正在加锁:进程' + str(args))
            print(f'正在加锁value: {identifier}')
            redis_client.expire(lock_name, time_out)  # 给key设置过期时间
            return identifier
        elif redis_client.ttl(lock_name) == -1:  # 查询key的过期时间, 没设置生存时间返回-1, 不存在-2, 
            redis_client.expire(lock_name, time_out)
        time.sleep(0.01)
    return False  # 客户端超时返回false


# 释放锁
def release_lock(lock_name, identifire):
    lock_names = "lock_name:" + lock_name
    pipe = redis_client.pipeline(True)  # 事务
    print('开始释放锁')
    while True:
        try:
            pipe.watch(lock_names)  # 监控key, key在事务过程中发生改变则失败
            print('释放锁uuid:',pipe.get(lock_names))
            if pipe.get(lock_names).decode() == identifire:
                pipe.multi()  # 队列
                pipe.delete(lock_names)
                pipe.execute() # 提交
                return True
            pipe.unwatch()  # 关闭监控
            print('释放锁完毕')
            break
        except redis.exceptions.WatchError:
            pass # 释放锁时间, 有其他客户端改变了键值对,锁释放失败,进行循环
    return False



# 测试
def exec_test(lock_name, args):
    identifire = acquire_lock(lock_name, args) # 加锁
    # print(f'加锁成功,identifire: {identifire}')
    if identifire:
        time.sleep(3)
        res = release_lock(lock_name, identifire)
        print(f'释放完成:{res}')
    else:
        print('获取redis分布式锁失败,其他进程正在使用')

if __name__ == '__main__':
    for i in range(0, 5):
        Process(target=exec_test, args=('test', i)).start()