当前位置:   article > 正文

php redis分布式互斥锁(基于lua脚本保证原子性)_php redis互斥锁

php redis互斥锁
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Hank
  5. * Date: 2019/3/25 0025
  6. * Time: 下午 15:14
  7. */
  8. namespace App\Lib\Redis;
  9. use Predis\ClientInterface;
  10. /**
  11. * redis锁
  12. * 安全和可靠性保证
  13. 在描述我们的设计之前,我们想先提出三个属性,这三个属性在我们看来,是实现高效分布式锁的基础。
  14. 一致性:互斥,不管任何时候,只有一个客户端能持有同一个锁。
  15. 分区可容忍性:不会死锁,最终一定会得到锁,就算一个持有锁的客户端宕掉或者发生网络分区。
  16. 可用性:只要大多数Redis节点正常工作,客户端应该都能获取和释放锁。
  17. * Class RedisLock
  18. * @author hank
  19. * @package App\Lib\Redis
  20. */
  21. class RedisLock
  22. {
  23. const LOCK_REDIS_KEY_PREFIX = "LOCK_KEY:";
  24. /**
  25. * @var ClientInterface
  26. */
  27. private $redis;
  28. /**
  29. * RedisLock constructor.
  30. * @param ClientInterface $redis
  31. */
  32. public function __construct(ClientInterface $redis)
  33. {
  34. $this->redis = $redis;
  35. }
  36. /**
  37. * 获得锁
  38. * @param $key
  39. * @param $timeout int 超时秒数默认10秒
  40. * @return bool|int 获得成功锁返回随机value
  41. */
  42. public function lock($key, $timeout = 10){
  43. $myRandomValue = mt_rand();
  44. $key = self::LOCK_REDIS_KEY_PREFIX.$key;
  45. if($this->redis->eval("return redis.call('SET', KEYS[1], KEYS[2], 'NX', 'PX', KEYS[3])", 3, $key, $myRandomValue, $timeout*1000)){
  46. return $myRandomValue;
  47. }
  48. return false;
  49. }
  50. /**
  51. * 解锁
  52. * !这里如果锁自动过期不存在了也返回 解锁成功true!
  53. * @param $key
  54. * @param $myRandomValue int 解锁随机值
  55. * @return bool
  56. */
  57. public function unLock($key, $myRandomValue){
  58. $key = self::LOCK_REDIS_KEY_PREFIX.$key;
  59. if($this->redis->eval("if redis.call('EXISTS',KEYS[1]) == 0 then return 1 else if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end end", 1, $key, $myRandomValue)){
  60. return true;
  61. }
  62. return false;
  63. }
  64. }

这里需要明白为什么使用lua脚本,因为redis的lua脚本是原子性(事务)的,加锁解锁整个过程必须保证原子性(事务),具体的原理可以参考:《Redis官方文档》用Redis构建分布式锁

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号