基於redis的分佈式鎖, 性能和穩定性都非常好. 但是redis中setnx
+expire
是非原子操作, 除了用LUA腳本保證實現原子操作, 其實可以直接使用redis自帶的set
方法直接實現.
setnx+expire操作過程中, 如果expire無法執行, 會導致死鎖
原生命令格式:
SET key value [EX seconds] [PX milliseconds] [NX|XX]
- EX seconds : 將鍵的過期時間設置爲 seconds 秒。 執行
SET key value EX seconds
的效果等同於執行SETEX key seconds value
。 - PX milliseconds : 將鍵的過期時間設置爲 milliseconds 毫秒(千分之一秒)。 執行
SET key value PX milliseconds
的效果等同於執行PSETEX key milliseconds value
。 - NX : 只在鍵不存在時, 纔對鍵進行設置操作。 執行
SET key value NX
的效果等同於執行SETNX key value
。 - XX : 只在鍵已經存在時, 纔對鍵進行設置操作
在php的redis擴展中提供的函數的定義是:
/**
* Set the string value in argument as value of the key.
*
* @since If you're using Redis >= 2.6.12, you can pass extended options as explained in example
*
* @param string $key
* @param string|mixed $value string if not used serializer
* @param int|array $timeout [optional] Calling setex() is preferred if you want a timeout.<br>
* Since 2.6.12 it also supports different flags inside an array. Example ['NX', 'EX' => 60]<br>
* - EX seconds -- Set the specified expire time, in seconds.<br>
* - PX milliseconds -- Set the specified expire time, in milliseconds.<br>
* - PX milliseconds -- Set the specified expire time, in milliseconds.<br>
* - NX -- Only set the key if it does not already exist.<br>
* - XX -- Only set the key if it already exist.<br>
* <pre>
* // Simple key -> value set
* $redis->set('key', 'value');
*
* // Will redirect, and actually make an SETEX call
* $redis->set('key','value', 10);
*
* // Will set the key, if it doesn't exist, with a ttl of 10 seconds
* $redis->set('key', 'value', ['nx', 'ex' => 10]);
*
* // Will set a key, if it does exist, with a ttl of 1000 miliseconds
* $redis->set('key', 'value', ['xx', 'px' => 1000]);
* </pre>
*
* @return bool TRUE if the command is successful
*
* @link https://redis.io/commands/set
*/
public function set($key, $value, $timeout = null)
{
}
$redis->set('key', 'value', ['nx', 'ex' => 10])
表示當key不存在時, 設置key且過期時間爲10秒.
$redis->set('key', 'value', ['nx', 'px' => 500])
表示當key不存在時, 設置key且過期時間爲500毫秒(即0.5秒).