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

Redis事务全解析:从秒杀案例看原子操作实现

💡 一句话真相:Redis事务就像"点套餐"🍱——把多个命令打包下单(MULTI),后厨(Redis)一次性烹饪(EXEC),但某个菜缺货(失败)不会退单!


🔧 一、为什么需要事务?转账案例的痛点

场景:A向B转账100元

客户端RedisGET A_balance → 500GET B_balance → 300SET A_balance 400SET B_balance 400客户端Redis

风险:若第二步后Redis宕机 → A扣款成功,B未到账!


🛠️ 二、Redis事务实现:三阶段流程

1. 开启事务(点餐下单)
MULTI  # 开启事务 → 返回OK  

效果:后续命令进入队列,不立即执行

2. 命令入队(选菜品)
DECRBY A_balance 100  # A账户减100 → 进入队列  
INCRBY B_balance 100  # B账户加100 → 进入队列  

特性:

  • 语法错误(如INCRBY B 100)直接拒绝入队
  • 运行时错误(如对字符串DECRBY)不检查
3. 执行事务(后厨烹饪)
EXEC  # 执行队列中所有命令  

输出示例:

1) (integer) 400  # DECRBY结果  
2) (integer) 400  # INCRBY结果  

🚨 三、原子性≠回滚:核心差异图解

事务开始
命令1成功
命令2失败
命令3执行
事务提交

与传统数据库对比:

特性Redis事务MySQL事务
原子性命令全部执行全部成功或全部回滚
隔离性单线程天然隔离需设置隔离级别
错误处理继续执行后续命令自动回滚
回滚支持❌ 无✅ 有

💥 关键结论:Redis事务是 “部分原子性” —— 保证命令打包执行,但不支持回滚!


🔒 四、乐观锁:Watch命令解决并发冲突

1. 秒杀库存超卖问题
客户端1Redis客户端2GET stock → 10GET stock → 10DECR stockDECR stock客户端1Redis客户端2
2. Watch实现乐观锁
WATCH stock  # 监控库存键  MULTI  
DECR stock  
EXEC  # 若stock被其他客户端修改,EXEC返回(nil)  

执行效果:
在这里插入图片描述

3. 重试机制(代码示例)
import redis  
r = redis.Redis()  def decr_stock():  while True:  try:  r.watch('stock')  stock = int(r.get('stock'))  if stock > 0:  pipe = r.pipeline()  pipe.multi()  pipe.decr('stock')  if pipe.execute():  # 执行成功返回非None  break  else:  print("库存不足")  break  except Exception:  continue  # 冲突则重试  

⚠️ 五、事务四大坑点与解决方案

坑点现象解决方案
命令错误不回滚SET失败后DECR仍执行开发阶段用redis-cli --pipe检测语法
运行时错误继续执行对字符串INCR → 继续执行事务保证数据类型正确性
WATCH失效重试风暴高并发时无限重试设置最大重试次数/退避策略
事务内执行慢命令阻塞其他客户端避免KEYS、大数据操作

💎 六、事务 vs Lua脚本:终极选择

特性事务Lua脚本
原子性命令级脚本级(真正原子)
复杂度简单需学习Lua语法
性能较高超高(减少网络往返)
错误处理强(可抛异常)

Lua脚本示例:

local stock = redis.call('GET', KEYS[1])  
if tonumber(stock) > 0 then  redis.call('DECR', KEYS[1])  return 1  -- 成功  
else  return 0  -- 失败  
end  

执行命令:

EVAL "脚本内容" 1 stock  

🔧 七、最佳实践:3类场景选型

在这里插入图片描述

  1. 简单命令组 → 事务(如:MULTI + SET A 1 + SET B 2 + EXEC
  2. 原子计数器 → Lua脚本(如:库存扣减)
  3. 读后写冲突WATCH + 事务(如:余额转账)

💡 八、总结:Redis事务三原则

  1. 非回滚设计:执行即提交,失败命令需业务补偿
  2. 隔离性保障:单线程执行天然隔离
  3. 乐观锁搭档:WATCH解决并发冲突

🔥 黄金口诀:

  • 简单打包用MULTI
  • 并发控制靠WATCH
  • 真原子操作选Lua

在这里插入图片描述

#Redis事务 #高并发 #分布式系统
👉 关注我,下期揭秘《Redis+Lua实现分布式锁》!

http://www.dtcms.com/a/343669.html

相关文章:

  • C#_接口设计:角色与契约的分离
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day10
  • 树莓派采集、计算机推理:基于GStreamer的YOLOv5实现方案
  • Codeforces Round 1043 (Div.3)
  • AI生成技术报告:GaussDB与openGauss的HTAP功能全面对比
  • Vue 插槽(Slots)全解析2
  • 大数据毕业设计推荐:基于Hadoop+Spark的手机信息分析系统完整方案
  • 使用GMail API 发送邮箱
  • 在Kubernetes中部署一个单节点Elasticsearch
  • 集成电路学习:什么是Camera Calibration相机标定
  • Effective C++ 条款55:熟悉Boost库
  • 8.21-8.22网络编程——词典
  • 集成电路学习:什么是Template Matching模版匹配
  • C++创建一个空类的时候,编译器会自动生成哪些函数了
  • 数据处理与统计分析 —— apply自定义函数
  • lesson44:Redis 数据库全解析:从数据类型到高级应用
  • 鸿蒙开发中的List组件详解
  • spring之自定义拦截器:HandlerInterceptor 控制请求生死权
  • Java微服务开发:从入门到精通
  • 证书只是手段:把学习变成可复用能力的路线图
  • FPGA 在情绪识别领域的护理应用(三)
  • gRPC 与 HTTP 性能对比分析
  • C++浅拷贝和深拷贝区别
  • 【华为OD-C卷-019 对称字符串 100分(python、java、c++、js、c)】
  • 【Transient-Free 3DGS】delayed densification + coarse to fine增加GS的鲁棒性
  • 【GaussDB】使用gdb定位GaussDB编译package报错
  • 图像中物体计数:基于YOLOv5的目标检测与分割技术
  • 智能编程中的智能体与 AI 应用:概念、架构与实践场景
  • Effective C++ 条款54:熟悉标准库
  • typescript常用命令选项