前言
不说废话,这次分享是某500强企业真实亿级流量业务中台技术架构演进过程实战。
核心目标
构建一个兼具高性能、高可用、强一致性的分布式系统,支撑亿级流量场景下的稳定运行。
演进路线大纲
阶段一:横向扩展(应对万级QPS)
核心目标:突破单机性能瓶颈,建立弹性基础
[Nginx]
/ | \
[App1][App2][App3] ← 无状态服务集群
\ | /
[DB Proxy] ← 读写分离中间件
/ \
[Master] ← 写节点
[Slave1][Slave2] ← 读节点集群
关键任务清单:
-
服务无状态化改造
• 会话管理:Spring Session + Redis Cluster(TTL 30分钟)
• 配置文件外置:Nacos配置中心动态下发
• 本地缓存清理:无 → Caffeine(性能提升40%) -
数据库读写分离
• 中间件选型:ShardingSphere-JDBC(轻量级,兼容Spring Cloud)
• 主从同步延迟处理:// 强制走主库的注解 @MasterRoute public void updateOrder(Order order) { // 写操作强制路由到主库 }
• 连接池优化:Druid连接池(MaxActive=200, MinIdle=20)
技术选型对比:
组件 | 方案1 | 方案2 | 最终选择 |
---|---|---|---|
负载均衡 | Nginx | AWS ALB | Nginx + Keepalived(自主可控) |
配置中心 | Spring Cloud Config | Alibaba Nacos | Nacos(配置热更新) |
缓存集群 | Redis Sentinel | Redis Cluster | Redis Cluster(自动分片) |
实施步骤示例:
- 灰度验证:10%流量切到无状态节点
- 全量切换:旧会话数据迁移到Redis
- 性能压测:使用JMeter模拟1万用户并发
典型问题与解决方案:
• 问题:主从延迟导致查询旧数据
方案:关键业务查询强制走主库(@MasterRoute注解)
• 问题:缓存击穿引发DB雪崩
方案:BloomFilter预热+互斥锁重建
阶段二:垂直拆分(支撑十万级QPS)
核心目标:解耦业务,突破单数据库连接数限制
[API Gateway]
/ | \
Order-Service Pay-Service Logistics-Service ← 垂直拆分微服务
/ | \
[OrderDB] [PayDB] [LogisticsDB] ← 分库分表
Shard_00-03 Shard_00-03 Shard_00-03
关键任务清单:
-
业务领域拆分
• DDD划分:订单域、支付域、物流域建立Bounded Context
• 数据库拆分:按业务线独立部署MySQL集群
• 服务通信:OpenFeign+Protobuf(节省30%带宽) -
分库分表实施
• 分片策略:// 订单ID分片算法 int shardNo = (orderId.hashCode() & Integer.MAX_VALUE) % 1024; String tableSuffix = String.format("_%04d", shardNo / 256);
• 分布式ID生成:Leaf-Snowflake(美团开源的ID生成器)
技术选型对比:
组件 | 方案1 | 方案2 | 最终选择 |
---|---|---|---|
分库分表中间件 | MyCAT | ShardingSphere | ShardingSphere(无缝集成Spring) |
事务方案 | 强一致 2PC/ Seata/TCC | 最终一致 本地消息/事务消息 | 多方案混合,适配业务场景 |
监控系统 | Prometheus | SkyWalking | SkyWalking(全链路追踪)、Prometheus(指标监控) |
实施步骤示例:
- 数据迁移:使用DataX进行存量数据分片
- 双写验证:新旧分片同时写入核对数据
- 灰度切换:按用户ID尾号逐步切流
典型问题与解决方案:
• 问题:跨分片分页查询性能差
方案:ES构建二级索引,替代复杂查询
• 问题:分布式事务数据不一致
方案:Seata事务+每日对账任务兜底
阶段三:单元化改造(目标百万级QPS)
1000000*3600 = 36亿次请求/每小时
核心目标:实现异地多活,突破数据库容量瓶颈
[Global DNS]
|
[Traffic Director] ← 基于用户位置路由
/ \
[Unit A: us-east-1] [Unit B: us-west-2] ← 独立单元
/ | \ / | \
Order Payment Inventory Order Payment Inventory ← 微服务副本
DB DB DB DB DB DB ← 单元内数据闭环
关键任务清单:
-
用户分片路由
• 分片算法:// 用户ID哈希分片 int hash = Hashing.murmur3_32().hashString(userId, UTF_8).asInt(); int unitNo = Math.abs(hash % 64); // 分为64个单元
• 路由组件:自研RouteSDK(本地缓存分片映射表)
-
跨单元数据同步
• 同步方案:Unit A → Canal抓取binlog → RocketMQ → Unit B消费
• 冲突解决:版本向量(Version Vector)+最后写入胜出(LWW)
技术选型对比:
组件 | 方案1 | 方案2 | 最终选择 |
---|---|---|---|
单元发现 | Eureka | Nacos | Nacos(元数据路由) |
消息队列 | Kafka | RocketMQ | RocketMQ(事务消息) |
实施步骤示例:
- 单元划分:按用户ID分片,首批部署4个单元
- 数据同步:使用DTS进行实时双向同步
- 流量切换:DNS权重调整逐步切流
典型问题与解决方案:
• 问题:跨单元事务延迟高
方案:TCC模式+异步冲正(最终一致性)
• 问题:热点用户访问倾斜
方案:动态分片(如将大V用户拆分到多个单元)
架构演进性能基线对比
指标 | 阶段1(横向扩展) | 阶段2(垂直拆分) | 阶段3(单元化) |
---|---|---|---|
最大QPS | 8700 | 110000 | 1040000 |
平均延迟 | 85ms | 43ms | 27ms |
故障恢复时间 | 17分钟 | 2分钟 | 10秒 |
扩容耗时 | 22分钟 | 11分钟 | 自动弹性 |
后续我会根据演进的阶段,逐步细化演进路线的实现细节!