2、高可用架构基础:单点故障(SPOF)概念、冗余设计原则、负载均衡原理、健康检查与故障转移

聊高可用,咱们得先搞清楚一个最根本的问题——系统为什么会挂?

我做了十几年运维,见过太多事故了。说白了,大部分宕机都源于一个共同点:单点故障(SPOF)。只要某个环节是唯一的,它一挂,整个服务就跟着完蛋。

2.1 单点故障(SPOF)—— 系统的阿喀琉斯之踵

单点故障,英文叫 Single Point of Failure。指的是系统中某个组件一旦失效,就会导致整个系统不可用。

举个例子。你想想看,一个 Web 服务只有一台服务器。这台服务器挂了,网站就打不开了。这台服务器就是 SPOF。

我在项目中遇到过最典型的案例:某电商平台把数据库部署在一台物理机上,没有做主从。结果硬盘坏了,数据恢复花了整整两天。两天啊,损失惨重。

SPOF 的常见类型:
  • 硬件单点:单台服务器、单块硬盘、单个电源
  • 软件单点:单实例数据库、单节点缓存
  • 网络单点:单条链路、单个交换机
  • 人员单点:只有一个人会修某个系统
注意:人员单点往往被忽略。我曾经见过一个团队,核心系统的维护只有一个人懂。他休假期间出了问题,没人能处理。嗯,这很要命。

2.2 冗余设计原则 —— 别把所有鸡蛋放一个篮子里

解决 SPOF 的办法很简单:冗余。说白了就是多准备几份。

但冗余不是瞎堆机器。我总结了几条核心原则:

  1. N+1 原则:实际需要 N 台,至少准备 N+1 台。比如需要 3 台 Web 服务器扛流量,那就部署 4 台。
  2. 故障隔离:冗余的组件之间要能独立运行。一台挂了,不影响另一台。
  3. 无状态设计:尽量让服务不保存状态。状态集中到数据库或缓存里。这样任何一台服务器都能处理请求。
  4. 跨可用区部署:别把服务器放同一个机房。万一机房断电呢?

我个人习惯,在设计冗余时一定会问自己一个问题:「如果这个组件现在立刻消失,系统还能撑多久?」

避坑指南:我曾经犯过一个错——做了冗余,但两台机器配置不一样。结果主节点挂了,备节点扛不住流量,照样崩。冗余的机器,性能要一致。

2.3 负载均衡原理 —— 流量分发的艺术

有了冗余的服务器,怎么把请求分给它们?这就是负载均衡干的事。

负载均衡的核心就一句话:把流量均匀地分到后端多台服务器上

常见的负载均衡算法:

算法 原理 适用场景
轮询(Round Robin) 按顺序轮流分配 后端服务器性能一致
加权轮询 给性能好的机器分配更多请求 服务器性能不均
最少连接 分配给当前连接数最少的机器 长连接场景
IP Hash 根据客户端 IP 计算哈希,固定分配 需要会话保持

你想想看,如果不用负载均衡,直接让客户端随机选一台服务器,会怎样?

嗯,很可能某台机器被挤爆,其他机器闲着。负载均衡就是解决这个问题的。

下面我用一张图展示负载均衡的核心流程:

客户端 负载均衡器 (Nginx / LVS / F5) 服务器 A 服务器 B 服务器 C 实线:请求流量 虚线:健康检查 负载均衡器定期检查后端状态

这张图很直观。客户端请求先到负载均衡器,它再根据算法分给后端服务器。同时,负载均衡器会通过健康检查(虚线)确认每台服务器是否活着。

2.4 健康检查与故障转移 —— 自动发现并处理故障

光有负载均衡还不够。如果后端某台服务器挂了,负载均衡器还继续往它发请求,那用户就会看到报错。

所以需要健康检查

健康检查就是负载均衡器定期向后端服务器发探测请求。常见的检查方式:

  • TCP 端口检查:看端口是否在监听。最简单,但不够精确。
  • HTTP 状态码检查:请求一个特定 URL,看返回 200 还是 500。
  • 自定义脚本检查:执行一个脚本,检查业务逻辑是否正常。

一旦健康检查发现某台服务器挂了,负载均衡器就会把它从可用列表中移除。这就是故障转移

故障转移的关键点:
  • 自动摘除:故障机器自动下线,不再接收新请求
  • 自动恢复:机器恢复后,自动加回集群
  • 连接耗尽:优雅关闭,等正在处理的请求完成再下线

我曾经遇到过一个问题:健康检查间隔设得太长(比如 30 秒)。结果服务器挂了,负载均衡器还在往它发请求,用户白白等了 30 秒的报错。后来我改成 3 秒检查一次,连续 3 次失败就摘除。效果好了很多。

建议:健康检查的间隔和超时时间要合理设置。太短会增加负载,太长会延迟故障发现。一般建议 3-5 秒检查一次,连续 2-3 次失败视为宕机。

2.5 实战:Nginx 负载均衡配置示例

说了这么多理论,咱们看个实际例子。用 Nginx 做负载均衡,配置很简单:

upstream backend {
    # 定义后端服务器池
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 backup;  # 备用节点

    # 健康检查(需要 nginx_upstream_check_module)
    check interval=3000 rise=2 fall=3 timeout=1000;
}

server {
    listen 80;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

这段配置里:

  • weight 控制权重,性能好的机器多分点流量
  • backup 标记备用节点,平时不干活,其他机器全挂了才顶上
  • check 配置健康检查,3 秒检查一次,连续 3 次失败就摘除

你想想看,有了这套机制,就算某台服务器突然宕机,用户也几乎感知不到。负载均衡器会自动把流量切到其他健康的机器上。

嗯,这就是高可用的基础。说白了就是:别让任何组件成为唯一的依赖。冗余 + 负载均衡 + 健康检查,这三板斧用好了,系统的可用性就能从 99% 提升到 99.9% 甚至更高。

最后提醒一句:冗余不是万能的。如果整个机房都断电了,你冗余再多机器也没用。所以还要考虑跨机房、跨地域的容灾。这个我们后面会详细讲。

公众号:蓝海资料掘金营,微信deep3321