Skip to content

Latest commit

 

History

History
204 lines (143 loc) · 12.2 KB

File metadata and controls

204 lines (143 loc) · 12.2 KB
title 冗余设计详解:RTO/RPO、高可用集群、同城灾备与异地多活
description 冗余设计详解,讲解硬件冗余、服务冗余、数据冗余和地域冗余,覆盖 RTO/RPO、高可用集群、主备模式、主主模式、同城灾备、异地灾备、同城多活、异地多活和故障转移。
category 高可用
icon mdi:server-network-outline
tag
冗余设计
容灾
head
meta
name content
keywords
冗余设计,高可用集群,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.8
Loading
  • RPO(Recovery Point Objective,恢复点目标):可容忍的 最大数据丢失量,即从上次备份到故障发生之间的数据。RPO = 0 表示不允许丢失任何数据,但通常需要同步复制作为代价,写入延迟会受到最慢副本影响。
  • RTO(Recovery Time Objective,恢复时间目标):可容忍的 最大恢复时间,即从故障发生到系统恢复正常服务的时间。RTO = 0 表示服务不能中断。

下面的 RPO/RTO 是典型配置下的参考值,实际结果取决于复制方式(同步/异步)、故障检测阈值、切换自动化程度和团队运维能力。

架构方案 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.8
Loading

高可用集群

高可用集群 是指同一份服务部署两份或者多份,当正在使用的服务突然挂掉的话,可以切换到另外一台服务,从而保证服务的高可用。

高可用集群有两种常见模式:

模式 说明 优点 缺点
主备模式(Active-Standby) 主节点提供服务,备节点待命 实现简单,数据一致性好 资源利用率低,备节点闲置
主主模式(Active-Active) 多个节点同时提供服务 资源利用率高,无单点故障 写入冲突需要应用层解决;自增 ID、唯一约束等可能冲突

主备模式的数据一致性好,通常是建立在单主写入的前提下;如果采用异步复制,主备切换时仍可能丢失尚未同步的数据。高可用集群单纯是服务的冗余,并没有强调地域。同城灾备、异地灾备、同城多活和异地多活实现了地域上的冗余。

同城灾备

同城灾备 不是简单地将服务冗余部署在同一个机房内,而是将主服务和备用服务分别部署在 同一个城市的不同机房 中。并且,备用服务不处理请求。这样可以避免单个机房出现停电、火灾等故障时导致服务完全不可用。

  • 适用场景:对 RTO 要求较高(分钟级),成本有限的企业。
  • 典型配置:两个机房距离 30~100 公里,通过专线连接,专线延迟通常在毫秒级,同步复制是否可接受取决于业务写入延迟要求。

异地灾备

异地灾备 类似于同城灾备,不同的是,相同服务部署在 异地(通常距离较远,甚至是在不同的城市或者国家)的不同机房中

  • 适用场景:需要防范区域性灾难(地震、洪水)的核心业务系统。
  • 挑战:网络延迟较大,数据同步通常采用异步方式,可能存在数据丢失。

同城多活

同城多活 类似于同城灾备,但 备用服务可以处理请求,这样可以充分利用系统资源,提高系统的并发。

  • 适用场景:对性能和可用性都有较高要求的系统。
  • 技术要点:需要解决数据同步、流量调度、会话管理等问题。

异地多活

异地多活 将服务部署在 异地的不同机房 中,并且,它们可以 同时对外提供服务

和传统的灾备设计相比,同城多活和异地多活最明显的改变在于 “多活”,即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况,比如火灾、地震等自然或者人为灾害,以及区域性网络中断、机房级故障、合规要求等场景。

同城和异地的主要区别在于 机房之间的距离。异地通常距离较远,甚至是在不同的城市或者国家。

故障转移机制

光做好冗余还不够,必须要配合上 故障转移(Failover) 才可以!所谓故障转移,简单来说就是 将流量从故障节点快速、自动地切换到健康节点,整个过程不需要人为干涉

故障转移通常包含以下几个步骤:

  1. 故障检测:通过心跳检测、健康检查等机制发现故障节点。检测阈值要权衡误判和漏判,太敏感容易误切,太保守会延长故障时间。
  2. 故障确认:避免误判,通常需要多次检测确认,并通过多数派投票、仲裁节点或租约机制防止脑裂。
  3. 故障切换:将流量切换到备用节点。
  4. 故障通知:发送告警通知运维人员。
  5. 故障恢复:故障节点恢复后重新加入集群。

Redis 哨兵模式示例

哨兵模式的 Redis 集群中,Sentinel 集群通过投票确认 master 故障后,会自动执行故障转移,将某一台 slave 升级为新的 master,确保整个 Redis 系统的可用性。生产环境通常至少部署 3 个 Sentinel 实例以保证 Quorum 有效性,并重点关注 down-after-millisecondsfailover-timeout 等参数。

Nginx + Keepalived 示例

Nginx 可以结合 Keepalived 来实现高可用。如果 Nginx 主服务器宕机的话,Keepalived 可以基于 VRRP 协议自动进行故障转移,备用 Nginx 主服务器升级为主服务。并且,这个切换对外是透明的,因为使用的 虚拟 IP(VIP),虚拟 IP 不会改变。生产中还要根据业务选择抢占或非抢占模式,避免主节点恢复后发生不必要的二次切换。

异地多活的挑战

异地多活架构实施起来非常难,需要考虑的因素非常多:

挑战 说明 解决思路
数据一致性 多个机房数据如何保持一致 单元化路由、最终一致性、TCC/Saga、冲突解决机制
网络延迟 异地机房之间网络延迟较大 就近接入、数据分区
流量调度 如何将用户请求分配到合适的机房 DNS 智能解析、GSLB
会话管理 用户会话如何在多机房之间共享 分布式会话、无状态设计
成本 多机房建设和运维成本高 按业务重要性分级部署

如果你想要深入学习异地多活相关的知识,推荐以下资料:

异地多活的核心取舍可以用 CAP 来理解:跨地域网络延迟和分区不可避免,系统必须在强一致性和可用性之间取舍。常见做法是按用户或地域做单元化分片,让大部分读写落在同一机房;跨单元操作再通过 TCC / Saga、对账补偿或业务冲突解决保证最终一致。并不是所有业务都需要异地多活,通常要按业务影响面、故障概率、建设成本综合评估。