66 @date:2023/9/11 11:45
77 @desc:
88"""
9- from datetime import timedelta
9+ from functools import wraps
1010
11+ import uuid_utils .compat as uuid
1112from django .core .cache import caches
13+ from django_redis import get_redis_connection
1214
1315memory_cache = caches ['default' ]
1416
17+ class RedisLock ():
18+ def __init__ (self ):
19+ self .lock_value = None
1520
16- def try_lock (key : str , timeout = None ):
17- """
18- 获取锁
19- :param key: 获取锁 key
20- :param timeout 超时时间
21- :return: 是否获取到锁
22- """
23- if timeout is None :
24- timeout = 3600 # 默认超时时间为3600秒
25- return memory_cache .add (key , 'lock' , timeout = timeout )
21+ def try_lock (self , key : str , timeout = None ):
22+ """
23+ 获取锁
24+ :param key: 获取锁 key
25+ :param timeout 超时时间
26+ :return: 是否获取到锁
27+ """
28+ redis_client = get_redis_connection ("default" )
29+ if timeout is None :
30+ timeout = 3600 # 默认超时时间为3600秒
31+ self .lock_value = str (uuid .uuid7 ())
32+ return redis_client .set (key , self .lock_value , nx = True , ex = timeout )
2633
2734
28- def un_lock (key : str ):
29- """
30- 解锁
31- :param key: 解锁 key
32- :return: 是否解锁成功
33- """
34- return memory_cache .delete (key )
35+ def un_lock (self , key : str ):
36+ """
37+ 解锁
38+ :param key: 解锁 key
39+ :return: 是否解锁成功
40+ """
41+ redis_client = get_redis_connection ("default" )
42+ unlock_script = """
43+ if redis.call("get", KEYS[1]) == ARGV[1] then
44+ return redis.call("del", KEYS[1])
45+ else
46+ return 0
47+ end
48+ """
49+ redis_client .eval (unlock_script , 1 , key , self .lock_value )
3550
3651
3752def lock (lock_key , timeout = None ):
@@ -43,15 +58,19 @@ def lock(lock_key, timeout=None):
4358
4459 """
4560
46- def inner (func ):
47- def run (* args , ** kwargs ):
61+ def decorator (func ):
62+ @wraps (func )
63+ def wrapper (* args , ** kwargs ):
4864 key = lock_key (* args , ** kwargs ) if callable (lock_key ) else lock_key
65+ rlock = RedisLock ()
66+ if not rlock .try_lock (key , timeout ):
67+ # 获取锁失败,可自定义异常或返回
68+ return None
4969 try :
50- if try_lock (key = key , timeout = timeout ):
51- return func (* args , ** kwargs )
70+ return func (* args , ** kwargs )
5271 finally :
53- un_lock (key = key )
72+ rlock . un_lock (key )
5473
55- return run
74+ return wrapper
5675
57- return inner
76+ return decorator
0 commit comments