一、实现原理
使用redis里字符类型:SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]
EX seconds
设置指定的到期时间(以秒为单位)。PX milliseconds
设置指定的到期时间(以毫秒为单位)。NX
仅在键不存在时设置键。XX
只有在键已存在时才设置。
二、Python实现分布式锁
# redis实现分布式锁
import time
import threading
import redis
class RedisLock:
def __init__(self):
self.redis_client = redis.StrictRedis(host="localhost", port=6379, db=0)
self._lockid = None
def get_lock(self, name, timeout):
"""
加锁
:param name: 锁名
:param timeout: 超时时间
:return: 加锁成功返回True; 加锁失败返回False
"""
query_val = self.redis_client.get(name)
if query_val:
return False
self._lockid = int(time.time() * 1000)
lock_val = f"lock_{self._lockid}"
set_result = self.redis_client.set(name=name, value=lock_val, ex=timeout, nx=True)
return set_result
def release_lock(self, name):
"""
释放锁
:param name: 锁名
:return: 释放成功返回True; 释放失败返回False
"""
query_val = self.redis_client.get(name)
if not query_val:
return True
if query_val.decode("utf-8") == f"lock_{self._lockid}":
del_nb = self.redis_client.delete(name) # 获取到的是删除的条数
return del_nb > 0
return False
# ######################################## 多个线程去竞争锁
def run_task(rds_obj, lockname, timeout):
lock_status = rds_obj.get_lock(lockname, timeout)
print(f"rds_obj--{id(rds_obj)}: current lock status is {lock_status}")
rds_list = []
for i in range(1, 4):
rds_obj = RedisLock()
rds_list.append(rds_obj)
timeout = i * 5
lock_name = "mylock"
td = threading.Thread(target=run_task, args=(rds_obj, lock_name, timeout))
td.start()
td.join()
'''
结果输出:
rds_obj--2573431598928: current lock status is True # 第一个线程获取锁成功
rds_obj--2573430176272: current lock status is False # 第二、三个线程获取锁失败
rds_obj--2573470176656: current lock status is False
'''
# ######################################## 倒序逐个去释放锁
while rds_list:
rds_obj_pop = rds_list.pop()
release_status = rds_obj_pop.release_lock("mylock")
print(f"rds_obj--{id(rds_obj_pop)}: release lock status is {release_status}")
'''
结果输出:
rds_obj--2573470176656: release lock status is False # 第三、二个线程释放锁失败
rds_obj--2573430176272: release lock status is False
rds_obj--2573431598928: release lock status is True # 第一个线程释放锁成功
'''