讲师中心 微信公众号
AI工具推荐 视频效率加速

ThinkPHP Redis分布式锁怎么实现防止超卖问题

老萱同学_8643

老萱同学_8643

发布时间:2026-08-22 14:08:48

|

367人浏览过

|

来源于php中文网

原创

TP8.0中Redis防超卖应优先用DECRBY原子预扣减+数据库乐观锁兜底;若用分布式锁,必须用SET命令原子设锁(带client_id和EX)、Lua脚本安全解锁、自动续期,禁用SETNX+EX等非原子操作。

thinkphp redis分布式锁怎么实现防止超卖问题

直接说结论:TP8.0 里用 Redis 实现防超卖,别手写锁逻辑,优先走 DECRBY 原子预扣减 + 数据库乐观锁兜底;真要上分布式锁,必须带 client_id 校验和自动续期,否则锁可能被误删或提前过期。

为什么不能只用 SETNX + EX 模拟锁

很多人照着老教程写 SETNX 加锁、再 EXPIRE 设过期时间,这在 TP8.0 高并发下会出问题:两步操作非原子,中间若进程崩溃,锁就永远卡住;或者锁过期了但业务还没跑完,别的请求进来又拿到锁,导致库存被重复扣减。

正确做法是用 SET 命令一次性完成:key、value(唯一 client_id)、['nx' => true, 'ex' => 30]。TP8.0 的 Redis::set() 支持这个参数组合,它等价于 Redis 原生命令 SET key value NX EX 30,天然规避“设锁成功但设不过期”的竞态。

  • client_id 必须全局唯一(比如用 uniqid('', true) 或 UUID),不能写死字符串
  • 过期时间别设太短(低于业务执行时间),也别太长(影响故障恢复速度),30 秒是常见起点
  • 如果 config/cache.php 里 Redis 连接没配对,Redis::set() 会静默失败,日志里都看不到报错

解锁必须用 Lua 脚本校验 value

解锁不是简单 DEL lock:key 就完事。A 请求的锁过期后被 B 拿走,A 还在执行 DEL,就把 B 的锁删了——这就是典型的“误删”。TP8.0 中必须用 Lua 脚本保证“判断 + 删除”原子性:

立即学习“PHP免费学习笔记(深入)”;

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载
if redis.call('get', KEYS[1]) == ARGV[1] then
  return redis.call('del', KEYS[1])
else
  return 0
end

调用时传入两个参数:['lock:goods:123'] 和当初 set 时用的 client_id 字符串。TP8.0 的 Redis::eval() 可以直接执行这段脚本。

  • 别用 GET + DEL 两步判断,网络往返期间就可能被抢占
  • 脚本里不能用 redis.call('exists', ...) 替代 get 判断,因为锁可能被其他客户端更新过 value
  • 如果 eval() 返回 0,说明不是自己加的锁,不该删——这时候该抛异常还是重试,得看业务容忍度

比锁更稳的方案:DECRBY 直接原子预扣减

在秒杀类场景中,95% 的超卖其实发生在“查库存 → 扣库存”之间。与其费劲加锁,不如让 Redis 直接干掉这个窗口:redis()->decrBy('stock:1001', $buyCount)。

这个命令返回扣减后的值,只要检查它是否

  • 必须前置使用:先 DECRBY,再查 DB,顺序反了就没意义
  • 如果 DB 更新失败(比如 version 不匹配),一定要在 catch 或 finally 里调用 redis()->incrBy('stock:1001', $buyCount) 补回,否则库存永久丢失
  • 不要依赖 DECRBY 返回值做业务状态判断(比如“扣减成功”),它只代表 Redis 层动作,DB 层仍可能失败

自动续期不是可选项,是必选项

锁持有时间超过业务实际耗时,就会提前释放。比如你设了 30 秒过期,但支付回调处理花了 45 秒,中间 15 秒锁就空了。TP8.0 没内置看门狗,得自己实现一个后台任务定期 EXPIRE 延长锁 TTL,或者用 think-redis-lock 这类扩展。

手动续期要注意:只给“自己加的锁”续期,得用 client_id 查一遍当前 value 是否匹配,否则又会误操作别人锁。

  • 续期频率建议设为锁过期时间的 1/3(比如 30 秒锁,每 10 秒 check 一次)
  • 别在锁即将过期前 1 秒才续,网络抖动可能导致续期请求迟到
  • 如果业务流程里有 IO 等待(如调第三方接口),锁生命周期很可能覆盖不到全程,这时更适合拆成多段锁或换用消息队列削峰

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

9664

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

5801

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2055

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

3628

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

4314

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

3371

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

4797

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

3762

2023.11.13

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

0

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn