基于redis的分布式锁中的setnx+expire非原子操作问题
基于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秒).
————————————————
版权声明:本文为CSDN博主「aben_sky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/aben_sky/article/details/121515122