tp6万级并发抢购核心是分层拦截、错峰执行、原子控制:redis用decr原子扣减拦截95%请求;队列异步处理订单;数据库用乐观锁update兜底;辅以限流、多级缓存和连接池加固。

TP6 处理 1 万并发抢购,核心不是“硬扛”,而是分层拦截、错峰执行、原子控制。数据库击穿本质是大量请求同时穿透缓存直击 DB,导致连接打满、锁冲突、超卖或崩溃。关键要让绝大多数请求在 Redis 层就终结,只让极小部分真正有效的请求落到数据库。
Redis 层原子扣减:用 DECR 拦住 95% 请求
库存字段必须初始化为非负整数(如 INCR stock:1001 100),抢购接口直接调用 $redis->decr('stock:1001')。返回值是减后的值,判断 if ($val >= 0) 即表示扣减成功。DECR 是单命令原子操作,Redis 单线程串行执行,不存在“读-判-写”时间窗口,天然防超卖。别用 GET+SET 或模型 find+save,那是击穿高发区。
队列削峰:抢购接口只做两件事
抢购控制器内只做:① Redis 原子扣库存;② 调用 Queue::push(ConfirmOrderJob::class, ['goods_id' => 1001, 'user_id' => 123]) 推消息进队列。订单创建、支付校验、库存落库、通知发送等全部交给后台消费者异步处理。需单独运行 php think queue:listen --queue=high,避免和 Web 进程争资源。消息体只传 ID 和签名,敏感数据实时查库获取。
数据库层兜底:乐观锁 UPDATE 语句直击行锁
异步下单消费时,不能先查再 update。必须用原生 SQL 或 Db::raw 构造原子更新:$res = Db::name('goods')->where('id', 1001)->where('stock', '>=', 1)->update(['stock' => Db::raw('stock - 1')]);
检查 $res === 1 才算真正扣减成功;若为 0,说明库存已被清空或条件不满足,直接丢弃该任务。加索引确保 where 条件走主键或唯一索引,避免全表扫描锁表。
配套加固:限流 + 多级缓存 + 连接池
- 用中间件对
/api/flashbuy路由做令牌桶限流(如 500 req/min/IP),过滤异常刷量 - 商品详情页等热点数据,用
Cache::store('redis')->remember()+Cache::store('file')->get()构建多级缓存,降低 Redis 压力 - MySQL 配置连接池:
'pool_size' => 100,并启用读写分离,写走主库、读走从库轮询,分散负载
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











