解锁redis锁的正确姿势

发布时间 - 2026-01-11 00:18:18    点击率:

解锁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  #   # 解锁  # 详解Java如何实现基于Redis的分布式锁  # Redis实现分布式锁的几种方法总结  # redis实现加锁的几种方法示例详解  # Redis上实现分布式锁以提高性能的方案研究  # Redis数据库中实现分布式锁的方法  # php结合redis实现高并发下的抢购、秒杀功能的实例  # Redis高并发问题的解决方法  # Redis瞬时高并发秒杀方案总结  # 如何利用Redis锁解决高并发问题详解  # 这个时候  # 不存在  # 对它  # 的是  # 是一个  # 我就  # 有一  # 我要  # 是在  # 也有  # 随机数  # 走了  # 是有  # 有可能  # 上了  # 好朋友  # 数据结构  # 我再  # 不要再 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  如何挑选高效建站主机与优质域名?  如何确认建站备案号应放置的具体位置?  bing浏览器学术搜索入口_bing学术文献检索地址  浅谈javascript alert和confirm的美化  Android使用GridView实现日历的简单功能  PHP正则匹配日期和时间(时间戳转换)的实例代码  公司门户网站制作流程,华为官网怎么做?  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  Laravel怎么为数据库表字段添加索引以优化查询  ChatGPT 4.0官网入口地址 ChatGPT在线体验官网  MySQL查询结果复制到新表的方法(更新、插入)  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  公司网站制作需要多少钱,找人做公司网站需要多少钱?  Python进程池调度策略_任务分发说明【指导】  如何快速选择适合个人网站的云服务器配置?  如何快速查询网站的真实建站时间?  phpredis提高消息队列的实时性方法(推荐)  打开php文件提示内存不足_怎么调整php内存限制【解决方案】  谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  千库网官网入口推荐 千库网设计创意平台入口  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  如何在IIS7中新建站点?详细步骤解析  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)  如何在Windows 2008云服务器安全搭建网站?  安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出  Laravel如何配置任务调度?(Cron Job示例)  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  黑客如何通过漏洞一步步攻陷网站服务器?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  如何快速上传自定义模板至建站之星?  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  晋江文学城电脑版官网 晋江文学城网页版直接进入  动图在线制作网站有哪些,滑动动图图集怎么做?  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  高防服务器:AI智能防御DDoS攻击与数据安全保障  QQ浏览器网页版登录入口 个人中心在线进入  Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  Laravel怎么实现支付功能_Laravel集成支付宝微信支付  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  如何在腾讯云免费申请建站?  Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  昵图网官网入口 昵图网素材平台官方入口  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  使用C语言编写圣诞表白程序  网站制作软件免费下载安装,有哪些免费下载的软件网站?