当前位置:首页 > 文章列表 > 数据库 > Redis > Redis SETNX 分布式锁为什么会误删:令牌校验、过期与释放脚本

Redis SETNX 分布式锁为什么会误删:令牌校验、过期与释放脚本

来源:17golang原创 2026-08-24 15:28:47 0浏览 收藏

订单超时任务偶尔会同时跑两次,排查 Redis 记录时却发现锁明明存在过。最容易忽略的情况是:持锁进程暂停超过租约,新进程已经拿到同一个锁,旧进程恢复后执行一条无条件 DEL,把新进程的锁也删掉了。

日常开发里用SETNX做Redis分布式锁,很容易碰到自己的任务卡了几秒、最后顺手删掉了别人刚拿到的锁的情况,问题根源根本不是SETNX本身有bug,而是锁的所有权校验、原子操作边界、过期规则这几块没做对。

实践要点

  • SETNX 只负责竞争,锁值必须放入每次任务独有的随机令牌。
  • 释放前要比对令牌,比较和删除必须由 Redis 原子完成。
  • 过期时间是兜底边界,不是续期和业务完成确认的替代品。
常见的误删场景里,绝大多数情况都是没做锁持有者身份校验,直接用DEL命令删锁,或者校验令牌和删锁的两步操作中间插入了别的调度逻辑,最后动了不属于当前进程的锁。

先把误删现场还原出来

假设锁键是 lock:order-timeout。进程 A 抢到锁后暂停,租约 10 秒到期;进程 B 随后抢到锁并写入自己的令牌。此时 A 恢复,若仍执行 DEL lock:order-timeout,B 的任务就失去了互斥保护。

Redis 分布式锁误删竞态:旧持有者 A 延迟释放,新持有者 B 已经写入令牌

这条时间线里,A 的删除动作在语法上完全成功,但在所有权上已经失效。日志只记录“删除返回 1”并不能证明删除的是自己的锁,必须把令牌和持有者一起记录下来。

加锁时同时写入随机令牌和租约

Redis 版本支持 SET 的 NX 与 EX 组合时,优先使用一条命令完成抢锁和设置过期时间:

SET lock:order-timeout 7f3c...a91 NX EX 10

返回 OK 才代表本次任务拿到锁;返回空值表示已有持有者。令牌可以使用 UUID 或安全随机串,不能用固定的主机名、进程名,也不要让所有任务共用一个值。

为什么不建议分成两条命令

SETNX、再 EXPIRE 存在中间崩溃窗口:锁已经写入,却没有租约,最后变成永久占用。即便业务还在使用旧写法,也要把设置过期时间的失败纳入告警和人工清理流程。

释放锁要把比较和删除绑在一起

下面的 Lua 脚本把“读取当前值、比较令牌、删除键”放进一次 Redis 脚本调用。只有值仍然等于自己的令牌时,删除才会发生:

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

在客户端中执行脚本时,KEYS[1] 传入锁键,ARGV[1] 传入本次任务保存的令牌。返回 1 表示确实释放了自己的锁,返回 0 可能意味着锁已经过期、被续期逻辑改变,或当前持有者不是自己;这三种情况都不应再补一条无条件删除。

Redis 分布式锁安全释放:读取令牌、比较所有权后原子删除

续期和业务耗时要分开验收

任务耗时可能超过初始 10 秒时,可以按固定周期续期,但续期同样必须先校验令牌。否则 A 的续期请求在租约到期后到达,也可能延长 B 的锁。

if redis.call('get', KEYS[1]) == ARGV[1] then
  return redis.call('expire', KEYS[1], ARGV[2])
end
return 0

续期周期要明显短于租约,并给暂停、网络抖动和 Redis 响应延迟留出余量。更重要的是,业务完成后仍要走带令牌校验的释放脚本,不要把“任务执行成功”误当成“当前进程仍拥有锁”。

用可复查命令做一次小实验

可以在测试实例中手工验证所有权边界。先让 A 写入令牌:

SET lock:order-timeout token-a NX EX 5
GET lock:order-timeout
TTL lock:order-timeout

等待过期后让 B 写入 token-b,再用 A 的令牌调用释放脚本,结果应为 0,且 GET lock:order-timeout 仍然返回 token-b。最后用 B 的令牌调用同一脚本,结果才应为 1。

几个容易误判的结果

  • TTL 返回 -2 只表示键已不存在,不能证明某个进程释放成功。
  • 脚本返回 0 不等于 Redis 故障,先查看当前令牌和任务日志。
  • 集群模式下,脚本涉及的锁键应保持在同一个哈希槽;不要把无关键塞进同一脚本。

常见问题与上线前检查

放在当前任务的内存变量中,并把任务编号写入结构化日志。不要把令牌放在全局固定配置里,否则多个任务无法区分所有权。

令牌应该放在哪里?

不能把租约当成业务授权。进程发现续期失败或租约已经失效后,应停止会产生副作用的后续动作;无法中止时,业务写入还需要幂等键或版本校验兜底。

过期后还能继续做业务吗?

确认加锁使用 NX 与过期时间,令牌每次唯一;释放和续期都通过令牌校验脚本;日志能区分抢锁、续期、释放的返回值;最后用 A/B 两个令牌复查“旧持有者不能删除新持有者”。

Redis 分布式锁的安全边界不在“有没有 SETNX”,而在每个动作是否持续证明自己仍是持有者。把令牌校验放进 Redis 原子脚本,再用幂等和版本检查承接租约失效,才算完成一条可验收的并发控制链路。

上线前检查什么?

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
多模态模型图片输入怎么做尺寸校验:压缩、像素上限与失败重试多模态模型图片输入怎么做尺寸校验:压缩、像素上限与失败重试
上一篇
多模态模型图片输入怎么做尺寸校验:压缩、像素上限与失败重试
Google 同态加密如何让私有 AI 可用:开发团队该看懂的技术边界
下一篇
Google 同态加密如何让私有 AI 可用:开发团队该看懂的技术边界
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    5214次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    4719次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    4669次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    4930次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    4885次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码