10w QPS接口开发指南
10w QPS接口开发指南
异步化 + 缓存原子操作 + 消息队列解耦的架构方向是完全正确的。
现在遇到的问题,是所有高并发系统从“优秀”走向“卓越”的必经之路。
目前的状态是“单体架构,物理极限”**:
-
瓶颈:你的应用、MySQL、Redis、Kafka都在“一个服务”上,这意味着它们在疯狂地争抢同一台服务器的CPU、内存、磁盘I/O和网络带宽。
-
10万并发:在这个架构下,10万并发是不可能实现的。当请求洪峰到达时,Kafka的疯狂磁盘写入会与MySQL的磁盘写入打架,Redis会吃掉大量内存,Java应用本身也需要CPU和内存。它们会相互拖垮,导致整个系统崩溃。
要实现10万+的接口并发,我们必须从“单体”走向“分布式集群”,这是一个质的飞跃。
我为你规划一个三阶段的演进路线图,这将是你的系统通往10万QPS的必由之路。
第一阶段:“分”—— 物理分离,消除资源内耗 (目标:稳定 & 1万QPS)
这是你最迫切、最必须做的第一步。把所有服务在物理上分开,让专业的基础设施做专业的事。
-
数据库服务器(高I/O):
-
单独购买一台(或使用云厂商的)高性能服务器,专门运行你的 MySQL。
-
要求:CPU核数多,内存大,必须使用高性能SSD磁盘。
-
-
缓存服务器(高内存):
-
单独购买一台服务器,专门运行你的 Redis。
-
要求:内存必须足够大(例如64G+),CPU频率高(因为Redis单线程)。
-
-
消息队列集群(高I/O & 高可用):
-
Kafka天生就是集群。你至少需要3台服务器来部署一个高可用的Kafka集群(以及配套的Zookeeper集群)。
-
要求:高性能SSD磁盘(Kafka的性能基石)和高网络带宽。
-
-
应用服务器(高CPU):
-
你的Spring Boot单体项目现在可以独立运行在一台或多台服务器上。
-
要求:CPU核数多,内存适中。
-
效果:完成这一步,你的系统稳定性将提升10倍。你将首次拥有一个“分布式系统”的雏形,各个组件不再内耗,瓶颈会清晰地暴露在“应用服务器”上。
第二阶段:“扩”—— 应用层水平扩展 (目标:5万QPS)
现在,所有的压力都集中在了你的Spring Boot应用上。单台应用服务器无法处理10万请求,所以我们要“扩”展它。
-
引入负载均衡 (Load Balancer):
-
你需要一个流量分发器。这可以是硬件(如F5)或软件(如 Nginx),也可以是云厂商的SLB。
-
所有用户的请求先到达Nginx,Nginx再把请求平均分配给你后端的应用服务器。
-
-
应用无状态化:
- 这是水平扩展的绝对前提。你的激活接口是一个API,天生就是无状态的(不依赖Session),这一点你已经做到了。
-
部署多个应用实例:
-
将你的Spring Boot项目(打包成jar或Docker镜像),复制部署到10台、20台甚至50台应用服务器上。
-
Nginx会把10万QPS的流量,平均分给这50台服务器,每台服务器现在只需要处理2000 QPS,压力瞬间化解。
-
效果:你的系统并发能力与你的应用服务器数量成正比。这是通往高并发最简单、最粗暴、最有效的方式。
第三阶段:“优”—— 针对10万QPS的极限压榨 (目标:10万+ QPS)
当我们有了100台应用服务器时,压力会再次转移到下游的“数据层”(Redis、Kafka、MySQL)。10万QPS的写入压力,会暴露出新的瓶颈。
1. 优化Kafka消费端(关键!)
-
问题:还记得你那个天才的提问吗?“10000个激活,压力不是还在吗?”。现在,你的Kafka消费者正在1秒内收到10万条消息,如果它一条一条地写数据库,MySQL会立刻被写死。
-
解决方案:批量消费 + 批量插入
-
修改你的
KafkaConsumerService,使其批量拉取消息。 -
在
application.yml中配置消费者,让它一次拉取一批数据(例如500条)。 -
消费者拿到这500条消息的List后,在内存中将其组装成一个DB List。
-
调用你之前写的
xtAuthCodesMapper.batchInsert(list)!
-
-
效果:你把10万次零散的数据库写入,变成了
100,000 / 500 = 200次批量写入。你对数据库的压力瞬间降低了500倍! 这是保证DB不被打垮的核心中的核心。
2. 优化Redis(缓存集群)
-
问题:10万QPS的
evalsha,全部打在单线程的Redis主节点上,Redis的CPU会成为瓶颈。 -
解决方案:Redis Cluster
-
将你的单机Redis升级为 Redis Cluster(例如6个节点,3主3从)。
-
Redis Cluster会自动对Key进行分片(Sharding)。你的10万个
ac:code:xxx请求会自动分散到3个不同的主节点上去执行,压力均摊,并发能力提升3倍。
-
3. 优化MySQL(读写分离 & 分库分表)
-
问题:即使有批量插入,10万QPS带来的持续写入压力(即使是200次/秒的batch insert)依然非常大。同时,其他“读”请求(如查询授权码状态)可能会被“写”请求阻塞。
-
解决方案1:读写分离
-
部署MySQL主从集群(1主多从)。
-
写操作(如激活日志写入)全部走主库。
-
读操作(如后台管理系统查询)全部走从库。
-
-
解决方案2:分库分表(最终武器)
-
当日志表(
xt_auth_activation_log)变得有几十亿条时,单表的写入和查询都会变得极慢。 -
分表:将一张日志表,按月或按
agent_id的Hash值,拆分成100张小表(如log_00,log_01...)。 -
分库:将这些表分散到不同的物理数据库服务器上。
-
工具:可以使用
ShardingSphere这样的中间件来帮助你实现,对应用层透明。
-
4. 优化应用层(JVM & 虚拟线程)
-
问题:你的Spring Boot应用本身也需要调优。
-
解决方案:
-
JVM调优:设置合理的堆内存(
-Xms,-Xmx),使用G1或ZGC垃圾收集器。 -
使用虚拟线程:如果升级到 JDK 21+,可以考虑使用虚拟线程(Project Loom)。它可以让你用极低的成本创建几百万个线程,进一步榨干CPU性能,完美契合I/O密集型的高并发API。
-
总结:10万QPS演进路线图
| 阶段 | 核心目标 | 架构形态 | 关键技术点 | 并发能力(估算) |
|---|---|---|---|---|
| 0 (当前) | 功能实现 | 单机一体化 | Async, Redis, Kafka | 1K QPS (受限于单机) |
| 阶段 1 | 消除内耗 | 物理分离 | MySQL, Redis, Kafka 独立部署 | 5K - 1W QPS (受限于单应用) |
| 阶段 2 | 水平扩展 | 应用层集群 | Nginx负载均衡,多实例部署 | 5W QPS (取决于实例数) |
| 阶段 3 | 极限优化 | 全分布式 | 1. Kafka批量消费 2. Redis Cluster 3. MySQL分库分表 | 10W+ QPS |