扩容方案设计
问题
业务快速增长,现有架构即将到达瓶颈,如何设计扩容方案?
答案
扩容决策流程
水平扩展 vs 垂直扩展
| 对比 | 垂直扩展(Scale Up) | 水平扩展(Scale Out) |
|---|---|---|
| 方式 | 升级 CPU / 内存 / 磁盘 | 增加服务器数量 |
| 优点 | 简单,无需改架构 | 理论上无上限 |
| 缺点 | 有物理上限,单点风险 | 需要无状态设计 |
| 适用 | 数据库、Redis 主节点 | Web 服务、API 网关 |
| 停机 | 通常需要停机 | 无需停机 |
Kubernetes HPA 自动扩容
# HPA 基于 CPU/内存自动扩缩容
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # CPU 超过 60% 触发扩容
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
behavior:
scaleUp:
stabilizationWindowSeconds: 30 # 30 秒内快速扩容
policies:
- type: Percent
value: 100 # 每次最多翻倍
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 300 # 缩容等 5 分钟,避免抖动
policies:
- type: Percent
value: 10 # 每次最多缩 10%
periodSeconds: 60
扩容前提:应用必须无状态
水平扩展要求:
- 无本地状态:Session 存 Redis,文件存 OSS
- 幂等接口:同一请求重复调用结果一致
- 健康检查:readinessProbe 就绪后才接流量
数据库扩容方案
# 1. 读写分离(读多写少场景)
# 主库写 → 从库读
# 延迟容忍:报表/搜索可以走从库
# 实时性要求高:强制走主库
# 2. 分库分表(数据量大 / 写入高)
# 水平分片:按 user_id % 4 分到 4 个库
# 垂直拆分:用户库、订单库、商品库分离
# 3. 缓存层(减轻数据库压力)
# Redis 缓存热点数据
# 本地缓存(Caffeine)减少 Redis 访问
各层扩容手册
| 层级 | 扩容方式 | 关键命令 / 操作 |
|---|---|---|
| Nginx | 增加上游节点 | upstream 添加 server |
| K8s | HPA / 手动 scale | kubectl scale --replicas=N |
| MySQL 读 | 添加从库 | CHANGE MASTER TO |
| MySQL 写 | 分库分表 | ShardingSphere 配置 |
| Redis | Cluster 扩容 | redis-cli --cluster add-node |
| Kafka | 增加分区/Broker | kafka-topics.sh --alter |
| ES | 添加数据节点 | 新节点加入集群,分片自动再平衡 |
常见面试问题
Q1: 大促活动前如何做容量预估和扩容?
答案:
- 估算流量:根据历史数据和活动预期,估算峰值 QPS(通常是日常的 3~10 倍)
- 单机压测:对单实例做压测,得到单机承载 QPS
- 计算实例数:
实例数 = 峰值 QPS / 单机 QPS × 1.5(冗余系数) - 提前扩容:活动前 1~3 天完成扩容,预热缓存
- 限流兜底:设置限流阈值,超出容量时降级而不是崩溃
- 演练验证:全链路压测验证扩容后是否满足目标