1.redis鎖引入該類
<?php/** * Redis鎖操作類 * Date: 2016-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * public lock 擷取鎖 * public unlock 釋放鎖 * private connect 串連 */class RedisLock { // class start private $_config; public $_redis; /** * 初始化 * @param Array $config redis串連設定 */ public function __construct($config=array()){ $this->_config = $config; $this->_redis = $this->connect(); } /** * 擷取鎖 * @param String $key 鎖標識 * @param Int $expire 鎖到期時間 * @return Boolean */ public function lock($key, $expire=5){ $is_lock = $this->_redis->setnx($key, time()+$expire); // 不能擷取鎖 if(!$is_lock){ // 判斷鎖是否到期 $lock_time = $this->_redis->get($key); // 鎖已到期,刪除鎖,重新擷取 if(time()>$lock_time){ $this->unlock($key); $is_lock = $this->_redis->setnx($key, time()+$expire); } } return $is_lock? true : false; } /** * 釋放鎖 * @param String $key 鎖標識 * @return Boolean */ public function unlock($key){ return $this->_redis->del($key); } /** * 建立redis串連 * @return Link */ private function connect(){ try{ $redis = new Redis(); $redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']); if(!empty($this->_config['auth'])){ $redis->auth($this->_config['auth']); } $redis->select($this->_config['index']); }catch(RedisException $e){ throw new Exception($e->getMessage()); return false; } return $redis; }} // class end
2.調用
$oRedisLock = new RedisLock($config); // 擷取鎖,嘗試3次 for ($i=0;$i<=3;$i++){ $is_lock = $oRedisLock->lock($key, 2); if($is_lock){ break; } } if($is_lock){ //dosth 邏輯 // 釋放鎖 $is_lock = $oRedisLock->unlock($key); }else{ }
3.更加簡單的方式
SET key value [EX seconds] [PX milliseconds] [NX|XX]
從 Redis 2.6.12 版本開始, SET 命令的行為可以通過一系列參數來修改: EX second :設定鍵的到期時間為 second 秒。 SET key value EX second 效果等同於 SETEX key second value 。 PX millisecond :設定鍵的到期時間為 millisecond 毫秒。 SET key value PX millisecond 效果等同於 PSETEX key millisecond value 。 NX :只在鍵不存在時,才對鍵進行設定作業。 SET key value NX 效果等同於 SETNX key value 。 XX :只在鍵已經存在時,才對鍵進行設定作業。
1、 用戶端A請求伺服器設定key的值,如果設定成功就表示加鎖成功 2、 用戶端B也去請求伺服器設定key的值,如果返回失敗,那麼就代表加鎖失敗 3、 用戶端A執行程式碼完成,刪除鎖 4、 用戶端B在等待一段時間後在去請求設定key的值,設定成功 5、 用戶端B執行程式碼完成,刪除鎖 $redis->set($key, $value, array('nx', 'ex' => $ttl)); //ex表示秒