当前位置: 首页 > news >正文

【Redis】事务与Lua脚本Day7(2026年)

写在前面

Redis的事务机制与关系型数据库有很大不同,它没有完整的ACID特性,这让很多开发者感到困惑。同时,Lua脚本作为Redis的原子执行能力,在复杂业务场景中发挥着重要作用。今天我们深入探讨Redis事务和Lua脚本的原理与应用。

文章目录

    • 写在前面
    • 一、Redis事务基础
      • 1.1 什么是Redis事务?
      • 1.2 事务相关命令
      • 1.3 事务基本使用
    • 二、WATCH命令详解
      • 2.1 WATCH的作用
      • 2.2 WATCH使用示例
      • 2.3 WATCH实现乐观锁
    • 三、Redis事务的ACID分析
      • 3.1 原子性(Atomicity)
      • 3.2 一致性(Consistency)
      • 3.3 隔离性(Isolation)
      • 3.4 持久性(Durability)
      • ACID对比表
    • 四、Lua脚本详解
      • 4.1 为什么需要Lua脚本?
      • 4.2 Lua脚本基本使用
      • 4.3 常用Lua脚本示例
      • 4.4 Lua脚本注意事项
    • 五、事务 vs Lua脚本对比
    • 六、踩坑提醒
    • 七、面试高频考点
      • 考点1:Redis事务和MySQL事务的区别?
      • 考点2:Redis事务如何实现乐观锁?
      • 考点3:Lua脚本的优势是什么?
      • 考点4:如何处理Lua脚本执行超时?
    • 八、参考资料
    • 九、互动话题

一、Redis事务基础

1.1 什么是Redis事务?

实际场景:电商秒杀场景中,需要先检查库存、再扣减库存、最后记录订单,这三个操作必须作为一个整体执行,否则可能出现超卖问题。

Redis事务是一组命令的集合,这些命令会被顺序执行,执行过程中不会被其他客户端的命令打断。但需要注意的是,Redis事务不支持回滚,这与MySQL等关系型数据库有本质区别。

1.2 事务相关命令

命令说明
MULTI开启事务
EXEC执行事务中的所有命令
DISCARD取消事务
WATCH监视一个或多个key

1.3 事务基本使用

正常执行流程:

# 开启事务 MULTI # 返回:QUEUED # 命令入队 SET user:1:name "zhangsan" QUEUED SET user:1:age 25 QUEUED INCR counter QUEUED # 执行事务 EXEC # 返回:1) OK 2) OK 3) 1

取消事务:

MULTI SET key1 "value1" DISCARD # 事务取消,命令不会执行

二、WATCH命令详解

2.1 WATCH的作用

经验之谈:WATCH是实现乐观锁的关键,它可以让事务在执行前检查key是否被修改。

WATCH命令用于监视一个或多个key,如果在事务执行前这些key被其他客户端修改,则事务会被拒绝执行。

2.2 WATCH使用示例

场景:转账操作

# 客户端A:监视账户余额 WATCH account:balance GET account:balance # 返回:100 MULTI DECRBY account:balance 50 EXEC # 如果期间没有其他客户端修改balance,事务成功执行

如果期间被其他客户端修改:

# 客户端B在客户端A执行EXEC之前 SET account:balance 200 # 客户端A执行EXEC EXEC # 返回:(nil) 事务执行失败

2.3 WATCH实现乐观锁

┌─────────────────────────────────────────────────┐ │ 乐观锁流程 │ ├─────────────────────────────────────────────────┤ │ 1. WATCH key │ │ 2. GET key 获取当前值 │ │ 3. 计算新值 │ │ 4. MULTI │ │ 5. SET key 新值 │ │ 6. EXEC │ │ - 成功:事务执行 │ │ - 失败:key被修改,重试整个流程 │ └─────────────────────────────────────────────────┘

三、Redis事务的ACID分析

踩坑提醒:Redis事务不支持回滚!如果事务中某条命令执行失败,其他命令仍然会继续执行。

3.1 原子性(Atomicity)

Redis事务的原子性分析:

情况原子性说明
命令入队失败满足整个事务被拒绝执行
命令执行失败不满足错误命令跳过,其他继续执行
服务器宕机不满足已执行的命令无法回滚

示例:命令执行失败不影响其他命令

MULTI SET key1 "value1" LPUSH key1 "value2" # 错误:对string类型执行list操作 SET key2 "value2" EXEC # 返回:1) OK 2) (error) WRONGTYPE 3) OK # key1和key2都设置成功,LPUSH失败

3.2 一致性(Consistency)

