异地多活 以阿里为例

异地多活

参考链接如下:
https://blog.51cto.com/u_14153136/3270110
https://zhuanlan.zhihu.com/p/32009822
https://segmentfault.com/a/1190000024447073
https://developer.aliyun.com/article/763323

什么是异地多活?

  • 异地多活,Multi-Site High Availability
  • 分布在异地多个站点同时对外提供服务。
  • 与传统灾备最主要的区别是“多活”里所有站点都是同时在对外提供服务的,具体有以下几点不同:
    • 传统的灾备中心平时不提供服务,关键时刻无法确定切换到灾备中心是否可以切换成功。
    • 传统的灾备中心平时不提供服务,整个灾备资源会处于浪费状态,成本比较高。
    • 传统的灾备中心平时不提供服务,所以平时提供服务的数据中心还停留在单地域,当业务体量大到一定程度时,这种模式无法解决单地域资源瓶颈的问题。
  • 因为通过传统的灾备手段无法解决上述问题,阿里巴巴经过多年研究,成功在2013年的双十一实现了“丝般柔顺”的用户体验后,“异地多活”这项基础技术首次在业界亮相。

多活方案

  • 常见的多活方案有同城双活、两地三中心、三地五中心、异地多活等多种技术方案
  • 不同多活方案技术要求、建设成本、运维成本都不一样
  • 选用哪种方案要结合具体业务规模、当前基础建设能力、投入产出比等多种因素来决定

同城双活

  • 同城双活是在同城或相近区域内建立两个机房。同城双机房距离比较近,通信线路质量较好,比较容易实现数据的同步复制 ,保证高度的数据完整性和数据零丢失。
  • 同城两个机房各承担一部分流量,一般入口流量完全随机,内部RPC调用尽量通过就近路由闭环在同机房,相当于两个机房镜像部署了两个独立集群,数据仍然是单点写到主机房数据库,然后实时同步到另外一个机房。
  • 下图展示了同城双活简单部署架构,当然一般真实部署和考虑问题要远远比下图复杂。

在这里插入图片描述

  • 服务调用基本在同机房内完成闭环,数据仍然是单点写到主机房数据储存,然后实时同步复制到同城备份机房
  • 当机房A出现问题时候运维人员只需要通过GSLB或者其他方案手动更改路由方式将流量路由到B机房。
  • 同城双活可有效用于防范火灾、建筑物破坏、供电故障、计算机系统及人为破坏引起的机房灾难。

服务路由

  • zk集群:每个机房都部署一个zk集群,机房之间zk数据进行实时双向同步,每个机房都拥有所有机房zk注册数据。
  • 路由方案:条件路由 > 就近路由 > 跨机房路由,尽量避免跨机房调用。
  • 订阅方案:consumer订阅所有机房服务,provider只向该机房zk集群进行注册。

数据双活

  • MySQL:采用MHA部署方案,主从半同步方案保证数据一致性。读写分离、读就近路由到机房内数据节点、写路由到master节点所在机房。
  • Redis: Redis cluster模式主从同步,就近读、写路由主节点机房。采用原生主从同步跨机房写性能较低,也可以依靠CRDT理论构建多节点双向同步,实现机房就近读写,但是整体实现较为复杂。

同城双活方案评估

优势

  • 服务同城双活,数据同城灾备,同城不丢失数据情况下跨机房级别容灾。
  • 架构方案较为简单,核心是解决底层数据双活,由于双机房距离近,通信质量好,底层储存例如mysql可以采用同步复制,有效保证双机房数据一致性。

劣势

  • 数据库写数据存在跨机房调用,在复杂业务以及链路下频繁跨机房调用增加响应时间,影响系统性能和用户体验。
  • 保证同城市地区容灾,当服务所在的城市或者地区网络整体故障、发生不可抗拒的自然灾害时候有服务故障以及丢失数据风险。对于核心金融业务至少要有跨地区级别的灾备能力。
  • 服务规模足够大(例如单体应用超过万台机器),所有机器链接一个主数据库实例会引起连接不足问题。

两地三中心架构

  • 所谓两地三中心是指 同城双中心 + 异地灾备中心。
  • 异地灾备中心是指在异地的城市建立一个备份的灾备中心,用于双中心的数据备份,数据和服务平时都是冷的,当双中心所在城市或者地区出现异常而都无法对外提供服务的时候,异地灾备中心可以用备份数据进行业务的恢复。

