应用多活综述与实践
一、应用多活的相关概念
(1)容灾的关键指标
容灾(Disaster Tolerance),简单而言,是指在自然灾害、设备故障、人为操作破坏等灾难发生时,尽可能保障生产系统数据,保持生产系统的业务不间断地运行。
在衡量系统容灾效果或高可用特性时,一般有两个指标,表达灾难发生时业务的损失程度与恢复效率:
RPO(Recovery Point Objective):即数据恢复点目标,主要指的是业务系统所能容忍的数据丢失量,也就是业务系统恢复服务功能时,恢复得来的数据对应的时间点。例如,RPO=10 分钟意味着系统故障后,最多仅丢失故障前 10 分钟内产生的数据;若 RPO=0,则要求数据零丢失,需依赖实时数据同步技术实现。
RTO(Recovery Time Objective):即恢复时间目标,主要指的是所能容忍的业务停止服务的最长时间,也就是从灾难发生到业务系统恢复服务功能所需要的最短时间周期。例如,RTO=30 分钟意味着灾难发生后,业务需在 30 分钟内恢复服务;若 RTO 接近 0,则需实现业务无感知切换,这也是应用多活的核心目标之一。
(2)容灾的概念辨析
在高可用领域,容灾、容错与灾难恢复等概念相近,有时互通使用,但侧重点不同,也需明确以避免混淆:
容灾(Disaster Tolerance)
核心关注点:灾难发生时业务连续性与数据安全性。
实现方式:搭建冗余站点、数据同步、流量切换。
典型场景:地震导致机房断电,冗余机房接管业务。
容错(Fault Tolerance)
核心关注点:局部组件故障时系统正常运行能力。
实现方式:组件冗余(如双机热备)、故障自动检测与切换。
典型场景:服务器宕机,备用服务器立即接管服务灾难恢复。
灾难恢复(Disaster Recovery)
核心关注点:灾难后的业务重建与数据恢复。
实现方式: 数据备份、系统重建、恢复流程自动化。
典型场景:数据库因病毒攻击损坏,通过备份恢复数据与系统。
(3)容灾的等级划分
根据容灾系统对应用系统的保护程度,可分为三个等级,不同等级对应不同的 RTO、RPO 与实现成本:
数据级容灾:最低级别的容灾,仅实现生产中心数据向容灾中心的复制(如定时备份、异步同步)。灾难发生时,需在容灾中心重新部署应用、恢复数据实例后才能恢复业务,RTO 通常为天级别,RPO 取决于数据同步频率(如 1 小时备份对应 RPO=1 小时)。典型场景:小型企业的核心数据备份(如财务数据定时备份到异地存储)。
应用级容灾:在数据级容灾基础上,容灾中心搭建与生产中心一致的硬件环境(主机、网络)与应用部署。灾难发生时,无需重新部署应用,仅需恢复数据实例、切换网络配置即可恢复业务,RTO 通常为小时级别,RPO 可缩短至分钟级别(如半同步数据同步)。典型场景:中型企业的核心业务容灾(如电商平台的订单系统容灾)。
业务级容灾:最高级别的容灾,容灾中心与生产中心同时处理业务请求,数据实时同步。灾难发生时,仅需切换业务流量即可恢复服务,用户无感知,RTO 可缩短至分钟级别甚至秒级,RPO 接近 0。应用多活即属于业务级容灾范畴,典型场景:大型互联网企业的全域业务(如社交平台、支付系统)。
(4)传统灾备的局限性
传统灾备容灾(冷备、热备)是行业早期主流方案,但其设计理念存在固有缺陷,难以满足大规模业务的高可用需求:
可用性验证缺失:灾备中心日常不对外提供服务,无法常态化验证其硬件、软件、数据同步的可用性,容灾切换时可能出现预想不到的问题(如数据同步中断未发现、应用配置不一致),导致业务无法恢复。真的面临灾难,业务也往往不敢切。
资源利用率低:灾备中心的服务器、存储、网络等资源长期闲置,仅在灾难发生时启用,造成硬件成本、机房租赁成本的严重浪费(部分企业灾备资源利用率不足 10%)。
单地域资源瓶颈:传统灾备容灾依赖“生产中心 + 备用中心”的架构,实际对外服务仍局限于单地域生产中心,当业务体量增长到一定规模(如日活用户超千万),单地域的带宽、服务器算力会成为瓶颈,无法支撑业务横向扩展。
恢复效率低:即使是应用级容灾,灾难发生后仍需人工干预恢复数据实例、切换网络路由,RTO 难以缩短至分钟级别,无法满足金融、电商等对服务连续性要求极高的业务场景。
二、应用多活的设计核心
(1)应用多活的核心目标
应用多活是指在同城或异地搭建多个生产机房(节点),所有机房内的应用同时对外提供服务,数据实时同步,灾难发生时通过自动化流量切换实现业务无感知恢复的容灾架构。其核心目标可拆解为两点:
最小化故障影响:通过故障隔离机制,确保单个机房或组件故障仅影响部分用户(如某地域机房故障仅影响该地域 20% 用户),而非全量业务中断。
最大化恢复效率:通过自动化流量路由与数据同步,将 RTO 缩短至分钟级别,RPO 接近 0,实现业务 “故障无感知”。
(2)应用多活的核心支柱
应用多活架构的实现依赖“隔离、冗余、路由”三大支柱,三者层层递进、相互支撑,共同构建业务连续性保障体系:
● 隔离(Isolation):控制故障“爆炸半径”的基础。
隔离的核心是将系统拆分为独立单元,避免单个故障扩散至全系统。拆分维度包括:
逻辑数据拆分:按业务维度(如用户 ID 哈希、地域)将数据分片,每个分片仅在指定机房处理(如用户 ID 哈希值为单数的用户由机房 A 处理,双数的用户由机房 B 处理)。
物理部署拆分:将应用、数据库、消息队列等组件按机房部署独立集群,机房间网络、电源、硬件完全独立,避免“单点故障”(如机房 A 断电不影响机房 B)。
● 冗余(Redundancy):保障故障“恢复能力”的前提。
冗余是指为关键组件与数据提供备份,确保故障发生时存在可用替代资源。冗余维度包括:
数据冗余:通过实时同步(如 MySQL 半同步复制、分布式数据库多副本)将数据复制到多个机房,避免单机房数据丢失。
组件冗余:每个机房内部署多副本组件(如应用服务器集群、数据库主从架构),同时跨机房部署备用集群(如机房 A 的数据库故障时,机房 B 的备用数据库可立即接管)。
● 路由(Routing):实现“动态可用性”的关键。
路由指通过自动化流量调度,将用户请求导向可用机房与组件,同时保障数据读写一致性。其核心要求包括:
流量路由一致性:从可用性角度,所有业务请求需在可接受时间内响应,且请求质量不受部署机房物理距离、底层设施差异影响。因此需从入口流量起,让每一层技术组件具备流量识别与纠错能力,减少不合理跨机房 / 跨地域访问带来的延迟。
数据读写一致性:从准确性角度,所有业务数据需在可接受时间内保持正确(数据延迟足够短、无错乱)。这要求数据层具备数据同步能力,且在流量调配时,能为业务提供容错与保护方案,避免数据冲突引发的不一致问题。
(3)应用多活的典型架构
根据机房物理距离(同城 / 异地)与集群部署方式,应用多活可分为单集群、多集群、单元化三种典型架构模型,不同模型适用于不同业务场景。
● 单集群模型(同城机房级容灾)
适用场景:同城机房(物理距离 < 100 公里,网络延迟 < 5 ms),业务对数据一致性要求高、对跨机房延迟敏感(如金融支付、实时交易)。
架构特点:
多个机房的组件(应用、数据库、消息队列)组成统一集群(如数据库跨机房部署主从副本,应用服务器组成跨机房集群)。
数据通过实时同步(如 Redis 哨兵模式、MySQL MGR)保持强一致,用户请求可路由到任意机房的组件。
核心优势:对应用代码侵入小(无需修改数据分片逻辑),数据一致性强(单集群内数据实时同步)。
局限性:受物理距离限制,仅适合同城场景;单集群规模有限,难以支撑超大规模业务(如日活用户过亿)。
典型案例:某银行同城两个机房部署核心交易系统,数据库采用 MySQL MGR 跨机房集群,应用服务器组成跨机房负载均衡集群,单个机房故障时,流量自动切换到另一机房,RTO<5 分钟。
● 多集群模型(同城 / 低延迟异地容灾)
适用场景:同城机房或异地低延迟机房(物理距离 < 300 公里,网络延迟 < 20ms),组件无法跨机房组成单集群(如部分老旧数据库不支持跨机房集群)。
架构特点:
每个机房部署独立集群(应用集群、数据库集群、消息队列集群),集群间通过异步 / 半同步同步数据(如机房 A 数据库主集群向机房 B 备集群同步数据)。
流量路由通过接入网关控制,同一用户请求路由到指定集群(如地域路由:华北用户路由到北京集群,华东用户路由到上海集群)。
核心优势:集群独立部署,故障隔离性强(单个集群故障不影响其他集群);可灵活扩展集群数量(如新增广州集群服务华南用户)。
局限性:数据同步存在延迟(异步同步可能导致 RPO>0),需在应用层处理数据一致性问题(如分布式事务);对应用代码侵入较大(需适配多集群数据读写逻辑)。
典型案例:某电商平台在上海、杭州部署两个独立集群,订单数据通过半同步复制从上海集群同步到杭州集群,华东用户路由到上海集群,华南用户路由到杭州集群,上海集群故障时,流量切换到杭州集群,RTO<10 分钟。
● 单元化模型(异地大规模业务容灾)
适用场景:异地大规模业务(物理距离 > 300 公里,如北京、上海、广州机房),业务需支撑超大规模用户(日活过亿),同时要求低延迟与高可用(如社交平台、短视频应用)。
架构特点:核心是解决单集群、多集群模型无法突破的“物理距离 - 数据一致性 - 延迟”矛盾,通过“单元闭环”实现异地多活。
单元划分:将系统拆分为“中心单元 + 普通单元”,中心单元仅 1 个(部署全局业务),普通单元可横向扩展(如北京中心单元,上海、广州普通单元)。
业务分类:
全局业务:强一致性需求(如用户账户、支付),仅在中心单元读写,普通单元通过同步获取只读数据。
核心业务:可分片业务(如用户动态、订单),按用户 ID 分片到普通单元,在单元内闭环读写(如用户 ID 尾号 0-3 的动态在上海单元读写)。
共享业务:被核心业务依赖的只读业务(如商品信息、配置),中心单元写入,普通单元同步只读。
数据同步:核心业务数据在普通单元间双向同步(如上海单元与广州单元同步用户数据),全局 / 共享业务从中心单元单向同步到普通单元。
核心优势:
延迟低:用户请求路由到就近单元,避免跨地域调用(如广州用户路由到广州单元,延迟 < 20ms)。
扩展性强:普通单元可按需新增(如新增成都单元服务西南用户),支撑业务无限横向扩展。
容灾能力强:单个普通单元故障仅影响该单元用户,中心单元故障时,可通过普通单元间数据同步临时接管全局业务。
局限性:架构复杂,需对业务进行深度拆分(如数据分片、业务分类);对技术组件要求高(需支持跨单元数据同步、动态路由);应用代码侵入大(需适配单元化读写逻辑)。
典型案例:某短视频平台采用单元化架构,北京中心单元部署用户账户业务,上海、广州、成都普通单元部署用户短视频、评论业务,按用户 ID 尾号分片到普通单元,单个普通单元故障时,流量切换到其他单元,RTO<5 分钟,用户无感知。
三、应用多活的实现要点
应用多活是“架构 + 管理”的解决方案,一般按应用分层架构(如接入层、应用层、中间件、数据层等)分组串联,每层组件需实现特定能力,共同支撑多活架构的稳定运行。
(1)接入层:业务流量的路由调度
接入层是应用多活的“流量大门”,负责接收用户请求并路由到正确的机房 / 单元,核心目标是实现“流量识别”与“流量分发”,保障“流量路由一致性”。
● 核心能力
机房 / 单元粒度路由:
比例分流:按预设比例将流量分配到不同机房(如北京机房承担 40% 流量,上海机房承担 60%),适用于流量均衡场景。
精准路由:提取请求中的业务标识(如用户 ID、地域编码),按规则路由到指定机房(如用户 ID 哈希后路由到对应单元),确保同一用户请求始终进入同一单元。
故障自动切流:实时检测机房健康状态(如通过 ping、HTTP 探活),当某机房故障时,自动将该机房流量切换到其他正常机房,实现 “流量切零”(故障机房流量占比降为 0)。
应用粒度路由:根据请求的应用标识(如 URL、请求头),将流量路由到对应应用实例(如 /api/order 路由到订单应用,/api/user 路由到用户应用),支持多应用共存场景。
● 技术方案
接入网关是接入层的核心组件,主流实现方案有单集群与多集群两种模式。
单集群模式:
接入网关集群对外提供一个统一接入点,流量进入网关后集群后,按照一定的路由规则将业务流量调度到相应机房内的应用。
当某机房发生故障时,可以通过修改接入网关的流量规则,从而将故障机房流量切换到其他正常机房,实现故障机房流量切零。
多集群模式:
每个接入网关集群对外提供一个统一接入点,使用 DNS 按权重解析访问到不同的网关集群,多个关集群均按照相同一致的的流量规则进行路由纠错。
当某机房发生故障时,通过修改所有网关集群的流量路由规则,将故障机房的流量切换到其他正常机房。若故障影响到了接入网关集群,则还需要调整 DNS 权重来将故障机房整体流量切零。
● 典型问题
问题 1:DNS 缓存导致切流延迟。DNS 解析结果在本地客户端有缓存(通常 10-30 分钟),修改 DNS 权重后,部分客户端仍会访问故障机房。
解决方案:采用 HTTPDNS 替代传统 DNS,客户端直接向 HTTPDNS 服务器请求解析,绕过本地缓存,切流延迟缩短至 1 分钟内。
问题 2:跨机房路由错误。网关路由规则配置错误,导致用户请求路由到错误机房,引发数据不一致。
解决方案:路由规则上线前进行灰度验证(如先路由 1% 流量测试),同时在网关层增加路由校验(如用户 ID 分片与机房匹配校验),错误路由直接返回异常。
(2)应用层:业务逻辑的多活支撑
应用层是业务逻辑的执行层,主要包括微服务与部分“轻数据依赖、重逻辑调用”的中间件,核心目标是实现“业务逻辑多活”与“故障隔离”,确保跨机房 / 单元的业务调用一致性。
● 核心能力
流量路由:
条件路由:根据服务参数(如用户 ID、订单 ID)路由到指定机房的服务实例。
优先路由:优先调用同机房的服务,减少跨机房调用延迟。
流量保护:服务提供方接收到服务请求时,根据最新的路由规则进行计算,若识别为错误流量,则拒绝处理请求,保证全局流量路由的一致性。
故障隔离:通过熔断、降级机制,当某机房的服务故障时,自动停止调用该机房服务,避免故障扩散。
● 技术方案
服务打标:服务发布到注册中心(如 Nacos、Eureka)时附加多活管理信息,如多活应用、所属地域、归属单元等。
服务同步:跨集群同步注册中心数据,实现服务跨集群发现,通过打标信息进行分组。
链路标记:将服务参数(如用户 ID、订单 ID)附加到请求上下文中(如线程变量、方法参数、框架支持的 Attachment 等)。
路由重载:重载调用端负载均衡,从跨集群服务全集中筛选符合路由要求的目标实例。
前置检查:添加服务端前处理过滤器,在业务逻辑前进行可进入判断,拦截错误路由流量。
● 典型问题
问题 1:优先路由导致负载不均衡。机房内服务实例数量、外部流量比例、服务调用放大乘数不一定呈等比关系,同机房优先可能导致服务负载不均,忙的过载,闲的浪费。
解决方案:设置流量封闭阈值,如果同机房内服务数量低于界限,则按物理距离扩充可调用的服务集合,总体上“可用性 > 稳定性 > 性能”。
(3)数据层:业务正确的核心保障
业务的准确性往往取决于数据的准确性,数据层负责数据的存储、同步与一致性保护,核心目标是实现“数据零丢失”(严谨来说,是“丢失可预期”)与“读写一致性”,避免因跨机房数据交互导致的“读写冲突”(脏读、脏写)。
● 核心能力
数据同步:
强同步:同城场景(延迟 < 10ms),采用同步或半同步复制(如 MySQL 半同步),确保数据写入主库后,至少同步到一个备库才返回成功,RPO=0。
弱同步:异地场景(延迟 > 50ms),采用异步复制(如 Canal 异步同步),平衡延迟与一致性,RPO 可控制在 100ms 内。
数据保护:
日常态保护:写数据前根据最新路由规则计算,禁止错误流量操作数据,避免在多个机房读写相同数据,产生数据冲突。
切流态保护:流量切换时,分两个阶段禁写:①规则变更阶段:路由规则推送期间,禁止所有机房写操作,避免规则不一致导致脏写;②同步延迟阶段:数据同步未追平时,禁止变更数据集写操作,避免新写入数据被旧数据覆盖。
数据切换:
单集群:节点故障自动切换(如主备 VIP 自动飘移、数据网关自动轮转)。
多集群:应用数据访问多连接策略(如读写分离、主连接置换)。
● 技术方案
SQL 解析:解析业务 SQL,在语句层面识别读写操作。
数据库驱动:重载数据库驱动组件(如 Driver/Connection/Statement),减少对上层模块(如连接池)的影响。
数据访问层:增加数据访问层或数据库网关,解耦控制逻辑与业务逻辑,实现业务代码对环境变更和策略变更无感。
数据传输服务:数据稽核和数据镜像检测,保障数据准确性;同步延迟检测,为管理面提供状态数据支持。
分布式数据库:直接采用分布式数据库(如 OceanBase、TiDB)可以简化数据管理工作,通过数据库流量亲和策略(如 PrimaryZone)控制流量路径范围。
● 典型问题
问题 1:数据同步延迟导致不一致。异地场景下,异步复制存在延迟(如 100ms),切流后目标机房可能读取到旧数据,写入的新数据可能被同步的旧数据覆盖。
解决方案:切流时等待数据同步追平(如通过 binlog 位点校验,确保目标机房数据与源机房一致),追平后再放入流量;同时在应用层增加缓存预热或主动淘汰,避免读旧数据。
问题 2:跨分片事务一致性。跨分片业务(如用户 A[分片 0-3] 向用户 B[分片 4-7] 转账)需保证事务一致性,传统两阶段提交(2PC)延迟高。
解决方案:采用最终一致性方案,如 TCC(Try-Confirm-Cancel)或 SAGA 模式,将跨分片事务拆分为本地事务,通过补偿机制确保最终一致。
四、应用多活的落地建议
(1)落地阶段划分
应用多活架构复杂,建议分三阶段落地,逐步实现业务多活:
试点阶段(1-3 个月):选择非核心业务(如用户日志、通知服务),部署同城双机房单集群多活,验证接入层、应用层的路由能力,积累运维经验。
推广阶段(3-6 个月):将核心业务(如订单、支付)迁移到多集群或单元化架构,实现异地多活,优化数据同步与一致性保护机制,确保 RTO<10 分钟,RPO<100ms。
成熟阶段(6-12 个月):实现全业务多活,常态化容灾演练(每月一次),故障自愈率达 90% 以上,RTO<5 分钟,RPO 接近 0,满足金融级高可用需求。
(2)关键成功因素
业务驱动:多活架构需与业务需求匹配,避免“为多活而多活”(如小型企业无需部署单元化架构)。
技术储备:提前储备分布式数据库、混沌工程、动态路由等核心技术,组建跨团队(业务、开发、运维)的多活专项组。
常态化演练:容灾能力需通过演练验证,避免“纸上谈兵”,建议每月模拟 1-2 次故障场景,优化切流流程。
版权声明: 本文为 InfoQ 作者【陈一之】的原创文章。
原文链接:【http://xie.infoq.cn/article/7ad7325e84a3deeee78c362a0】。文章转载请联系作者。
评论