redis_lock.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # !/usr/bin/python
  2. # -*- encoding: utf-8 -*-
  3. """
  4. @Time : 2025/07/30 14:40
  5. @Author :
  6. @File : RedisLock.py
  7. @Software: VScode
  8. @Desc : None
  9. """
  10. import time
  11. import uuid
  12. class RedisLock:
  13. """
  14. Redis 锁类
  15. """
  16. def __init__(self, redis_client, lock_name, expire_time=30):
  17. """
  18. :param redis_client: Redis 客户端连接
  19. :param lock_name: 锁的名称
  20. :param expire_time: 锁的过期时间(秒)
  21. """
  22. self.redis = redis_client
  23. self.lock_name = lock_name
  24. self.expire_time = expire_time
  25. self.identifier = str(uuid.uuid4()) # 唯一标识,用于安全释放锁
  26. def acquire(self, timeout=10):
  27. """
  28. 获取锁
  29. :param timeout: 获取锁的超时时间(秒)
  30. :return: 是否成功获取锁
  31. """
  32. end = time.time() + timeout
  33. while time.time() < end:
  34. # 尝试获取锁
  35. if self.redis.set(self.lock_name, self.identifier, nx=True, ex=self.expire_time):
  36. return True
  37. time.sleep(0.001) # 短暂等待后重试
  38. return False
  39. def release(self):
  40. """
  41. 释放锁
  42. """
  43. # 使用 Lua 脚本保证原子性
  44. unlock_script = """
  45. if redis.call("get", KEYS[1]) == ARGV[1] then
  46. return redis.call("del", KEYS[1])
  47. else
  48. return 0
  49. end
  50. """
  51. self.redis.eval(unlock_script, 1, self.lock_name, self.identifier)
  52. def __enter__(self):
  53. if not self.acquire():
  54. raise Exception("Could not acquire lock")
  55. return self
  56. def __exit__(self, exc_type, exc_val, exc_tb):
  57. self.release()