LockService.php 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. <?php
  2. namespace crmeb\services;
  3. use Swoole\Coroutine\System;
  4. use think\facade\Cache;
  5. class LockService
  6. {
  7. /**
  8. * @param $key
  9. * @param $fn
  10. * @param int $ex
  11. * @throws \Throwable
  12. */
  13. public function exec($key, $fn, int $ex = 6)
  14. {
  15. try {
  16. $this->lock($key, $key, $ex);
  17. return $fn();
  18. } finally {
  19. $this->unlock($key, $key);
  20. }
  21. }
  22. public function tryLock($key, $value = '1', $ex = 6)
  23. {
  24. return Cache::store('redis')->handler()->set('lock_' . $key, $value, ["NX", "EX" => $ex]);
  25. }
  26. public function lock($key, $value = '1', $ex = 6)
  27. {
  28. if ($this->tryLock($key, $value, $ex)) {
  29. return true;
  30. }
  31. System::sleep(1);
  32. return $this->lock($key, $value, $ex);
  33. }
  34. public function unlock($key, $value = '1')
  35. {
  36. $script = <<< EOF
  37. if (redis.call("get", "lock_" .. KEYS[1]) == ARGV[1]) then
  38. return redis.call("del", "lock_" .. KEYS[1])
  39. else
  40. return 0
  41. end
  42. EOF;
  43. return Cache::store('redis')->handler()->eval($script, [$key, $value], 1) > 0;
  44. }
  45. }