当前位置: 首页 > 后端技术 > PHP

Redis应用-分布式锁

时间:2023-03-29 15:40:51 PHP

系列文章Redis应用-分布式锁Redis应用-异步消息队列和延迟队列Redis应用-位图Redis应用-HyperLogLogRedis应用-布隆过滤器Redis应用-限流Redis应用-Geo多进程时不在同一个系统,需要使用分布式锁来控制多个进程对资源的访问。使用redis实现分布式锁主要使用如下命令:SETNXKEYVALUE如果key不存在,则设置该字符串对应的keyvalueexpireKEYseconds设置key的过期时间delKEY删除key代码实现如下:$redis=newRedis();$redis->connect('127.0.0.1',6379);$ok=$redis->setNX($key,$value);if($ok){//得到锁……做点什么……$redis->del($key);}上面的代码有没有问题?如果我们在逻辑处理过程中出现异常情况,没有删除KEY,那么就会出现死锁。所以一般我们在拿到锁后都会给KEY加上一个过期时间。为了保证执行的原子性,我们使用multi有如下代码$redis->multi();$redis->setNX($key,$value);$redis->expire($key,$ttl);$res=$redis->exec();if($res[0]){//获取锁...做点什么...$redis->del($key);}但是还有一个问题像这样。第一次请求成功,后面的请求虽然没有拿到锁,但是每次都会刷新锁的时间。这样一来,设置锁过期时间的意义就不存在了。所以我们会在拿到锁后操作过期时间。这时候我们可以牺牲Lua脚本来进行原子操作。代码如下$script=<<eval($script,[$key,$val,$ttl],3);if($res){//获取锁...做一些事情...$redis->del($key);}虽然借助lua脚本解决了问题,但是还是有点麻烦。从Redis2.6.12版本开始,可以通过一系列参数修改SET命令的行为:EXsecond:设置key的过期时间为second秒。SETkeyvalueEXsecond相当于SETEXkeysecondvalue。PXmillisecond:设置密钥过期时间为millisecond毫秒。SETkeyvaluePXmillisecond相当于PSETEXkeymillisecondvalue。NX:仅当密钥不存在时才设置密钥。SET键值NX等同于SETNX键值。XX:仅当密钥已存在时才设置密钥。$ok=$redis->set($key,$random,array('nx','ex'=>$ttl));if($ok){//获取锁...做点什么...如果($redis->get($key)==$random){$redis->del($key);}}上面可以看到我们的值引入了一个随机数,就是为了防止逻辑处理时间过长,锁的失效时间已经过期。这时候下一个请求会获取到锁,而上一个请求逻辑处理完后会直接删除锁。锁主要用于秒杀等并发请求等场景。以上就是redis锁的实现。本文同时发布在微信公众号【小刀资讯】,欢迎扫描二维码关注!