LockService.php 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. <?php
  2. namespace qiniu\services;
  3. use think\exception\ValidateException;
  4. use think\facade\Cache;
  5. class LockService
  6. {
  7. /**
  8. * @param $key
  9. * @param $fn
  10. * @param int $ex
  11. * @return mixed
  12. * @author 吴汐
  13. * @email 442384644@qq.com
  14. * @date 2023/03/01
  15. */
  16. public function exec($key, $fn, int $ex = 6)
  17. {
  18. try {
  19. if ($this->lock($key, $key, $ex))
  20. return $fn();
  21. else throw new ValidateException('请求太过频繁,请稍后再试');
  22. } finally {
  23. $this->unlock($key, $key);
  24. }
  25. }
  26. public function tryLock($key, $value = '1', $ex = 6)
  27. {
  28. return Cache::store('redis')->handler()->set('lock_' . $key, $value, ["NX", "EX" => $ex]);
  29. }
  30. public function lock($key, $value = '1', $ex = 6)
  31. {
  32. if ($this->tryLock($key, $value, $ex)) {
  33. return true;
  34. } else {
  35. return false;
  36. }
  37. }
  38. public function unlock($key, $value = '1')
  39. {
  40. $script = <<< EOF
  41. if (redis.call("get", "lock_" .. KEYS[1]) == ARGV[1]) then
  42. return redis.call("del", "lock_" .. KEYS[1])
  43. else
  44. return 0
  45. end
  46. EOF;
  47. return Cache::store('redis')->handler()->eval($script, [$key, $value], 1) > 0;
  48. }
  49. }