redis--011

一、传统秒杀痛点

原始流程全部压力落在 MySQL:查询库存、判断用户是否下单、扣库存、创建订单,大量并发请求直接打数据库,MySQL 扛不住高并发。

二、Redis 优化整体架构

  1. Nginx:接收前端大量请求,做负载均衡。
  2. Redis 层(Lua 脚本) :库存校验、一人一单校验、扣减库存、记录已下单用户,全部在 Redis 内部原子完成,拦截绝大部分无效请求。
  3. 阻塞队列 :Redis 校验成功后,把优惠券ID、用户ID丢入阻塞队列,直接给前端返回订单 ID。
  4. 异步消费者:后台线程从队列取出消息,异步操作 MySQL 完成真正的创建订单、扣数据库库存。

核心思想:Redis 做前置校验过滤流量,数据库异步慢处理,把高并发挡在 Redis,保护 MySQL。

三、Lua 脚本作用

Redis 单线程执行 Lua 脚本,整个脚本具备原子性,中间不会被其他命令打断,避免超卖、重复下单并发问题。

Lua 脚本业务逻辑

输入参数:voucherId优惠券ID、userId用户ID

  1. 判断库存:读取seckill:stock:{voucherId}库存值
    • 库存≤0 → 返回1,代表库存不足
  2. 判断用户是否已经抢购过:使用 Set 集合seckill:order:{voucherId}保存已下单用户 ID
    • sismember判断用户已存在 → 返回2,代表重复下单
  3. 校验全部通过:
    • incrby对库存 key 做 - 1 扣减库存
    • sadd把 userId 写入 Set 集合标记该用户已下单
    • 返回0,代表校验成功,可以下单

返回码含义

表格

返回值 含义
0 校验通过,允许下单,进入异步队列
1 库存不足
2 用户重复下单(一人一单限制)

四、完整业务执行流程

  1. 用户发起秒杀请求,进入服务。
  2. Java 调用 Redis 执行 Lua 脚本。
  3. 判断脚本返回结果:
    • 返回1/2:直接向前端返回失败提示。
    • 返回0:把业务数据放进阻塞队列,立刻返回订单 ID 给前端。
  4. 后台独立线程不断消费阻塞队列:
    • 查询数据库
    • 扣减 MySQL 真实库存
    • 创建订单记录
相关推荐
Knight_AL5 小时前
本地服务连接 SaaS 测试环境实践:Docker 部署 Redis 与 RocketMQ 完成接口联调
redis·docker·rocketmq
夕除7 小时前
redis--服务器优化
redis
xiaoqiMikko8 小时前
Redis 实战(一):内存满了 —— 拒写、淘汰、被系统杀掉,以及删了 key 内存为什么不降(6.2.4 实测)
redis·后端
wefg19 小时前
【Redis】安装与启动
数据库·redis·缓存
大圣编蚕10 小时前
常见的 Redis 面试题(高频整理)
数据库·redis·缓存
小猿姐11 小时前
KubeBlocks Enterprise v2.3 发布!
redis·kubernetes·aiops
梅菲塔亚11 小时前
博客_Redis入门到实战
数据库·redis·缓存
蓝胖的四次元口袋11 小时前
Redis 知识梳理(3)
数据库·redis·缓存
lbb 小魔仙12 小时前
Redis运行状态总靠手动查?我用redis_exporter+Prometheus把指标、告警和远程抓取全接起来了
redis·bootstrap·prometheus