当前位置:首页 > 文章列表 > 数据库 > Redis > Redis Lua 脚本中如何保证多个 key 原子更新

Redis Lua 脚本中如何保证多个 key 原子更新

来源:17golang原创 2026-09-10 17:57:25 0浏览 收藏

要同时修改 Redis 中的多个 key,最稳妥的做法是把“读取、判断、写入”放进一次 Lua 脚本调用。Redis 会在脚本运行期间串行执行其中的命令,其他客户端不会插入到读取和两次更新之间,因此库存扣减与已售计数可以保持并发可见性上的一致。

要点速览
  • 脚本访问的 key 全部放在 KEYS,业务值放在 ARGV
  • Redis Cluster 中,多个 key 必须落在同一个 hash slot,常用做法是使用相同的 hash tag。
  • Lua 脚本是不可交错执行的,但脚本内部运行时错误不会替业务自动补偿回滚。

先把多个 key 设计成一个原子更新单元

下面用库存场景说明:stock:{sku-1001}:available 保存可用库存,stock:{sku-1001}:sold 保存已售数量。花括号里的 sku-1001 是 Redis Cluster 的 hash tag,两个 key 会使用同一段标签计算槽位,脚本才能在集群中作为一个多 key 操作执行。

脚本中的 key 名不要通过字符串拼接生成,也不要从 Redis 里的值推导。调用方提前声明全部 key,脚本用 KEYS[1]KEYS[2] 访问;扣减数量则放到 ARGV[1]

Redis Lua 原子更新中 KEYS、ARGV、库存与已售计数的边界关系技术框图
图1:把两个数据 key 放入同一更新边界,业务参数通过 ARGV 进入脚本。

用 Lua 完成检查、扣减和累计

帮助读者理解脚本内的读取、条件判断、两个写命令与返回值之间的静态关系。
图2:查看 Lua 脚本中的校验边界和两个写入组件,理解为什么客户端不会看到半更新状态。

这个脚本先读取可用库存,扣减量不合法或库存不足时直接返回;只有校验通过,才同时执行两个写命令。关键点是不要先在客户端执行 GET,再单独发送 DECRBY,否则两个请求之间可能被另一个购买请求抢走库存。

-- 先检查输入,再在同一脚本中更新两个相关 key
local available = tonumber(redis.call('GET', KEYS[1]) or '0')
local delta = tonumber(ARGV[1])

-- 拒绝非正数,避免把扣减脚本变成意外的加库存脚本
if not delta or delta 

返回数组的第一个元素是状态:1 表示扣减成功,0 表示库存不足;第二个元素是当前可用量。生产代码可以把它映射成明确的业务结果,而不是只判断命令是否返回错误。

通过 EVAL 显式传入两个 key

准备初始数据后,用 EVAL 的第二个参数声明 key 数量。这里的 2 很重要:Redis 会把后面的两个参数放进 KEYS,再把逗号之后的参数放进 ARGV

# 初始化两个同槽位 key;注释说明每个值的业务含义
redis-cli SET 'stock:{sku-1001}:available' 8
redis-cli SET 'stock:{sku-1001}:sold' 0

# 2 表示后面有两个 KEYS,最后的 3 会进入 ARGV[1]
redis-cli EVAL "local n=tonumber(redis.call('GET',KEYS[1]) or '0'); local d=tonumber(ARGV[1]); if n 

成功时返回类似 1, 5,随后可分别读取两个 key 检查业务结果。若把扣减量误放到两个 key 之后的数量位置,或者把 numkeys 写成 1,Lua 看到的数组就会错位,这是最常见的调用错误。

原子执行的边界:不交错,不等于自动回滚

Redis 的脚本执行期间会阻塞其他服务端活动,所以其他客户端不会读到“库存已经减了、已售还没加”的中间状态。但原子执行主要解决并发交错问题,不应被理解成带数据库事务回滚的异常恢复机制。

因此要把可能失败的输入校验放在第一条写命令之前,尽量使用参数明确、类型稳定的命令。脚本执行中如果在第一条写命令之后又遇到命令错误,业务层仍需要幂等键、补偿任务或对账机制兜底;不要用一段长脚本包住大量不可控逻辑。

检查项正确做法常见误区
key 传递所有访问的 key 放入 KEYS在 Lua 中拼接 key 名
集群路由多 key 使用相同 hash tag两个 key 分属不同槽位
参数位置业务值放 ARGV把值当成 key 传入
脚本长度只保留短小、可预测的更新逻辑在脚本中塞入慢查询或复杂循环

常见问题

多个 key 不在同一个 Cluster 槽位怎么办?

调整 key 命名,让共同的业务标识放进相同的花括号 hash tag,例如 order:{1001}:stockorder:{1001}:sold。不要只改脚本参数顺序,路由槽位不会因此改变。

应该一直发送 EVAL 还是使用 EVALSHA?

脚本稳定后可以先用 SCRIPT LOAD 缓存,再用 EVALSHA 调用以减少重复传输;缓存会因重启、故障切换或刷新而消失,客户端仍应准备回退加载。

为什么不直接用 MULTI/EXEC?

只需要把一组已经确定的命令排队时,事务就够用;如果必须先读取、判断,再决定是否更新多个 key,Lua 可以把条件逻辑和写入放在服务端一次完成。

把 key 边界、参数边界和失败边界先设计清楚,Lua 才真正适合做 Redis 的多 key 原子更新。上线前重点检查 Cluster 槽位、脚本耗时和异常后的对账方案。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go slice alias 截取后修改元素为什么会影响原切片Go slice alias 截取后修改元素为什么会影响原切片
上一篇
Go slice alias 截取后修改元素为什么会影响原切片
Go encoding/csv Comment 注释符出现在引号字段里为什么不会被忽略
下一篇
Go encoding/csv Comment 注释符出现在引号字段里为什么不会被忽略
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之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推荐
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    67次使用
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    224次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    148次使用
  • AI Prompt Library:免费AI提示词库,助力ChatGPT高效创作与营销
    AI Prompt Library
    探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
    81次使用
  • Generrated:DALL·E 2/3 AI绘画提示词灵感库与图像对比平台
    Generrated
    Generrated汇集9300+张DALL·E生成图像及对应提示词,支持查看完整图集、对比DALL·E 2与3版本差异,是AI绘图新手学习Prompt设计与获取创作灵感的实用工具。
    60次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码