当用户规模突破百万,单机房部署已经无法满足可用性和性能要求。多城市多地部署是必经之路。这篇文章分享我在多地部署过程中的实战经验。
一、为什么需要多地部署
1.1 单机房的局限性
| 问题 | 影响 |
|---|---|
| 单点故障 | 机房断电/网络故障,服务全挂 |
| 延迟问题 | 距离远用户延迟高 |
| 容量瓶颈 | 单机房承载能力有限 |
| 合规要求 | 数据需存储在特定区域 |
1.2 多地部署的目标
| 目标 | 说明 |
|---|---|
| 高可用 | 任一机房故障,服务不中断 |
| 低延迟 | 用户就近访问 |
| 容灾 | 数据不丢失 |
| 合规 | 数据按要求存储 |
二、多地部署架构设计
2.1 整体架构
2.2 机房规划
| 机房 | 角色 | 用户覆盖 | 服务比例 |
|---|---|---|---|
| 北京 | 主机房 | 北方用户 | 40% |
| 上海 | 从机房 | 华东用户 | 35% |
| 广州 | 从机房 | 南方用户 | 25% |
2.3 服务分层
| 服务类型 | 部署策略 | 说明 |
|---|---|---|
| 无状态服务 | 全机房部署 | 用户服务、房间服务 |
| 有状态服务 | 主从部署 | 消息服务、RTC服务 |
| 数据层 | 主从同步 | MySQL、Redis |
三、数据同步方案
3.1 MySQL主从同步
北京机房(主)
· Binlog同步 ──▶ 上海机房(从)
· Binlog同步 ──▶ 广州机房(从)
写入:只写主机房 读取:就近读取
同步延迟:
· 同城:<1ms
· 跨城:10-50ms
· 跨国:100-300ms
3.2 Redis同步
方案一:主从复制
北京机房(主)
· 复制 ──▶ 上海/广州(从)
方案二:Redis Cluster多机房
Redis Cluster
· 北京机房:主分片 0, 2, 4
· 上海机房:主分片 1, 3, 5
· 广州机房:从分片(备份)
3.3 数据一致性策略
| 策略 | 适用场景 | 延迟 | 一致性 |
|---|---|---|---|
| 强一致性 | 支付、账户 | 高 | 强 |
| 最终一致性 | 消息、动态 | 低 | 弱 |
| 因果一致性 | 社交关系 | 中 | 中 |
四、流量调度
4.1 DNS智能解析
用户DNS查询,DNS服务器判断用户位置
· 华北用户 → 北京机房IP
· 华东用户 → 上海机房IP
· 华南用户 → 广州机房IP
4.2 就近接入
4.3 故障切换
北京机房故障:
-
DNS检测到故障
-
DNS更新解析结果, 北京用户 → 上海机房
-
服务自动切换,上海机房接管北京流量
五、跨机房服务调用
5.1 服务发现
每个机房独立的Nacos集群:
· 北京Nacos
· 上海Nacos
· 广州Nacos
服务注册:
· 北京服务实例 → 北京Nacos
·上海服务实例 → 上海Nacos
· 广州服务实例 → 广州Nacos
跨机房调用:
· 优先调用本机房服务
· 本机房不可用时调用其他机房
5.2 调用策略
// 服务调用优先级
public ServiceInstance selectInstance(List<ServiceInstance> instances) {
String localZone = getCurrentZone();
// 优先选择同机房
List<ServiceInstance> local = instances.stream()
.filter(i -> i.getZone().equals(localZone))
.collect(Collectors.toList());
if (!local.isEmpty()) {
return randomSelect(local);
}
// 无同机房实例,选择延迟最低的
return selectLowestLatency(instances);
}
六、房间数据的特殊处理
6.1 问题描述
语音房间的状态数据(成员列表、音频流)实时性要求高,跨机房同步延迟会影响体验。
6.2 解决方案
房间数据本地化:
用户创建房间,根据创建者位置选择机房
· 北京用户 → 北京机房创建
· 上海用户 → 上海机房创建
· 广州用户 → 广州机房创建
房间数据存储:
· 房间元数据:所有机房同步(允许延迟)
· 房间实时状态:只存储在创建机房
用户访问非本地房间:
上海用户访问北京房间
方案一:跨机房访问(延迟50-100ms)
方案二:提示用户「该房间为异地房间,可能延迟」
七、容灾演练
7.1 演练场景
| 场景 | 演练内容 | 预期结果 |
|---|---|---|
| 单服务故障 | kill某个服务 | 自动重启/切换 |
| 单机房网络故障 | 断开机房网络 | DNS切换到其他机房 |
| 数据库主从切换 | 主库故障 | 从库自动升级为主 |
| 全机房故障 | 模拟全部不可用 | 有异地备份可恢复 |
7.2 演练流程
演练前:
· 通知所有相关人员
· 准备回滚方案
· 监控大屏就位
演练中:
· 执行故障注入
· 观察系统行为
· 记录恢复时间
演练后:
· 分析演练结果
· 修复发现的问题
· 更新应急预案
八、成本控制
8.1 成本构成
| 成本项 | 占比 | 说明 |
|---|---|---|
| 服务器 | 50% | 计算+存储 |
| 带宽 | 30% | 跨机房专线+公网 |
| 第三方服务 | 15% | IM、RTC、CDN |
| 其他 | 5% | 监控、日志等 |
8.2 成本优化
| 优化点 | 方案 | 效果 |
|---|---|---|
| 带宽 | 压缩、缓存、减少跨机房调用 | 节省20% |
| 服务器 | 弹性伸缩、资源复用 | 节省15% |
| 数据存储 | 冷热分离、归档 | 节省10% |
九、经验总结
9.1 成功经验
| 经验 | 说明 |
|---|---|
| 先规划后实施 | 多机房架构要提前规划 |
| 监控先行 | 跨机房监控是基础 |
| 定期演练 | 容灾能力靠演练验证 |
| 文档完善 | 每个决策都要文档化 |
9.2 踩过的坑
| 坑 | 说明 |
|---|---|
| 数据同步延迟被忽视 | 导致数据不一致 |
| DNS缓存时间过长 | 故障切换慢 |
| 跨机房调用过多 | 延迟高、成本高 |
| 容灾演练不足 | 真故障时手忙脚乱 |
下篇预告: 《社交App安全架构:防刷、防作弊、内容审核》——安全是业务护城河。
持续输出社交App开发实战经验,关注我,一起成长。