Redis事务可以保证一致性:

  • 入队错误:整个事务不会执行
  • 执行错误:错误命令会被识别并跳过
  • 服务器宕机:根据持久化配置恢复数据

3.3 隔离性(Isolation)

Redis事务的隔离性分析:

隔离级别是否支持说明
读未提交支持事务执行前可看到其他事务未提交的数据
读已提交支持单线程模型,事务执行时不会被干扰
可重复读不支持WATCH可以部分实现
串行化支持单线程执行

3.4 持久性(Durability)

取决于持久化配置:

  • 无持久化:不满足持久性
  • RDB:可能丢失几分钟数据
  • AOF(everysec):可能丢失1秒数据
  • AOF(always):基本满足持久性

ACID对比表

特性Redis事务MySQL事务
原子性部分(无回滚)完整支持
一致性支持支持
隔离性单线程隔离多种隔离级别
持久性取决于配置支持(WAL)

四、Lua脚本详解

4.1 为什么需要Lua脚本?

实际场景:分布式锁释放时,需要先判断锁是否属于自己,再执行DEL操作。如果用两个命令执行,中间可能被其他客户端干扰。

Redis Lua脚本的优势:

  1. 原子性:整个脚本作为一个整体执行
  2. 减少网络开销:多个命令一次发送
  3. 复用性:脚本可以缓存,重复使用
  4. 灵活性:实现复杂业务逻辑

4.2 Lua脚本基本使用

执行Lua脚本:

# EVAL命令 EVAL "return redis.call('GET', KEYS[1])" 1 user:1:name # 使用KEYS和ARGV数组 EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 user:1:name "zhangsan"

脚本缓存:

# 加载脚本,返回SHA1校验和 SCRIPT LOAD "return redis.call('GET', KEYS[1])" # 返回:e465c6bf...(SHA1值) # 使用SHA1执行脚本 EVALSHA e465c6bf... 1 user:1:name

4.3 常用Lua脚本示例

1. 分布式锁释放:

-- unlock.luaifredis.call("GET",KEYS[1])==ARGV[1]thenreturnredis.call("DEL",KEYS[1])elsereturn0end
# 执行redis-cli--evalunlock.lua lock_key , my_unique_value

2. 限流脚本:

-- rate_limit.lualocalkey=KEYS[1]locallimit=tonumber(ARGV[1])localwindow=tonumber(ARGV[2])localcurrent=redis.call("GET",key)ifcurrentandtonumber(current)>=limitthenreturn0-- 超过限制endredis.call("INCR",key)iftonumber(current)==0thenredis.call("EXPIRE",key,window)endreturn1-- 允许访问

3. 库存扣减(防超卖):

-- deduct_stock.lualocalstock=tonumber(redis.call("GET",KEYS[1]))ifstock<=0thenreturn-1-- 库存不足endredis.call("DECR",KEYS[1])returnstock-1

4.4 Lua脚本注意事项

踩坑提醒:Lua脚本执行时会阻塞Redis,长时间运行的脚本会影响其他请求。

注意事项:

问题解决方案
脚本执行时间过长设置lua-time-limit,默认5秒
脚本过大使用SCRIPT LOAD缓存脚本
随机函数问题Redis禁用了部分随机函数
数据类型错误使用tonumber()tostring()转换
# redis.conf 配置 lua-time-limit 5000 # Lua脚本最大执行时间(毫秒)

五、事务 vs Lua脚本对比

对比项Redis事务Lua脚本
原子性部分(无回滚)完整原子性
复杂逻辑不支持支持条件判断、循环
网络开销多次交互单次交互
错误处理无法捕获可以处理错误
使用场景简单批量操作复杂原子操作
学习成本中等

六、踩坑提醒

踩坑提醒:事务不支持回滚

问题:

MULTI SET key1 "value1" INCR key1 # 对string执行INCR会失败 SET key2 "value2" EXEC # key1被设置为"value1",INCR失败,key2被设置为"value2"

解决方案:

  • 使用Lua脚本实现条件判断
  • 在应用层做数据校验

踩坑提醒:WATCH使用后需要UNWATCH

问题:
WATCH监视的key在EXEC/DISCARD后自动取消,但如果事务被取消后想重新使用这些key,需要手动UNWATCH。

WATCH key1 GET key1 # 发现值不符合预期,想放弃本次操作 UNWATCH # 手动取消监视

七、面试高频考点

考点1:Redis事务和MySQL事务的区别?

答案:

对比项Redis事务MySQL事务
回滚机制不支持支持
隔离级别无明确级别四种隔离级别
锁机制无锁行锁、表锁等
原子性部分(无回滚)完整支持
使用场景批量命令执行数据一致性保证

