首页 > Spring > 当前页面

秒杀令牌桶算法详解

2026-06-12 NEW个对象

📌 一、问题背景

在高并发秒杀系统中,核心矛盾不是“如何下单”,而是如何控制入口流量。如果不做任何限制,所有请求会直接冲击库存服务和数据库,导致系统崩溃。

因此引入“秒杀令牌机制(Token Bucket / Token Gate)”,本质是:

通过提前分配有限令牌,实现流量准入控制

典型场景:

  • 10万用户抢100件商品
  • 不能让所有请求进入数据库层
  • 必须在入口层过滤掉99%以上请求

🎯 二、核心原理

秒杀令牌的核心思想是:只有持有合法令牌的用户才允许进入下单流程

整体流程分为三层控制:

  • 流量入口控制(令牌发放)
  • 请求资格校验(令牌验证)
  • 业务执行层(库存扣减 + 下单)

核心原则:

  • 令牌数量 = 可承载流量上限
  • 令牌必须唯一且不可伪造
  • 令牌校验必须基于 Redis 原子操作

📊 三、数据结构设计

Key 类型 作用
promo_token_pool_{id} SET 令牌池
promo_door_count_{id} STRING 大闸控制流量
user_token_{userId} STRING 用户持有令牌

⚙️ 四、算法分析

秒杀令牌算法本质是一个“有限资源分配问题”

  • 初始化令牌池(根据库存 × 倍数)
  • 用户请求时随机/抢占令牌
  • Redis 原子校验令牌合法性
  • 成功则进入下单流程

关键点:必须保证并发下不会出现重复令牌或超发令牌。

🔄 五、执行流程

系统初始化 → Redis生成令牌池

用户请求进入秒杀接口

获取/校验秒杀令牌

校验失败 → 直接拒绝

校验成功 → 进入库存扣减

MQ异步创建订单

关键点:令牌校验是第一道防线。

📌 六、代码实现(核心)

1. 初始化令牌池

一般是在秒杀活动开始之前的“预热阶段”完成的,核心原则是:越接近活动开始越好,但必须在流量进来之前完成。

RedisTemplate.opsForSet().add("promo_token_pool_" + promoId, token);

2. 生成秒杀令牌(大闸控制)

redisTemplate.opsForValue().set("promo_door_count_" + promoId, stock * 5);

3. 用户获取令牌

String token = redisTemplate.opsForSet().pop("promo_token_pool_" + promoId);

4. 令牌校验

Boolean exist = redisTemplate.opsForSet().isMember("promo_token_pool_" + promoId, token);

5. 请求完整流程

   用户登录

        ↓

    点击秒杀(恶意用户:验证码防刷、nginx对异常IP拉黑)

        ↓

    获取Token (token生成策略,uuid就可以)

        ↓

    Redis保存Token

        ↓

    返回前端

        ↓

    用户下单

        ↓

    携带Token

        ↓

    校验Token

        ↓

    删除Token

        ↓

    扣Redis库存                          (就会遇到一系列redis问题,redis的面试题都可能在这里问到)

       ↓

    发送MQ                                (这一步可能会存在:redis扣库存成功,但是生成订单失败的情况)

       ↓

    生成订单                                       

        ↓

    扣减MySQL库存                    

完整请求流程

⚠️ 七、优缺点分析

优点 缺点
有效削峰 需要预热令牌池
保护数据库 令牌设计复杂
高并发可控 存在资源浪费

❓ 八、面试常见问题

  • 秒杀令牌如何防止重复使用?
  • 令牌池如何初始化?
  • 如何避免令牌被提前抢完?
  • Redis 如何保证令牌操作原子性?

🚀 九、总结

秒杀令牌机制的本质是流量准入控制,而不是业务逻辑优化。

核心思想:

  • 用 Redis 控制入口流量
  • 用有限令牌限制请求数量
  • 用 MQ 保证异步削峰

一句话总结:秒杀令牌解决的不是“如何下单”,而是“谁能下单”。

上一篇:OAuth2三方登录授权码模式深度解析

下一篇:

相关文章

NEW个对象 NEW个对象
JAVA是世界上最好的语言