thinkphp6支撑万级并发需禁用文件session和select for update悲观锁,改用redis存储session、原子化update乐观锁扣库存,并通过pdo持久连接、redis缓存与热点数据预热降低数据库压力。

ThinkPHP6 要支撑一万并发,单靠默认数据库操作会立刻卡死——核心瓶颈不在框架本身,而在 MySQL 连接争抢、行锁堆积和事务阻塞。真正有效的解法不是“加锁更狠”,而是“让锁变少、变快、变可控”。
用乐观锁替代 for update,避开行锁排队
高并发扣库存、抢名额等场景,别用 SELECT ... FOR UPDATE 加行锁。它会让所有请求在同一条记录上排队等待,QPS 直接腰斩。TP6 中应改用原子化 UPDATE:
- 写法示例:
Db::name('goods')->where('id', $id)->where('stock', '>=', $need)->update(['stock' => Db::raw("stock - $need")]) - 执行后检查返回值:
$res === 1表示成功;$res === 0表示库存不足或已被抢先扣完 - 若需更强一致性,加版本号字段(如
version),WHERE 条件带上version = $expected,UPDATE 同时自增 version
禁用 Session 文件锁,改用 Redis 存储
TP6 默认的 file 驱动 Session 在万级并发下会因文件锁导致大量请求阻塞在 session_start() 上。
- 关闭自动 Session 初始化:在中间件或控制器中手动控制,非必要不开启
- 切换为 Redis 驱动:配置
'type' => 'redis',并确保session.save_handler = redis已在 PHP.ini 中启用 - 设置合理过期时间,避免 Redis 内存暴涨
连接复用 + 主动探测,防止连接池耗尽
MySQL 的 max_connections 通常默认 151,一万并发下极易触发 Too many connections 错误。
- 开启 PDO 持久连接:
'params' => [\PDO::ATTR_PERSISTENT => true],但需配合调大 MySQL 的wait_timeout - 每次查询前轻量探测:
Db::connect()->query('SELECT 1'),快速剔除断连 - 避免长事务:
Db::transaction()内只做必要操作,禁止嵌套或含 sleep、远程请求
热点数据走缓存,数据库只做最终落库
万级并发查同一商品、用户资料?数据库扛不住,缓存才是第一道防线。
- 强制使用 Redis 缓存驱动,禁用 file 缓存(高并发下文件锁是性能杀手)
- 读操作先
Cache::get($key),未命中再查库并Cache::set($key, $data, $ttl) - 写操作采用“先删缓存,再更新库”策略,或延时双删(尤其涉及关联缓存时)
- 对超热 key(如首页 banner)加随机过期时间,防雪崩
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











