
秒杀系统最怕的其实不只是“流量大”。正常用户再多至少大家都是打开页面 ↓ 看商品 ↓ 点抢购 ↓ 提交订单黄牛脚本就不一样了。可能在秒杀开始的一瞬间100个账号 1000个请求 几十台代理机器同时打进来。如果系统只遵循谁请求先到库存就给谁。最后很可能出现一种很尴尬的结果服务器扛住了商品却全被脚本抢走了。所以真正的秒杀系统除了抗高并发还必须解决另一个问题这个请求到底像不像一个正常用户一、系统其实并不能真正知道“你是不是人”这是理解秒杀风控最重要的一点。服务端收到一个请求POST /seckill它看到的只是一些数据userId IP Cookie Token 设备信息 请求时间 行为记录服务器并没有办法隔着网络看见“电脑前面坐的是张三还是一段 Python 代码。”所以真正的实现方式并不是真人 → 放行 机器人 → 拦截而是收集行为特征 ↓ 计算风险 ↓ 低风险放行 中风险验证 高风险拦截也就是说秒杀反黄牛本质上是风险识别而不是机器识别。二、最简单的一层请求频率假设正常用户抢一个商品。可能是10:00:00.123 点击抢购 10:00:01.350 网络重试一次但某个账号出现10:00:00.001 10:00:00.006 10:00:00.011 10:00:00.016 10:00:00.0215毫秒一个请求。基本就不用研究他的鼠标轨迹了。人类正常情况下很难做到这种频率。因此第一层通常就是IP限流 账号限流 设备限流例如同一账号 1秒最多3次 同一设备 1秒最多5次超过直接拒绝。但只靠 IP 不够。因为黄牛完全可以准备代理IP A 代理IP B 代理IP C 代理IP D ...所以真正的风控不会只盯着一个 IP。三、为什么还需要“设备指纹”假设一个黄牛控制了100个账号。表面上账号不同 IP不同 手机号不同看起来像100个人。但仔细一看浏览器版本相同 屏幕分辨率相同 字体环境相同 操作系统相同 设备参数高度一致甚至大量账号都来自同一种运行环境。这时候系统就可以尝试生成Device Fingerprint设备指纹。它不一定是一个真实硬件序列号而是根据多种客户端特征组合出的设备标识。于是原来看到的是账号A 账号B 账号C 账号D进一步分析可能发现┌→账号A 设备X ──┼→账号B ├→账号C └→账号D这就开始可疑了。所以风控经常不是问这个账号有没有问题而是问这些账号之间是不是存在异常关联四、真正厉害的是行为识别脚本最容易暴露的地方其实不是“速度快”。而是太标准了。正常用户的行为通常有随机性。比如进入页面 ↓ 停留2.3秒 ↓ 滑一下页面 ↓ 看商品 ↓ 点击抢购另一个人可能是进入页面 ↓ 停留5秒 ↓ 点击规则 ↓ 返回 ↓ 抢购人类行为天然有噪声。脚本则容易变成请求页面 100ms 请求接口 100ms 请求下单 100ms1000个账号都是100ms 100ms 100ms这反而非常不自然。所以风控系统可以统计页面停留时间 点击间隔 请求间隔 操作路径 失败重试频率 请求时间分布然后判断这组行为到底像不像正常用户。五、一个特别形象的例子假设10点整开始抢茅台。真实用户的请求时间可能是10:00:00.128 10:00:00.417 10:00:01.032 10:00:01.784分布比较散。某批异常账号却全部是账号A 10:00:00.001 账号B 10:00:00.001 账号C 10:00:00.002 账号D 10:00:00.001 账号E 10:00:00.002如果有几百个账号都出现这种情况就很值得怀疑。因为它们很可能不是几百个人同时练成了“毫秒级手速”。更可能是同一套程序在统一调度。所以风控真正找的是异常的规律性。六、账号本身也有“画像”再往下一层可以看账号历史。比如正常用户注册半年 有浏览记录 有正常订单 有地址 偶尔参加活动某个账号昨天注册 没有任何浏览记录 没有历史订单 今天第一次登录 秒杀前1分钟上线 10点整精准请求 抢完立即退出风险显然完全不一样。所以系统可以给账号建立一些特征账号年龄 历史订单数 登录频率 收货地址 支付信息 活动参与频率 退款率 设备更换频率最后形成User Risk Score比如正常老用户 0 新注册账号 10 频繁切换IP 20 多个账号同设备 30 毫秒级高频请求 40假设Risk Score 30 → 正常放行 30 70 → 增加验证 70 → 拒绝秒杀真实系统当然会复杂很多但底层思想基本就是这样。七、验证码为什么不能一上来就给所有人很多系统想到防机器人第一反应就是上验证码。例如滑块 图片验证码 短信验证确实有用。但秒杀系统有一个特殊问题正常用户本来就很多。如果100万人全部先做验证码用户体验下降 验证码服务压力暴涨 正常用户抱怨所以更合理的是低风险用户 → 直接通过 可疑用户 → 滑块验证 高风险用户 → 更强验证或者直接拒绝这叫分级风控。不是所有人都接受同样的验证成本。八、为什么秒杀接口不能直接暴露假设页面里永远写死POST /api/seckill/10001那么脚本根本不用打开页面。它可以直接定时到10:00 ↓ 狂刷接口因此实际设计中经常会增加一个“资格获取”过程。例如进入活动 ↓ 完成必要校验 ↓ 获取短期秒杀资格 ↓ 携带资格访问下单接口资格可以有用户绑定 商品绑定 过期时间 签名 一次性状态服务端再验证资格是否合法 是不是这个用户的 是不是这个商品的 有没有过期 有没有重复使用这并不能让脚本彻底消失。但它能把知道接口地址 可以直接抢变成必须经过前面的业务链路 ↓ 才能获得下单资格攻击成本会高很多。九、为什么一定要多层拦截因为任何单一规则都容易误伤或者被绕过去。只限制 IP换代理只限制账号准备大量账号只看设备伪造设备环境只用验证码可能被打码平台或自动化识别绕过所以真正有效的系统一般是CDN / WAF ↓ IP和网络层风控 ↓ 账号限流 ↓ 设备指纹 ↓ 行为分析 ↓ 风险评分 ↓ 必要时验证码 ↓ 秒杀资格校验 ↓ Redis库存 ↓ MQ ↓ 创建订单黄牛每突破一层都要付出新的成本。反黄牛真正追求的也不是世界上任何脚本都进不来。这个目标基本不现实。更实际的是让批量作弊的成本高到没有收益。十、风控为什么不能写死成一堆 if最简单的系统可能这样写if (requestCount 10) { reject(); } if (accountAge 1) { reject(); } if (deviceUserCount 5) { reject(); }刚开始能用。规则越来越多以后很快就会变成几十个if 规则互相冲突 误杀越来越严重所以成熟一点的做法通常会抽象成特征 ↓ 风险规则 / 风控模型 ↓ Risk Score ↓ 决策例如risk 请求频率 × 权重 设备异常 × 权重 账号异常 × 权重 行为异常 × 权重然后根据风险等级采取不同措施。这样以后发现新的黄牛模式只需要增加新的特征 或者 新的规则不需要把整个秒杀业务重写一遍。总结秒杀系统想区分真实用户和黄牛脚本底层并没有一个神奇的isHuman()真正做的是不断收集信号这个账号正常吗 这个设备正常吗 请求频率正常吗 行为路径正常吗 这些账号有没有关联 请求时间是不是过于规律然后多维特征 ↓ 风险评分 ↓ 分级处理所以反黄牛最核心的思想不是识别出所有机器人。而是识别“正常人很少会出现但批量自动化工具经常出现”的行为模式。最后再通过限流 设备 账号 行为 验证 秒杀资格层层提高作弊成本。这也是秒杀风控最重要的底层逻辑真正有效的反黄牛不是筑一道绝对攻不破的墙而是让批量作弊变得越来越贵。