背景:
在实际开发场景中,可能会出现多个服务可能会同时调用同一个方法的情况,但是想要保证在一定的时间内该方法只能被一个服务调用。
实现原理:
1.单线程:首先redis本身是单线程的,当有多个线程同时访问redis的时候,一定是一个一个线程的按照顺序的访问redis,因此这是使用redis实现分布式锁的一个原因。
2.原子性:setnx具有原子性,当有多个线程时,只会有一个线程可以使用setnx设置成功。
3.特点:当有重复的锁key的时候setnx查询缓存就会返回false或者空,那我们可以利用它的这种机制去实现多个服务的同时调用一个方法的时候让所有的服务都有互斥的效果。
具体实现代码:
import redis
class LockerException(Exception):
pass
r = redis.Redis(host=REDIS_HOST, port=6379, decode_responses=True)
key_prefix = '项目名'
def set_nx(key, ex=60):
if r.setnx(key_prefix+key, 1):
r.expire(key_prefix+key, ex)
return True
elif r.ttl(key_prefix+key) == -1:
r.expire(key_prefix + key, ex)
return False
# 获取⼀个分布式锁
def acquire_lock(lock_name, ex):
return set_nx(lock_name, ex)
# 释放锁
def release_lock(lock_name):
del_(lock_name)
# 定义一个锁
def lock(lock_key, func, ex=60*5):
locked = False
try:
locked = acquire_lock(lock_key, ex)
if locked:
func()
except Exception as e:
raise LockerException(e)
finally:
if locked:
release_lock(lock_key)
# 使用分布式锁调用函数func_name
def run():
lock('任务名称',func_name)