153 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | ||
| 
 | ||
| namespace traits;
 | ||
| 
 | ||
| use bw\Redis;
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * 缓存
 | ||
|  */
 | ||
| trait CacheTrait
 | ||
| {
 | ||
| 
 | ||
| 
 | ||
|     private $cache_lock_error_msg = "获取锁失败!";
 | ||
| 
 | ||
|     private $cache_lock_thorws_excption = true;
 | ||
| 
 | ||
|     public function setCacheLockThorwsExcption($cache_lock_thorws_excption){
 | ||
|         $this->cache_lock_thorws_excption = $cache_lock_thorws_excption;
 | ||
|         return $this;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public function getCacheLockThorwsExcption(){
 | ||
|         return $this->cache_lock_thorws_excption;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|     public function hasRedis($is_interrupt = false) {
 | ||
|         $error_msg = '';
 | ||
|         try {
 | ||
|             $redis = $this->getRedis();
 | ||
| 
 | ||
|             // 检测连接是否正常
 | ||
|             $redis->ping();
 | ||
|         } catch (\BadFunctionCallException $e) {
 | ||
|             // 缺少扩展
 | ||
|             $error_msg = $e->getMessage() ? $e->getMessage() : "缺少 redis 扩展";
 | ||
|         } catch (\RedisException $e) {
 | ||
|             // 连接拒绝
 | ||
|             \think\Log::write('redis connection redisException fail: ' . $e->getMessage());
 | ||
|             $error_msg = $e->getMessage() ? $e->getMessage() : "redis 连接失败";
 | ||
|         } catch (\Exception $e) {
 | ||
|             // 异常
 | ||
|             \think\Log::write('redis connection fail: ' . $e->getMessage());
 | ||
|             $error_msg = $e->getMessage() ? $e->getMessage() : "redis 连接异常";
 | ||
|         }
 | ||
| 
 | ||
|         if ($error_msg) {
 | ||
|             if ($is_interrupt || $this->cache_lock_thorws_excption) {
 | ||
|                 throw new \Exception($error_msg);
 | ||
|             } else {
 | ||
|                 $this->setCacheLockErrorMsg($error_msg);
 | ||
|                 return false;
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public function getRedis() {
 | ||
|         if (!isset($GLOBALS['SPREDIS'])) {
 | ||
|             $GLOBALS['SPREDIS'] = (new Redis())->getRedis();
 | ||
|         }
 | ||
| 
 | ||
|         return $GLOBALS['SPREDIS'];
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|     public function getLock($key,$suffix = "-lock-suffix", $timeout = 120){
 | ||
|         $this->hasRedis(true);
 | ||
|         $redis = $this->getRedis();
 | ||
|         $hashKey = $key.$suffix;
 | ||
| //        $redis->del($hashKey);
 | ||
| //        var_dump($hashKey);die;
 | ||
|         //判断锁是否存在,如果存在,返回错误
 | ||
| //        if ($redis->exists($hashKey)){
 | ||
| ////            var_dump(111111222);die;
 | ||
| //            if($this->cache_lock_thorws_excption){
 | ||
| //                throw new \Exception($this->cache_lock_error_msg);
 | ||
| //            }else{
 | ||
| //                return false;
 | ||
| //            }
 | ||
| //
 | ||
| //        }
 | ||
|         //如果不存在创建锁并返回
 | ||
| //        $redis->set($hashKey, 1,$timeout);//注释掉
 | ||
|         //替换成原子操作的命令
 | ||
|         $nxLock =  $redis->set($hashKey, 1,['nx', 'ex' => $timeout]);
 | ||
|         if ($nxLock == 1) {
 | ||
|             return true;
 | ||
|         } else {
 | ||
|             if($this->cache_lock_thorws_excption){
 | ||
|                 throw new \Exception($this->cache_lock_error_msg);
 | ||
|             }else{
 | ||
|                 return false;
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public function setCacheLockErrorMsg($cache_lock_error_msg){
 | ||
|         $this->cache_lock_error_msg = $cache_lock_error_msg;
 | ||
|         return $this;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public function getCacheLockErrorMsg(){
 | ||
|         return $this->cache_lock_error_msg;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public function freeLock($key,$suffix = "-lock-suffix"){
 | ||
|         $this->hasRedis(true);
 | ||
|         $redis = $this->getRedis();
 | ||
|         if(!$key || !$suffix) return true;
 | ||
|         $hashKey = $key.$suffix;
 | ||
| 
 | ||
|         //执行lua脚本,确保删除锁是原子操作
 | ||
|         $lua = 'if redis.call("get",KEYS[1]) == ARGV[1]
 | ||
|         then
 | ||
|             return redis.call("del",KEYS[1])
 | ||
|         else
 | ||
|             return 0
 | ||
|         end';
 | ||
|         $result = $redis->eval($lua, [$hashKey, 1], 1);
 | ||
| 
 | ||
|         if ('1' == $result) {
 | ||
| 
 | ||
|             return true;
 | ||
|         }
 | ||
|         return false;
 | ||
| 
 | ||
| //        if (!$redis->EXISTS($hashKey)) return true;
 | ||
| //        $redis->del($hashKey);
 | ||
| //        return true;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| }
 |