SET key value [EX seconds] [PX milliseconds] [NX|XX]html
将字符串值value关联到keynode
对于某个本来带有生存时间(TTL)的键来讲, 当SET命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。redis
可选参数bash
命令的行为能够经过一系列参数来修改:锁在redis中最简单的数据结构就是string。最先的时候,上锁的操做通常使用setnx,这个命令是当锁不存在的时候set一个val,或许你还会记得使用expire来增长锁的过时,解锁操做就是使用del命令,代码以下:
app
if(redis.setnx('node:lock', 1)){
redis.expire('node:lock',10);
// ...todo
redis.del('node:lock')
}
}复制代码
问题就在于setnx和expire中间若是遇到crash等行为,可能这个lock就不会被释放了
ui
为了解决这个问题,咱们能够把超时时间设置跟set操做放在一块儿
spa
if(redis.set('node:lock',1, 'nx', 'ex', 10)){
// ...todo
redis.del('node:lock')
}
}复制代码
获取锁的机制是对了,可是删除锁的机制直接使用del是不对的。由于有可能致使误删别人的锁的状况。code
好比,这个锁我上了10s,可是我处理的时间比10s更长,到了10s,这个锁自动过时了,被别人取走了,而且对它从新上锁了。那么这个时候,我再调用del就是删除别人创建的锁了。cdn
终极版:
function lock(lockName,lockTimeout)){
let lockKey=lockName+':lock';
let lockValue=new Date().getTime();
if(redis.set(lockKey,lockValue, 'nx', 'ex', lockTimeout)){
return lockValue;
}
return null;
}
function unlock(lockName, lockValue)){
let lockKey=lockName+':lock';
if(redis.get(lockKey)===lockValue){ redis.del(lockName)
return true;
}}
复制代码
这里的lockValue是一个时间戳,当lock的时候,往redis的存储这个时间戳,unlock的时候,先get一下lock中的值,若是和我要删除的值是一致的,说明这个锁是以前我set的,不然的话,说明这个锁已通过期,是别人set的,我就不该该对它进行任何操做。