考点2:Redis事务如何实现乐观锁?

答案:
使用WATCH命令监视key,在EXEC执行前检查key是否被修改。如果被修改,事务返回nil,应用层可以重试。

WATCH key val = GET key MULTI SET key new_val EXEC # 如果key被其他客户端修改,EXEC返回nil

考点3:Lua脚本的优势是什么?

答案:

  1. 原子性:整个脚本原子执行,不会被其他命令打断
  2. 减少网络开销:多个命令一次发送
  3. 复用性:脚本缓存后可重复使用
  4. 灵活性:支持条件判断、循环等复杂逻辑

考点4:如何处理Lua脚本执行超时?

答案:

  1. 设置合理的lua-time-limit配置
  2. 使用SCRIPT KILL命令终止正在执行的脚本
  3. 如果脚本已经执行了写操作,只能使用SHUTDOWN NOSAVE强制关闭
  4. 优化脚本逻辑,避免长时间运行

八、参考资料

  1. Redis官方文档 - Transactions
  2. Redis Lua Scripting

九、互动话题

  1. 你在生产环境中使用Redis事务还是Lua脚本更多?为什么?
  2. 如何设计一个可靠的分布式锁方案?需要考虑哪些问题?
  3. Lua脚本执行超时时,你会如何处理?

欢迎在评论区分享你的经验和见解!


下一期预告:Day8 - Redis发布订阅与消息队列,敬请期待!

http://www.rkmt.cn/news/1441042.html

相关文章:

  • 数字分压器怎么选?靠谱品牌与联系方式一站式汇总 - 品牌推荐大师
  • 基于Arduino Uno的温湿度数据记录器:从传感器采集到SD卡存储
  • Sora 2动态时序压缩实战:从0到1实现200%流畅快放,附可复用的Prompt微调参数表(含v2.3.1验证版)
  • 树莓派系统烧录全攻略:从Raspberry Pi Imager到首次启动
  • Android Studio中文界面配置完整解决方案:3步实现高效开发环境
  • Visual Studio 2022 vs VSCode:新手第一门编程课,到底该选哪个IDE?
  • ZonyLrcToolsX:跨平台歌词下载工具,轻松解决本地音乐库歌词缺失问题
  • Unity 2D物理画线避坑指南:LineRenderer和EdgeCollider2D参数怎么调才不穿模?
  • 宜昌市中央空调维修师傅推荐|全城各区金牌师傅,靠谱选欧米到家 - 欧米到家
  • Arm SMMU缓存机制与地址翻译优化详解
  • 基于Arduino与超声波传感器的智能交互南瓜灯设计与实现
  • 告别‘-novopt’报错:Modelsim 2020.4与Vivado 2021.2联合仿真的正确打开方式
  • Sora 2动画短片创作黄金72小时法则:从概念到交付的倒计时拆解与风险熔断机制
  • 终极解放!淘宝自动化任务完整指南:如何用taojinbi脚本实现淘金币、蚂蚁森林、芭芭农场全自动执行
  • Keil MDK网络内存池优化与BSD_ENOMEM错误解决
  • 新手避坑指南:用SX1276和NS_Radio库搞定物联网国赛LoRa点对点通信(附完整代码)
  • 劳力士官方售后|盛夏腕间守护,解锁腕表四季长效养护法则 - 劳力士服务中心
  • 杭州包包回收水深?2026实地测评揭秘,帮你锁定正规无套路好店 - 奢侈品回收测评
  • 当“防护”遇上“原生景观”:景区边坡项目怎么挑厂家? - 资讯快报
  • 从单片机到FPGA:LCD1602驱动时序的Verilog实现对比与优化心得
  • 2026 年 6 月 重庆米花糖送礼选哪个不粘牙还体面 - 讲清楚了
  • 2026太阳能路灯哪家好?与景观灯搭配选型指南:五大源头厂家实战对比 - 深度智识库
  • 十二大未来技术趋势深度解析:从万物互联到AI原生的融合创新
  • 基于Arduino与Python的实时眨眼检测系统:从计算机视觉到嵌入式控制
  • JiYuTrainer极域电子教室破解指南:3步解锁课堂控制,重获学习自主权
  • 2026透明背景图怎么做?手机电脑制作方法保姆级教程 - AI测评专家
  • 活性炭吸附设备技术解析及山东合规厂家选型参考 - 奔跑123
  • 英雄联盟玩家的智能助手:如何用League Akari重新定义你的游戏体验
  • 聊聊教育圈最近的一些变化 - 品牌测评鉴赏家
  • 宇树机器人G1二次开发:语音对话完整功能实现(打断、停止、待命、激活、有线/无线话筒)