解锁redis锁的正确姿势
redis是php的好朋友,在php写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为。这个时候我们就要用到锁。锁的方式有好几种,php不能在内存中用锁,不能使用zookeeper加锁,使用数据库做锁又消耗比较大,这个时候我们一般会选用redis做锁机制。
setnx
锁在redis中最简单的数据结构就是string。最早的时候,上锁的操作一般使用setnx,这个命令是当:lock不存在的时候set一个val,或许你还会记得使用expire来增加锁的过期,解锁操作就是使用del命令,伪代码如下:
if (Redis::setnx("my:lock", 1)) { Redis::expire("my:lock", 10); // ... do something Redis::del("my:lock") }
这里其实是有问题的,问题就在于setnx和expire中间如果遇到crash等行为,可能这个lock就不会被释放了。于是进一步的优化方案可能是在lock中存储timestamp。判断timestamp的长短。
set
现在官方建议直接使用set来实现锁。我们可以使用set命令来替代setnx,就是下面这个样子
if (Redis::set("my:lock", 1, "nx", "ex", 10)) { ... do something Redis::del("my:lock") }
上面的代码把my:lock设置为1,当且仅当这个lock不存在的时候,设置完成之后设置过期时间为10。
获取锁的机制是对了,但是删除锁的机制直接使用del是不对的。因为有可能导致误删别人的锁的情况。
比如,这个锁我上了10s,但是我处理的时间比10s更长,到了10s,这个锁自动过期了,被别人取走了,并且对它重新上锁了。那么这个时候,我再调用Redis::del就是删除别人建立的锁了。
官方对解锁的命令也有建议,建议使用lua脚本,先进行get,再进行del
程序变成:
$token = rand(1, 100000); function lock() { return Redis::set("my:lock", $token, "nx", "ex", 10); } function unlock() { $script = ` if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end ` return Redis::eval($script, "my:lock", $token) } if (lock()) { // do something unlock(); }
这里的token是一个随机数,当lock的时候,往redis的my:lock中存的是这个token,unlock的时候,先get一下lock中的token,如果和我要删除的token是一致的,说明这个锁是之前我set的,否则的话,说明这个锁已经过期,是别人set的,我就不应该对它进行任何操作。
所以:不要再使用setnx,直接使用set进行锁实现。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
redis,锁,解锁
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 鸣潮新手池角色哪个好 新手池角色推荐
- 杨采妮.1997-离别之前新曲+精选(告别专辑)【EMI百代】【WAV+CUE】
- 新城唱好谢霆锋X达明一派同场异梦音乐会2CD[WAV+CUE]
- 翁立友2010-十年坚持好胆你就来[豪记][WAV]
- 鸣潮公测福利领取攻略 开服108抽福利获取大全
- 鸣潮是哪个公司的游戏 鸣潮游戏开发商介绍
- 鸣潮官方兑换码合集 最新可用兑换码分享
- 谭咏麟.1998-在乎【宝丽金】【WAV+CUE】
- 谭咏麟.1999-谁可改变谭咏麟原装版【环球】【WAV分轨】
- 郭富城.2006-MYNATION(国)【大国文化】【WAV+CUE】
- 崔子格《崔子格歌曲合集》[320K/MP3][121.9MB]
- 陈慧琳《陈慧琳歌曲合集》[320K/MP3][103MB]
- 陈慧娴《陈慧娴歌曲合集》[320K/MP3][110.2MB]
- 鸣潮角色强度排行攻略 公测最新节奏榜
- 鸣潮120高帧率怎么设置 120帧设置方法介绍