redis_lock.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. # -*- coding: utf-8 -*-
  2. # @Time : 2019/9/30 22:03
  3. # @Author : CRJ
  4. # @File : utils.py
  5. # @Software: PyCharm
  6. # @Python3.6
  7. import math
  8. import time
  9. import uuid
  10. import redis
  11. # 获取锁(乐观锁)
  12. def acquire_lock_with_timeout(conn, lockname, acquire_timeout=5, lock_timeout=10):
  13. # 128位随机标识符
  14. identifier = str(uuid.uuid4())
  15. lockname = 'lock:' + lockname
  16. lock_timeout = int(math.ceil(lock_timeout)) # 确保传给exprie是整数
  17. end = time.time() + acquire_timeout
  18. while time.time() < end:
  19. if conn.setnx(lockname, identifier):
  20. conn.expire(lockname, lock_timeout)
  21. return identifier
  22. elif not conn.ttl(lockname): # 为没有设置超时时间的锁设置超时时间
  23. conn.expire(lockname, lock_timeout)
  24. time.sleep(0.001)
  25. return False
  26. # 释放锁(乐观锁)
  27. def release_lock(conn, lockname, identifier):
  28. lockname = 'lock:' + lockname
  29. with conn.pipeline(True) as pipe:
  30. while True:
  31. try:
  32. pipe.watch(lockname)
  33. value = pipe.get(lockname)
  34. # 判断标志是否相同
  35. if value is not None and value == identifier:
  36. pipe.multi()
  37. pipe.delete(lockname)
  38. pipe.execute()
  39. return True
  40. # 不同则直接退出 return False
  41. pipe.unwatch()
  42. break
  43. except redis.exceptions.WatchError:
  44. pass
  45. return False