在这里插入图片描述

两地三中心方案评估

优势

  • 服务同城双活,数据同城灾备,同城不丢失数据情况下跨机房级别容灾。
  • 架构方案较为简单,核心是解决底层数据双活,由于双机房距离近,通信质量好,底层储存例如mysql可以采用同步复制,有效保证双机房数据一致性。
  • 灾备中心能防范同城双中心同时出现故障时候利用备份数据进行业务的恢复。

劣势

  • 数据库写数据存在跨机房调用,在复杂业务以及链路下频繁跨机房调用增加响应时间,影响系统性能和用户体验。

  • 服务规模足够大(例如单体应用超过万台机器),所有机器链接一个主数据库实例会引起连接不足问题。

  • 出问题不敢轻易将流量切往异地数据备份中心,异地的备份数据中心是冷的,平时没有流量进入,因此出问题需要较长时间对异地灾备机房进行验证。

  • 同城双活和两地三中心建设方案建设复杂度都不高,两地三中心相比同城双活有效解决了异地数据灾备问题,但是依然不能解决同城双活存在的多处缺点,想要解决这两种架构存在的弊端就要引入更复杂的解决方案去解决这些问题。

为什么要做异地多活

  1. 服务可以扩展到多个机房
  2. 能够应对整个机房级别的故障
  3. 做异地多活,把服务分散到多个机房,自然扩展和高可用的问题就迎刃而解了

“多活”和“双活”有什么区别?

  • 单从字面上看,“多活”和“双活”的区别仅是同时提供服务的站点数量的区别。一个是“多个”站点同时提供服务,一个是“两个”站点同时提供服务。

  • 即使都是“双活”,也会因为前面加了“同城”还是“异地”而有着本质的区别。

  • 如果是“异地双活”,就是和“异地多活”仅存在站点数量上的差别。

  • 如果是同城双活,在阿里内部,采用的是不同的技术。阿里的同城双活,整个模式应用层是双活的,两边的业务都有,用户访问过去都会处理请求,一旦进入某个数据中心,流量交付优先在本数据中心封装。

  • 存储层都是主备或者本身的高可用模式的,主备模式即主在A机房,备在B机房,不会同时用,严格意义上来讲,这是伪双活,因为数据不是真正意义的双活。但即使是这样的双活,阿里巴巴内部也是经历了很长一段时间的摸索才实现,双活其实也是一样的,如果真正做到就意味着同城任何一个机房出问题都要可以高效可靠地切换到另外一个机房,如果没有经过很多次真正切换的话,没有人敢说是一定能成功的。这里不只包含数据库主备的问题,还涉及到应用的业务依赖梳理、众多中间件层面的服务路由、调用和集群冗余的问题。

  • 一句话总结,“异地双活”和“异地多活”仅是数据中心数量的差别,但“同城双活”则是完全不同的技术。采用哪一种,完全取决自己的多个数据分布在同城还是异地,以及以后的业务扩展方向问题。

在这里插入图片描述

多活的理解

  • 异地多活的方案会限制机房间的相互调用,需要定义清晰的服务边界,减少相互依赖,让每个机房都成为独立的单元,不依赖于其他机房

3.1 实时异地多活

  • 异地多活本质上是通过异地的数据冗余,来保证在极端异常的情况下业务也能够正常提供给用户,因此数据同步是异地多活设计方案的核心。
  • 由于目前的技术还无法突破数据传输与物理距离解耦合,也就是说两个异地数据中心之间一定存在一定程度的延时,如果业务对实时性要求极高,那就无法实现异地多活。

3.2 所有用户异地多活

  • 同样是由于物理距离造成的数据传输的延迟,数据只能做到最终一致
  • 在一些极端情况下,部分用户的数据无法及时同步到新切换到的中心,这时,这部分用户的业务会受到一定程度的影响。

3.3 所有业务异地多活

  • 异地多活效果看起来很诱人,但如果不假思索贪大求全地要求所有业务都实现异地多活的话,很可能什么也做不成。
  • 原因是异地多活是有成本的,根据业务类型有不太一样的开发和运维成本,但如果全做加之对业务梳理不到位,会造成整个工期不可控,即使完成,上线后的效果也需多重验证。
  • 阿里第一次做异地多活也只是选取了与“买家”下订单相关的电商业务做的多活,然后根据业务需求,逐渐有新业务改造上线,到了今天的规模。

3.4 通用的异地多活

  • 异地多活的实现根据业务类型的不同也有一定程度的差异,为了让业务尽量少的做改动,尽可能把这种能力都封装在中间件和基础工具中,但即便如此,也无法保证这些能覆盖所有的业务类型。
  • 遇到特殊的业务类型或者用户自己实现的基础组件,仍然需要根据具体的业务特点制定新的多活方案。

异地多活的适用场景

  • 异地多活本质上就是通过自上而下的全域流量隔离来解决数据同步延时无法突破物理限制的问题,但异地多活也不是银弹,且不同的场景来做异地多活的成本也不一样,不一定适用于所有场景。
  • 下面把用户的业务按数据维度分成三种类型来看异地多活的适用场景:

4.1 读多写少型业务

  • 业务应用场景:典型的业务场景就是资讯、导购类的服务,比如商品浏览、新闻资讯...
  • 数据特点:典型的数据特点就是读多写少,用户以浏览为主,核心业务场景只读,单元里部署的都是只读业务
  • 多活接入成本:接入成本低,只需要用户在请求里标记上分流的标识即可

4.2 流水单据型业务

  • 业务应用场景:典型的业务场景就是电商交易、帐单流水类服务,比如用户的订单、用户的通话记录...
  • 数据特点:典型的数据特点就是数据可按照一定的维度进行分片且可以接受最终一致
  • 多活接入成本:接入成本略高,用户需要梳理业务,理出单元内部署的核心业务及其数据,对于单元依赖且无法拆分的业务采用读写分离,然后按照多活接入规范重点对服务层及数据层进行相应改造即可

4.3 状态依赖型业务

  • 业务应用场景:典型的业务场景就是银行账务,比如A、B在某银行均有帐户,A、B数据分片位于不同的数据中心,A和B之间会有转账行为
  • 数据特点:典型的数据特点就是数据有状态依赖且无法最终一致,数据还存在跨数据中心的交互
  • 多活接入成本:接入成本高

异地多活的设计原则

  • 选取分区维度:选择一个数据维度来做数据切片,进而实现业务可以分开部署在不同的数据中心
  • 确定改造范围:选择与上次选取的数据维度相关的业务范围来做多活
  • 单元封闭:尽量让调用发生在本单元,尽量避免跨数据中心的调用,一方面为了用户体验,本地调用RT更短,另一方面为了稳定性,防止一个数据中心出了问题,其它数据中心受影响
  • 无法接受最终一致的数据要进行单点写:对于一些实时性要求极高,无法接受最终一致的数据只能进行单点写

异地多活的价值

  • 虽然最初创造异地多活是为了解决容量和容灾的问题,但异地多活发展到今天其价值已远不止这些了,更大的价值是为阿里新技术演进提供试验田,甚至可以驱动商业上的一些玩法。

6.1 解决了容灾的问题,提升了业务的连续性

  • 现实运行过程中,容灾可不只是地震、挖光纤这些低概率事件,同样还有人为原因等高概率的事件,
  • 这些通过异地多活均可以解决。以下罗列一些常见的场景:
    • 人为操作失误:常见的有配置错误、应用发布失败等等
    • 硬件故障:常见的有网络设备出故障,导致机房或集群内多台服务器受影响
    • 网络攻击:DDoS等网络攻击
    • 断网/断电:支付宝光缆被挖断
    • 自然灾害:青云雷击导致机房电力故障
  • 有了异地多活,以上这些场景出现时,秉承“先恢复,再定位”的原则,可以有效提升业务的连续性。
  • 某互联网公司通过自己的实践验证取得了非常不错的成绩,可做到让“业务恢复时间”和“故障恢复时间”解耦合。

6.2 解决了容量异地扩展的问题

  • 有了异地多活,当机房或者地域容量遇到限制的时候,可以在其它机房或者其它地域快速扩建业务单元,实现快速水平扩容的目的。

在这里插入图片描述

6.3 为新技术演进提供了试验田

  • 异地多活本质上是提供了自上而下的一种流量隔离能力
  • 基于这种能力,我们完全可以做到单元之间的隔离,进而完成一个技术上需要的场景:
    • 基础设施的升级
    • 大的技术架构升级
    • 新技术验证
  • 阿里巴巴每年进行大促的技术大步演进但又风险可控,完全就是基于这种能力来实现的,每年有多个重大的技术演进,演进过程中难免遇到问题,但却从未造成大的影响。

6.4 驱动商业上产品创新玩法

  • 同样基于这种流量隔离能力,商业上也可以产生一些新的玩法:
    • 把VIP和普通用户分开到不同的集群
    • 把真实用户和爬虫分开
    • 新旧机器分成不同的物理集群,做流量隔离,进而做分级别的服务

异地多活(MSHA)产品介绍

7.1 产品形态

在这里插入图片描述

  • 异地多活是一个架构属性比较重的产品,其整个产品由管控+组件组成,同时需要和其它产品结合来完成整个异地多活。
  • 一个完整的异地多活应该包括如下组成部分:

A. 控制台

控制台提供多活配置及运维闭环的功能:

  • 接入层、应用层、数据层的各层接入多活的初始化操作和日常运维。
  • 发生灾难场景的切流操作。
  • 多活场景下的数据监控。
  • 多活切分规则的展示及查看。

B. 接入层

  • 目前这层主要是一个基于Tengine的多活组件,我们称之为MSFE。
  • MSFE需要多单元部署,它能承接所有的单元前端流量,并按照路由规则路由到正确单元的后端应用。
  • 多活控制台提供MSFE集群新建、扩容、缩容等常规运维能力。

C. 应用层

应用层主要包括基于EDAS的RPC服务组件和基于MQ的消息队列组件:

  • EDAS:EDAS的新增多活参数及处理逻辑支撑多活RPC能力,接入时业务需声明RPC-Provider的多活属性及升级EDAS容器版本。
  • CSB:通过级联CSB组件实现单元间的RPC服务互通,并在MSHA管控台进行发布操作。
  • ONS:基于ONS的同步能力和多活处理逻辑支持多活MQ能力,接入时需要在多活管控开启Producer和Consumer的单元属性及同步链路配置。

D. 数据层

目前这层主要是包括一个客户端和一个基于DRDS的多活组件,两者共同配合完成对多活数据层的管控:

  • 多活数据Driver:这是一个基于JDBC标准Driver进行二次封装的Driver,主要是用于传递一些标准的元信息给DRDS,同时封装了一些本地处理的多活逻辑。
  • DRDS多活组件:该组件需要安装在DRDS的Server端,主要是与多活的Drvier共同配合完成异地多活的逻辑处理。
    除了上述多活数据层的组件外,要想完成异地多活,还需要依赖数据同步相关的云产品:
  • DTS:基于DTS的单/双向同步能力,与多活管控共同配合完成异地多活的数据同步控制逻辑处理。

7.2 产品特点

A. 一站式多活管控

一站式管控主要体现在下述两个方面:

  • 横向从单元上线,到单元日常(监控、运维、切流),再到单元下线的全生命周期管理。
  • 纵向从单元流量入口,到服务化调用,异步化消息,再到数据入库的全方位管控。

B. 单元化类型自由扩展

  • 单元化类型routeType,描述的是业务类型。以电商场景为例,有买家业务、商家业务等。淘宝的交易单元化是以买家业务做的单元化,分流规则是买家id,也就是说买家的流量能分流到各个单元,而商家却没有多活。
  • 单元化类型自由扩展,能同时支持买家与商家业务的多活,赋能用户,使用户在业务扩展上拥有更大的灵活性。

C. 运维全自动化

  • 运维全自动化,主要体现在接入层、服务层、数据层的变更操作自动化以及接入层集群运维的全自动化。
  • 在接入层集群运维上,主要包含创建集群、扩缩容服务器、扩缩容SLB等,提供一键式运维变更方案,完全无需登录服务器。

D. 流量调度高可用

  • 由于流量分发路由规则在各个机器上,因此其会受如下因素影响:

    • 网络分发开销。
    • 配置中心性能。
    • 多个有序规则下发,乱序会导致流量执行逻辑错乱。
  • MSHA与上述影响点解耦:

    • 仅依赖ntp进行实际规则执行,弱化了网络和配置中心的时效性依赖,同时存在对ntp各机器不一致的容错时间,保证在切流期间,切流用户数据强一致的前提下规则执行的最终一致。
    • 多个有序规则合并为一个规则,去除对有序的依赖。
    • 当ntp灾难不可用时,启用容灾及时规则下发状态,即不依赖ntp,此时依赖配置中心下发后,禁写保切流用户强一致,而后生效。

服务案例

  • 在阿里云异地多活的服务项目中,较为典型的有饿了么与国家某部委的专有云项目。
  • 其中饿了么的业务场景、架构与阿里均有较大差异,在阿里的支持下用三个月走完阿里三年的多活改造之路,服务可拓展至多个机房,并且能够应对整个机房级别的故障。
  • 国家某部委的专有云平台自上线运行以来注册用户过亿,平日在线用户数超千万,日均交易量过千万,业务系统稳定性至关重要。
  • 2019年客户在广东、北京两个中心分别搭建混合云平台,整体解决方案实现两个中心联机业务“一写双读”,共同对外提供服务,大数据离线业务采用“异地容灾”技术进行业务连续性支撑,整个解决方案借助大量阿里云先进的技术及产品,为项目提供了业务双活和大数据容灾两个重要的容灾能力。

饿了么异地多活的实践

在这里插入图片描述

  • 整个下单到配送完成,有严格的时间要求,必须在短短的几十分钟内完成

  • 服务和地理位置强相关,并且实时性要求高,服务的地域性和实时性是我们的核心特性,多活设计最重要的是满足这两个特性。

  • 活架构通过遵循以下几条基本原则,来满足这两个核心特性:

在这里插入图片描述

  1. 业务内聚
    • 单个订单的旅单过程,要在一个机房中完成,不允许跨机房调用。
    • 这个原则是为了保证实时性,旅单过程中不依赖另外一个机房的服务,才能保证没有延迟。
    • 我们称每个机房为一个 ezone,一个 ezone 包含了饿了么需要的各种服务。
    • 一笔业务能够内聚在一个 ezone 中,那么一个定单涉及的用户,商家,骑手,都会在相同的机房,这样订单在各个角色之间流转速度最快,不会因为各种异常情况导致延时。恰好我们的业务是地域化的,通过合理的地域划分,也能够实现业务内聚。
  2. 可用性优先
    • 当发生故障切换机房时,优先保证系统可用,首先让用户可以下单吃饭,容忍有限时间段内的数据不一致,在事后修复。
    • 每个 ezone 都会有全量的业务数据,当一个 ezone 失效后,其他的 ezone 可以接管用户。用户在一个ezone的下单数据,会实时的复制到其他ezone。
  3. 保证数据正确
    • 在确保可用的情况下,需要对数据做保护以避免错误,在切换和故障时,如果发现某些订单的状态在两个机房不一致,会锁定该笔订单,阻止对它进行更改,保证数据的正确。
  4. 业务可感
    • 因为基础设施还没有强大到可以抹去跨机房的差异,需要让业务感知多活逻辑,业务代码要做一些改造
    • 需要业务代码能够识别出业务数据的归属,只处理本 ezone 的数据,过滤掉无关的数据。
    • 完善业务状态机,能够在数据出现不一致的时候,通过状态机发现和纠正。

在这里插入图片描述

服务划分(Sharding)

  • 为了实现业务内聚,我们首先要选择一个划分方法(Sharding Key),对服务进行分区,让用户,商户,骑手能够正确的内聚到同一个 ezone 中。分区方案是整个多活的基础,它决定了之后的所有逻辑。

  • 根据饿了么的业务特点,我们自然的选择地理位置作为划分业务的单元,把地理位置上接近的用户,商户,骑手划分到同一个ezone,这样一个订单的履单流程就会在一个机房完成,能够保证最小的延时,在某个机房出现问题的时候,也可以按照地理位置把用户,商户,骑手打包迁移到别的机房即可。

  • 最终选择的方案如下图,自定义地理划分围栏,用围栏把全国分为多个 shard,围栏的边界尽量按照行政省界,必要的时候做一些调整,避免围栏穿过市区。一个ezone可以包含多个 shard,某个 ezone 的 shard ,可以随时切换到另外一个 ezone ,灵活的调度资源和failover。

在这里插入图片描述

  • 这样的划分方案,基本解决了垮城市下单的问题,线上没有观察到有跨 ezone 下单的情况。围栏的划分是灵活的,可以随着以后业务的拓展进行修改,因为每个机房都是全量数据,所以调整围栏不会导致问题。

  • .如果两个城市是接壤的,会出现商家和用户处于不同 ezone 的情况,岂不是破坏了内聚性原则?

    • 这种情况确实会出现,为了尽量避免,我们在划分shard的时候没有简单的用城市名称,而是用了复杂的地理围栏实现,地理围栏主体按照省界划分,再加上局部微调,我们最大限度的避免了跨ezone下单的情况。但如果真的出现了,用户下单也不受影响,最多只是状态有1s左右的延迟。
  • 用户是会动的,如果用户从北京到了上海,那么划分规则应该怎么应对?

    • 用户在北京下单,数据落在北京shard,到上海下单,数据则落在上海的 shard,借助于底层的数据同步工具,用户无论在什么地方,都能看到自己的数据,但是有1s左右的延时,对于大部分的业务场景,这个延迟是可以承受的。当然也有些业务场景不能接受这 1s 的延时,我们也提供了另外的方案来应对,参考下文介绍Globa Zone的章节。
  • 为什么不简单点,按照用户的ID来切分?

    • 阿里是按照用户ID的取模来划分单元的,比较简洁。我们如果也用ID做切分,同一地方的用户,商户,骑手可能被划分到不同 ezone,就会出现比较多的跨机房调用,这样就更可能出现延迟,难以保证实时性。所以,我们本地配送的业务模式,决定了需要用地理位置来划分服务。

流量路由:

  • 基于地理位置划分规则,我们开发了统一的流量路由层(API Router),这一层负责对客户端过来的 API 调用进行路由,把流量导向到正确的 ezone。
  • API Router 部署在多个公有云机房中,用户就近接入到公有云的API Router,还可以提升接入质量。

在这里插入图片描述

  • 前端 APP 做了改造,为每个请求都带上了分流标签,API Router 会检查流量上自带的分流标签,把分流标签转换为对应的 Shard ID,再查询 Shard ID 对应的 eZone,最终决定把流量路由到哪个 ezone。

  • 最基础的分流标签是地理位置,有了地理位置,AR 就能计算出正确的 shard 归属。但业务是很复杂的,并不是所有的调用都能直接关联到某个地理位置上,我们使用了一种分层的路由方案,核心的路由逻辑是地理位置,但是也支持其他的一些 High Level Sharding Key,这些 Sharding Key 由 APIRouter 转换为核心的 Sharding Key,具体如下图。这样既减少了业务的改造工作量,也可以扩展出更多的分区方法。

在这里插入图片描述

  • 除了入口处的路由,还开发了 SOA Proxy,用于路由SOA调用的,和API Router基于相同的路由规则。APIRouter 和 SOAProxy 构成了流量的路由通道,让我们可以灵活的控制各种调用在多活环境下的走向。

数据复制:

  • 为了实现可用优先原则,所有机房都会有全量数据,这样用户可以随时切换到其他机房,全量数据就需要对数据进行实时复制,我们开发了相应的中间件,对 mysql,zookeeper ,消息队列和 redis 的数据进行复制。

在这里插入图片描述

  • Mysql 数据复制工具 DRC:

    • Mysql 的数据量最大,每个机房产生的数据,都通过 DRC 复制到其他 ezone,每个ezone的主键取值空间是ezoneid + 固定步长,所以产生的 id 各不相同,数据复制到一起后不会发生主键冲突。
    • 按照分区规则,正常情况下,每个 ezone 只会写入自己的数据,但万一出现异常,2个 ezone 同时更新了同一笔数据,就会产生冲突。
    • DRC 支持基于时间戳的冲突解决方案,当一笔数据在两个机房同时被修改时,最后修改的数据会被保留,老的数据会被覆盖。
  • ZooKeeper 复制:

    • 有些全局的配置信息,需要在所有机房都完全一致,我们开发了 zookeeper 复制工具,用于在多个机房中同步 ZK 信息。
  • 消息队列和Redis复制:

    • MQ,Redis 的复制与 ZK 复制类似,也开发了 相应的复制工具。
  • 强一致保证:

    • 对于个别一致性要求很高的应用,我们提供了一种强一致的方案(Global Zone),Globa Zone是一种跨机房的读写分离机制,所有的写操作被定向到一个 Master 机房进行,以保证一致性,读操作可以在每个机房的 Slave库执行,也可以 bind 到 Master 机房进行,这一切都基于我们的数据库访问层(DAL)完成,业务基本无感知。

在这里插入图片描述

切换过程和各种异常保护:

  • 避免数据错误非常重要,在网络断开,或者是切换过程中,特别容易产生错误数据。比如由于复制延时,订单状态不一致,用户有可能会重复支付。为了避免我们采取了一些保护措施,避免在切换时发生错误。

    • 在网络中断时,如果不是必要,不做切换,因为任意单个机房能够提供完整服务。
    • 如果需要切换,对锁定切换过程中的订单,直到切换完成,数据复制正常,才开放锁定。这个过程也通过 DAL 来实现
    • 对于标记为其他机房的写入数据,DAL 会进行保护,拒绝写入。
    • DRC 会检查并报告错误的写入操作,方便检查隐藏问题。
  • 通过以上4条的保护,我们保证了数据的正确性,频繁的切换也不会出现异常的业务数据。

多个机房的Cache刷新:

  • 数据的变更信息,通过 DRC 广播到多个机房,实现缓存的刷新,保证各个机房的缓存一致性。

业务改造:

  • 业务可感知是一条基本原则,通过中间件提供的服务,多活逻辑会暴露给业务方,例如:当前服务所属的 ezone,路由策略,数据的归属 shard 等,基于这些信息,业务可以执行很多的逻辑。包括:
    • 后台任务可以过滤掉非本 ezone 的数据。
    • 可以在发生切换时,执行特定的逻辑,触发特定动作。
    • 业务需要准备一些数据修复逻辑,在万一发生不一致时,手工或者自动纠正数据。

APIRouter : 路由分发服务

  • API Router是一个HTTP反向代理和负载均衡器,部署在公有云中作为HTTP API流量的入口,它能识别出流量的归属 shard ,并根据 shard 将流量转发到对应的 ezone。
  • API Router 支持多种路由键,可以是地理位置,也可以是商户ID,订单ID等等,最终由 API Router 映射为统一的 Sharding ID。

Global Zone Service:全局状态协调器

  • GZS 维护着整个多活的路由表,其他所有的服务都从 GZS 订阅路由信息。
  • 切换机房的操作也在 GZS 控制台中完成。
  • 路由表包括:地理围栏信息,shard 到 ezone 的归属信息,商铺ID/订单ID 等路由逻辑层到 shard id 的映射关系等。
  • GZS 通过在 SDK 端建立 Cache,来保证shard 逻辑能够最快速度执行,基本不需要和 GZS 交互,同时也有实时推送机制,确保在数据变更后能够快速通知到其他的服务。

SOA Proxy:内部网关

  • SOA Proxy 实现了对 SOA 调用的路由,执行和 API Router 相似的逻辑,但只用在机房之间进行通信的场景。
  • 业务使用 SOA Proxy 需要对代码做一些修改,把路由信息加入到调用的上下文中。

Data Replication Center:数据复制

  • DRC 负责 Mysql 数据的实时双向复制,保证跨机房延时在 1s 以内。
  • 提供了基于时间的冲突解决方案,确保各个机房的数据一致。
  • DRC 除了复制数据,还对外提供了数据变更的通知,让业务能够感知到其他机房的数据变化,做相应的处理,例如清除Cache等。
  • 除了DRC,我们还有 ZK复制工具,RMQ 复制工具,Redis复制工具,基本每个数据层次,都有对应的复制方案。

Data Access Layer:数据访问

  • 数据访问层支撑了 Globa Zone 的逻辑,还提供了最后一道保护,拒绝路由错误的数据写入,是多活最底层的支撑。
posted @ 2022-07-17 20:11  Jamgun  阅读(1230)  评论(0编辑  收藏  举报