冗余设计详解
本文系统讲解冗余设计核心知识,涵盖冗余类型(硬件/软件/数据/服务冗余)、RTO/RPO 指标、高可用集群(主备/主主模式)、同城灾备、异地灾备、同城多活、异地多活架构对比及故障转移机制,助力高可用架构设计与面试。
什么是冗余?#
冗余(Redundancy) 是保证系统和数据高可用的最常用手段,其核心思想是 通过部署多份相同的资源,当某一份资源出现故障时,其他资源可以接管其工作,从而保证系统的持续可用。
冗余设计可以从以下几个维度来理解:
| 冗余类型 | 说明 | 典型实现 |
|---|---|---|
| 硬件冗余 | 关键硬件设备部署多份 | 双电源、双网卡、RAID 磁盘阵列 |
| 软件冗余 | 应用服务部署多个实例 | 集群部署、容器化多副本 |
| 数据冗余 | 数据存储多份副本 | 数据库主从复制、分布式存储多副本 |
| 网络冗余 | 网络链路和设备冗余 | 多运营商接入、双活负载均衡 |
| 地域冗余 | 在不同地理位置部署系统 | 同城灾备、异地多活 |
对于 服务 来说,冗余的思想就是相同的服务部署多份,如果正在使用的服务突然挂掉的话,系统可以很快切换到备份服务上,大大减少系统的不可用时间,提高系统的可用性。
对于 数据 来说,冗余的思想就是相同的数据备份多份,这样就可以很简单地提高数据的安全性。
实际上,日常生活中就有非常多的冗余思想的应用。拿我自己来说,我对于重要文件的保存方法就是冗余思想的应用。我日常所使用的重要文件都会同步一份在 GitHub 以及个人云盘上,这样就可以保证即使电脑硬盘损坏,我也可以通过 GitHub 或者个人云盘找回自己的重要文件。
容灾核心指标:RTO 和 RPO#
在讨论容灾架构之前,需要先理解两个核心指标:
flowchart TB
subgraph Timeline["时间线"]
direction LR
A["上次备份"] --> B["故障发生"] --> C["系统恢复"]
end
A -.->|"数据丢失窗口(RPO)"| B
B -.->|"恢复时间窗口(RTO)"| C
classDef core fill:#4CA497,color:#fff,rx:10,ry:10
classDef highlight fill:#E99151,color:#fff,rx:10,ry:10
class A,B,C core
style Timeline fill:#F5F7FA,stroke:#E0E6ED,stroke-width:1.5px
linkStyle default stroke-width:1.5px,opacity:0.8mermaid- RPO(Recovery Point Objective,恢复点目标):可容忍的 最大数据丢失量,即从上次备份到故障发生之间的数据。RPO = 0 表示不允许丢失任何数据。
- RTO(Recovery Time Objective,恢复时间目标):可容忍的 最大恢复时间,即从故障发生到系统恢复正常服务的时间。RTO = 0 表示服务不能中断。
| 架构方案 | RPO | RTO | 成本 |
|---|---|---|---|
| 单机无备份 | 可能全部丢失 | 不可预估 | 低 |
| 本地备份 | 取决于备份周期 | 小时级 | 低 |
| 同城灾备 | 分钟级 | 分钟~小时级 | 中 |
| 异地灾备 | 分钟~小时级 | 小时级 | 中高 |
| 同城多活 | 秒级 | 秒级 | 高 |
| 异地多活 | 秒级 | 秒级 | 很高 |
冗余架构方案对比#
高可用集群(High Availability Cluster,简称 HA Cluster)、同城灾备、异地灾备、同城多活和异地多活是冗余思想在高可用系统设计中最典型的应用。
flowchart TB
subgraph Grid["冗余架构方案对比"]
direction LR
style Grid fill:#F0F2F5,stroke:#E0E6ED,stroke-width:1.5px
subgraph HACluster["高可用集群"]
direction LR
style HACluster fill:#F5F7FA,stroke:#E0E6ED,stroke-width:1.5px
A1["主节点"] --> A2["从节点"]
end
subgraph LocalDR["同城灾备"]
direction LR
style LocalDR fill:#F5F7FA,stroke:#E0E6ED,stroke-width:1.5px
B1["主机房<br/>(处理请求)"] -.->|"同步"| B2["备机房<br/>(不处理请求)"]
end
subgraph RemoteDR["异地灾备"]
direction LR
style RemoteDR fill:#F5F7FA,stroke:#E0E6ED,stroke-width:1.5px
C1["主机房<br/>北京"] -.->|"异步同步"| C2["备机房<br/>上海"]
end
subgraph LocalActive["同城多活"]
direction LR
style LocalActive fill:#F5F7FA,stroke:#E0E6ED,stroke-width:1.5px
D1["机房A<br/>(处理请求)"] <-->|"双向同步"| D2["机房B<br/>(处理请求)"]
end
subgraph RemoteActive["异地多活"]
direction LR
style RemoteActive fill:#F5F7FA,stroke:#E0E6ED,stroke-width:1.5px
E1["北京机房<br/>(处理请求)"] <-->|"双向同步"| E2["上海机房<br/>(处理请求)"]
end
end
classDef core fill:#4CA497,color:#fff,rx:10,ry:10
classDef external fill:#005D7B,color:#fff,rx:10,ry:10
class A1,B1,C1,D1,D2,E1,E2 core
class A2,B2,C2 external
linkStyle default stroke-width:1.5px,opacity:0.8mermaid高可用集群#
高可用集群 是指同一份服务部署两份或者多份,当正在使用的服务突然挂掉的话,可以切换到另外一台服务,从而保证服务的高可用。
高可用集群有两种常见模式:
| 模式 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| 主备模式(Active-Standby) | 主节点提供服务,备节点待命 | 实现简单,数据一致性好 | 资源利用率低,备节点闲置 |
| 主主模式(Active-Active) | 多个节点同时提供服务 | 资源利用率高,无单点故障 | 数据同步复杂,可能有一致性问题 |
高可用集群单纯是服务的冗余,并没有强调地域。同城灾备、异地灾备、同城多活和异地多活实现了地域上的冗余。
同城灾备#
同城灾备 是指一整个集群可以部署在同一个机房,而同城灾备中相同服务部署在 同一个城市的不同机房 中。并且,备用服务不处理请求。这样可以避免机房出现意外情况比如停电、火灾。
- 适用场景:对 RTO 要求较高(分钟级),成本有限的企业。
- 典型配置:两个机房距离 30~100 公里,通过专线连接。
异地灾备#
异地灾备 类似于同城灾备,不同的是,相同服务部署在 异地(通常距离较远,甚至是在不同的城市或者国家)的不同机房中。
- 适用场景:需要防范区域性灾难(地震、洪水)的核心业务系统。
- 挑战:网络延迟较大,数据同步通常采用异步方式,可能存在数据丢失。
同城多活#
同城多活 类似于同城灾备,但 备用服务可以处理请求,这样可以充分利用系统资源,提高系统的并发。
- 适用场景:对性能和可用性都有较高要求的系统。
- 技术要点:需要解决数据同步、流量调度、会话管理等问题。
异地多活#
异地多活 将服务部署在 异地的不同机房 中,并且,它们可以 同时对外提供服务。
和传统的灾备设计相比,同城多活和异地多活最明显的改变在于 “多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。
同城和异地的主要区别在于 机房之间的距离。异地通常距离较远,甚至是在不同的城市或者国家。
故障转移机制#
光做好冗余还不够,必须要配合上 故障转移(Failover) 才可以!所谓故障转移,简单来说就是 实现不可用服务快速且自动地切换到可用服务,整个过程不需要人为干涉。
故障转移通常包含以下几个步骤:
- 故障检测:通过心跳检测、健康检查等机制发现故障节点。
- 故障确认:避免误判,通常需要多次检测确认。
- 故障切换:将流量切换到备用节点。
- 故障通知:发送告警通知运维人员。
- 故障恢复:故障节点恢复后重新加入集群。
Redis 哨兵模式示例#
哨兵模式的 Redis 集群中,如果 Sentinel(哨兵)检测到 master 节点出现故障的话,它就会帮助我们实现故障转移,自动将某一台 slave 升级为 master,确保整个 Redis 系统的可用性。整个过程完全自动,不需要人工介入。
Nginx + Keepalived 示例#
Nginx 可以结合 Keepalived 来实现高可用。如果 Nginx 主服务器宕机的话,Keepalived 可以自动进行故障转移,备用 Nginx 主服务器升级为主服务。并且,这个切换对外是透明的,因为使用的 虚拟 IP(VIP),虚拟 IP 不会改变。
异地多活的挑战#
异地多活架构实施起来非常难,需要考虑的因素非常多:
| 挑战 | 说明 | 解决思路 |
|---|---|---|
| 数据一致性 | 多个机房数据如何保持一致 | 最终一致性、冲突解决机制 |
| 网络延迟 | 异地机房之间网络延迟较大 | 就近接入、数据分区 |
| 流量调度 | 如何将用户请求分配到合适的机房 | DNS 智能解析、GSLB |
| 会话管理 | 用户会话如何在多机房之间共享 | 分布式会话、无状态设计 |
| 成本 | 多机房建设和运维成本高 | 按业务重要性分级部署 |
如果你想要深入学习异地多活相关的知识,推荐以下资料: