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

LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考

目录

lua脚本

记录流水

记录流水的作用

流水什么时候删除


我们在做库存扣减的时候,显示基于Lua脚本和Redis实现的预扣减

这样可以在秒杀扣减的时候保证操作的原子性和高效性

lua脚本

// ... 已有代码 ...@Overridepublic InventoryResponse decrease(InventoryRequest request) {// 创建库存响应对象InventoryResponse inventoryResponse = new InventoryResponse();// 定义用于减少库存的Lua脚本String luaScript = """-- 检查哈希表 KEYS[2] 中是否已存在 ARGV[2] 对应的字段-- 如果存在,说明该操作已执行过,返回错误信息if redis.call('hexists', KEYS[2], ARGV[2]) == 1 thenreturn redis.error_reply('OPERATION_ALREADY_EXECUTED')end-- 从 Redis 中获取 KEYS[1] 对应的值,即当前库存local current = redis.call('get', KEYS[1])-- 如果返回值为 false,说明键不存在,返回错误信息if current == false thenreturn redis.error_reply('KEY_NOT_FOUND')end-- 尝试将当前库存值转换为数字,如果转换失败,返回错误信息if tonumber(current) == nil thenreturn redis.error_reply('current value is not a number')end-- 如果当前库存为 0,返回库存为零的错误信息if tonumber(current) == 0 thenreturn redis.error_reply('INVENTORY_IS_ZERO')end-- 如果当前库存小于要减少的数量 ARGV[1],返回库存不足的错误信息if tonumber(current) < tonumber(ARGV[1]) thenreturn redis.error_reply('INVENTORY_NOT_ENOUGH')end-- 计算减少库存后的新库存值local new = tonumber(current) - tonumber(ARGV[1])-- 将新的库存值存储回 Redis 中redis.call('set', KEYS[1], tostring(new))-- 获取 Redis 服务器的当前时间(秒和微秒)local time = redis.call("time")-- 将获取到的时间转换为毫秒级时间戳local currentTimeMillis = (time[1] * 1000) + math.floor(time[2] / 1000)-- 使用哈希结构存储库存减少操作的日志-- 在 KEYS[2] 对应的哈希表中,以 ARGV[2] 为字段名,存储操作日志的 JSON 字符串redis.call('hset', KEYS[2], ARGV[2], cjson.encode({action = "decrease",  -- 操作类型为减少库存from = current,       -- 操作前的库存值to = new,             -- 操作后的库存值change = ARGV[1],     -- 减少的库存数量by = ARGV[2],         -- 操作标识timestamp = currentTimeMillis  -- 操作的时间戳}))-- 返回更新后的库存值return new""";try {// ... 已有代码 ...

首先是合法性校验

然后是原子性扣减

最后记录一条库存扣减流水


记录流水

在 lua 脚本中 我们不仅是做了库存的扣减

还在 redis 中用 hash 存储了一条流水

key:买家id + token + 扣减数量

value:本次扣减的变化的库存数,变化前的库存数,变化后的库存数 变化操作的ID 变化的时间戳

记录流水的作用

  1. 幂等

执行lua脚本的时候 查看是否有当前流水

如果有 说明是一个重复请求 直接幂等掉

  1. 对账

很重要

redis库存扣减后 需要持久化到数据库 这边使用的是mq异步处理

如何保证一致性呢

我们用redis里的hash流水和数据库流水进行对账

如果不一致的话

很有可能是mq丢消息了

就要会进行排查了

流水什么时候删除

数据库 与 缓存对账后删除

商品下架后24小时后删除

http://www.xdnf.cn/news/12310.html

相关文章:

  • uefi协议设计目的
  • linux——磁盘和文件系统管理
  • python打卡训练营打卡记录day45
  • 数学运算在 OpenCV 中的核心作用与视觉效果演示
  • 本地部署大模型实战:使用AIStarter一键安装Ollama+OpenWeb教程(含最新版本更新指南)
  • 【图像处理3D】:焦距的像素单位标定
  • 使用API有效率地管理Dynadot域名,查看域名市场中所售域名的详细信息
  • 宠物车载安全座椅市场报告:解读行业趋势与投资前景
  • MyBatis-Plus深度全解:从入门到企业级实战
  • 旋转字符串的解题思路与算法分享
  • Offline Transition Modeling via Contrastive Energy Learning
  • 【iSAQB软件架构】软件架构中构建块的视图:黑箱、灰箱和白箱及其交互机制
  • vue和uniapp聊天页面右侧滚动条自动到底部
  • 计算机网络领域所有CCF-A/B/C类期刊汇总!
  • 低代码逻辑引擎配置化实战:三步穿透审批记录查询
  • 鞋内测量新方案:Moticon传感器鞋垫OpenGo在运动科学中的平衡测试应用
  • BIM Revit教程(十一)如何使用机器学习实现 MEP 布局自动化?
  • NumPy数组操作完全指南:从入门到精通
  • 【Zephyr 系列 9】Zephyr 与设备树机制详解:如何为你的板子编写 Devicetree
  • open3d:使用彩色图和深度图生成点云
  • 拆解实战案例:电商ERP管理系统从需求到原型全流程设计
  • 深度学习习题3
  • IDEA 包分层显示设置
  • Postgresql字符串操作函数
  • 《前端面试题:CSS3新特性》
  • 结合PDE反应扩散方程与物理信息神经网络(PINN)进行稀疏数据预测的技术方案
  • 【VLAs篇】02:Impromptu VLA—用于驱动视觉-语言-动作模型的开放权重和开放数据
  • reverse笔记
  • 深度学习在非线性场景中的核心应用领域及向量/张量数据处理案例,结合工业、金融等领域的实际落地场景分析
  • 比特币:固若金汤的数字堡垒与它的四道防线