2、单点故障与冗余设计:SPOF分析、冗余策略、负载均衡、健康检查
各位同学,今天我们来聊聊系统高可用里最基础、也最要命的一个话题——单点故障。
我入行头几年,有一次线上大半夜挂了。查了半天,发现是数据库主库的磁盘满了。就一台机器,没做任何冗余。那晚我盯着监控面板,心里就一个念头:单点,就是定时炸弹。
说白了,单点故障(Single Point of Failure,SPOF) 就是系统中某个组件一旦挂了,整个服务就瘫了。你想想看,交易系统里每一笔订单都经过网关、鉴权、风控、订单中心、支付……任何一个环节是单点,都可能让整个链路断掉。
2.1 单点故障分析:先找到“命门”
怎么找单点?我习惯从两个维度入手:
- 数据流维度:数据经过的每个节点,是不是只有一份?
- 控制流维度:调度、配置、路由这些逻辑,是不是只有一个实例在跑?
常见的单点重灾区:
| 层级 | 典型单点 | 风险说明 |
|---|---|---|
| 网络层 | 单一公网IP、单台交换机 | 入口断了,全完 |
| 应用层 | 单实例网关、单台Web服务器 | 请求无法分发 |
| 数据层 | 单主库、单Redis、单ZooKeeper | 数据写不了,读不了 |
| 基础设施 | 单电源、单机房 | 物理灾难直接团灭 |
2.2 冗余设计策略:主备、主从、多活
找到单点之后,就得用冗余来“对冲”风险。我常用的三种模式:
2.2.1 主备模式(Active-Standby)
一台主节点干活,一台备节点冷眼旁观。主挂了,备顶上。
- 优点:简单,数据一致性容易保证
- 缺点:备机平时闲着,浪费资源;切换需要时间,有短暂不可用
我建议用在对一致性要求高、但对切换时间容忍度尚可的场景,比如数据库主备。
2.2.2 主从模式(Master-Slave)
主节点负责写,从节点负责读。主挂了,从节点可以升级为主。
- 优点:读写分离,提升读性能
- 缺点:主从同步有延迟,可能读到旧数据
交易系统里,订单查询、历史流水这些读多写少的场景,主从很实用。但注意,支付、扣库存这种写操作,必须走主库。
2.2.3 多活模式(Multi-Active)
多个节点同时提供服务,没有主从之分。流量可以打到任意节点。
- 优点:利用率高,故障时流量自动切换,用户体验好
- 缺点:架构复杂,需要解决数据冲突、分布式事务等问题
多活是终极目标,但代价也最大。我一般建议先从主备或主从起步,等业务规模上来了再演进到多活。
2.3 负载均衡技术:把流量“摊平”
冗余做好了,还得有东西把请求分到各个节点上。这就是负载均衡的活。
我按层级给你捋一捋:
2.3.1 DNS负载均衡
最简单粗暴。一个域名配多个IP,DNS轮询返回不同IP。
- 优点:免费,配置简单
- 缺点:DNS缓存导致切换慢,无法感知后端健康状态
我一般只用它做第一层流量分发,比如按地域把用户引到不同机房。
2.3.2 Nginx/HAProxy(软件负载均衡)
这是应用层最常用的。Nginx支持HTTP、TCP、UDP多种协议,配置灵活。
upstream backend {
server 192.168.1.10:8080 weight=5;
server 192.168.1.11:8080 weight=3;
server 192.168.1.12:8080 backup; # 备用节点
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
这段配置里,weight控制权重,backup表示备用。Nginx还支持least_conn、ip_hash等算法,按需选。
max_fails和fail_timeout。比如连续3次失败,就认为节点挂了,自动摘除30秒。这样能避免把请求打到“半死不活”的节点上。
2.3.3 F5(硬件负载均衡)
F5是硬件设备,性能强悍,自带健康检查、SSL卸载、DDoS防护。
- 优点:吞吐量高,功能丰富,稳定
- 缺点:贵,一台几十万,扩容要买硬件
大厂的核心入口通常会放F5,后面再挂Nginx做细粒度分发。我见过一个交易系统,F5扛着每秒几十万连接,稳如老狗。
2.4 健康检查与自动摘除:别让“死节点”拖累系统
冗余和负载均衡都做了,但还有一个坑:节点挂了,负载均衡不知道。
所以必须配健康检查。我常用的方式:
- TCP端口检查:看端口通不通,简单但不够精确
- HTTP接口检查:请求一个特定URL(比如
/health),返回200才算健康 - 自定义脚本检查:执行脚本,检查进程、磁盘、数据库连接等
自动摘除的逻辑:
- 健康检查连续失败N次(比如3次)
- 负载均衡将该节点标记为“不可用”
- 停止向该节点分发新请求
- 继续检查,如果恢复,自动加回
2.5 本章小结:一张图看懂
下面这张图,把单点故障、冗余设计、负载均衡、健康检查串起来了:
从用户请求到数据存储,每一层都可能出现单点。我们用冗余设计消除单点,用负载均衡分发流量,用健康检查确保只把请求发给健康的节点。这三者缺一不可。
好了,这一章就到这里。记住一句话:没有冗余的系统,就是在赌运气。而交易系统,赌不起。