赞
踩
- <?php
- /**
- * Created by PhpStorm.
- * User: Hank
- * Date: 2019/3/25 0025
- * Time: 下午 15:14
- */
-
- namespace App\Lib\Redis;
-
-
- use Predis\ClientInterface;
-
- /**
- * redis锁
- * 安全和可靠性保证
- 在描述我们的设计之前,我们想先提出三个属性,这三个属性在我们看来,是实现高效分布式锁的基础。
- 一致性:互斥,不管任何时候,只有一个客户端能持有同一个锁。
- 分区可容忍性:不会死锁,最终一定会得到锁,就算一个持有锁的客户端宕掉或者发生网络分区。
- 可用性:只要大多数Redis节点正常工作,客户端应该都能获取和释放锁。
- * Class RedisLock
- * @author hank
- * @package App\Lib\Redis
- */
- class RedisLock
- {
- const LOCK_REDIS_KEY_PREFIX = "LOCK_KEY:";
- /**
- * @var ClientInterface
- */
- private $redis;
-
- /**
- * RedisLock constructor.
- * @param ClientInterface $redis
- */
- public function __construct(ClientInterface $redis)
- {
- $this->redis = $redis;
- }
-
- /**
- * 获得锁
- * @param $key
- * @param $timeout int 超时秒数默认10秒
- * @return bool|int 获得成功锁返回随机value
- */
- public function lock($key, $timeout = 10){
- $myRandomValue = mt_rand();
- $key = self::LOCK_REDIS_KEY_PREFIX.$key;
- if($this->redis->eval("return redis.call('SET', KEYS[1], KEYS[2], 'NX', 'PX', KEYS[3])", 3, $key, $myRandomValue, $timeout*1000)){
- return $myRandomValue;
- }
- return false;
- }
-
- /**
- * 解锁
- * !这里如果锁自动过期不存在了也返回 解锁成功true!
- * @param $key
- * @param $myRandomValue int 解锁随机值
- * @return bool
- */
- public function unLock($key, $myRandomValue){
- $key = self::LOCK_REDIS_KEY_PREFIX.$key;
- 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)){
- return true;
- }
- return false;
- }
- }
这里需要明白为什么使用lua脚本,因为redis的lua脚本是原子性(事务)的,加锁解锁整个过程必须保证原子性(事务),具体的原理可以参考:《Redis官方文档》用Redis构建分布式锁
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。