| 
									
										
										
										
											2024-11-04 15:00:20 +08:00
										 |  |  |  | <?php | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace traits; | 
					
						
							| 
									
										
										
										
											2024-12-04 18:17:08 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | use bw\Redis; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 15:00:20 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | /** | 
					
						
							|  |  |  |  |  * 缓存 | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | 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);
 | 
					
						
							| 
									
										
										
										
											2025-01-04 18:09:51 +08:00
										 |  |  |  | //        var_dump($hashKey);die;
 | 
					
						
							| 
									
										
										
										
											2024-11-04 15:00:20 +08:00
										 |  |  |  |         //判断锁是否存在,如果存在,返回错误
 | 
					
						
							| 
									
										
										
										
											2025-01-08 10:50:01 +08:00
										 |  |  |  | //        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 { | 
					
						
							| 
									
										
										
										
											2024-11-04 15:00:20 +08:00
										 |  |  |  |             if($this->cache_lock_thorws_excption){ | 
					
						
							|  |  |  |  |                 throw new \Exception($this->cache_lock_error_msg); | 
					
						
							|  |  |  |  |             }else{ | 
					
						
							|  |  |  |  |                 return false; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-01-08 10:50:01 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-04 15:00:20 +08:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     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; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-08 10:50:01 +08:00
										 |  |  |  |         //执行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;
 | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-11-04 15:00:20 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } |