美文网首页
LDC 单元化的异地多活和灾备

LDC 单元化的异地多活和灾备

作者: robot_test_boy | 来源:发表于2021-12-13 00:07 被阅读0次

架构师技术联盟的业务多活架构和分布式CAP实战,异地多活和异地容灾(冷备热备)的学习笔记

流量挑拨技术探秘简介

单元化后,异地多活只是多地部署而已。比如上海的两个单元为 ID 范围为 [00~19],[40~59] 的用户服务。而杭州的两个单元为 ID 为 [20~39]和[60,79]的用户服务,这样上海和杭州就是异地双活的。

支付宝对单元化的基本要求是每个单元都具备服务所有用户的能力,即——具体的那个单元服务哪些用户是可以动态配置的。所以异地双活的这些单元还充当了彼此的备份。

冷备热备已经被用的很乱了。最早冷备是指数据库在备份数据时需要关闭后进行备份(也叫离线备份),防止数据备份过程中又修改了,不需要关闭即在运行过程中进行数据备份的方式叫做热备(也叫在线备份)。

也不知道从哪一天开始,冷备在主备系统里代表了这台备用机器是关闭状态的,只有主服务器挂了之后,备服务器才会被启动。

而相同的热备变成了备服务器也是启动的,只是没有流量而已,一旦主服务器挂了之后,流量自动打到备服务器上。本文不打算用第二种理解,因为感觉有点野。

为了做到每个单元访问哪些用户变成可配置,支付宝要求单元化管理系统具备流量到单元的可配置以及单元到DB的可配置能力

其中 Spanner 是蚂蚁基于 Nginx 自研的反向代理网关,也很好理解,有些请求我们希望在反向代理层就被转发至其他IDC的Spanner而无需进入后端服务,如图箭头 2 所示。那么对于应该在本 IDC 处理的请求,就直接映射到对应的RZ 即可,如图箭头 1。进入后端服务后,理论上如果请求只是读取用户流水型数据,那么一般不会再进行路由了。

然而,对于有些场景来说,A 用户的一个请求可能关联了对 B 用户数据的访问,比如A转账给B,A 扣完钱后要调用账务系统去增加 B 的余额。这时候就涉及到再次的路由,同样有两个结果:跳转到其他 IDC(如图箭头 3)或是跳转到本 IDC 的其他 RZone(如图箭头 4)。

RZone 到 DB 数据分区的访问这是事先配置好的,上图中 RZ 和 DB 数据分区的关系为:

RZ0* --> a

RZ1* --> b

RZ2* --> c

RZ3* --> d

假设 C 用户所属的数据分区是 c,而 C 用户在杭州访问了 cashier.alipay.com(随便编的)。

①目前支付宝默认会按照地域来路由流量,具体的实现承载者是自研的 GLSB(Global  Server Load Balancing):

https://developer.alipay.com/article/1889

它会根据请求者的IP,自动将cashier.alipay.com解析为杭州 IDC 的 IP 地址(或者跳转到 IDC 所在的域名)。

大家自己搞过网站的化应该知道大部分 DNS 服务商的地址都是靠人去配置的,GLSB 属于动态配置域名的系统,网上也有比较火的类似产品,比如花生壳之类(建过私站的同学应该很熟悉)的。

②用户的请求来到了 IDC-1 的 Spanner 集群服务器上,Spanner 从内存中读取到了路由配置,知道了这个请求的主体用户 C 所属的 RZ3* 不再本 IDC,于是直接转到了 IDC-2 进行处理。

③进入 IDC-2 之后,根据流量配比规则,该请求被分配到了 RZ3B 进行处理。

④RZ3B 得到请求后对数据分区 c 进行访问。

⑤处理完毕后原路返回。

大家应该发现问题所在了,如果再来一个这样的请求,岂不是每次都要跨地域进行调用和返回体传递?

确实是存在这样的问题的,对于这种问题,支付宝架构师们决定继续把决策逻辑往用户终端推移。

比如,每个 IDC 机房都会有自己的域名(真实情况可能不是这样命名的):

IDC-1 对应 cashieridc-1.alipay.com

IDC-2 对应 cashieridc-2.alipay.com

那么请求从 IDC-1 涮过一遍返回时会将前端请求跳转到 cashieridc-2.alipay.com 去(如果是 App,只需要替换 rest 调用的接口域名),后面所有用户的行为都会在这个域名上发生,就避免了走一遍 IDC-1 带来的延时。

容灾机制

流量挑拨是灾备切换的基础和前提条件,发生灾难后的通用方法就是把陷入灾难的单元的流量重新打到正常的单元上去,这个流量切换的过程俗称切流。

支付宝 LDC 架构下的灾备有三个层次:

同机房单元间灾备、同城机房间灾备和异地机房间灾备

同机房单元间灾备:灾难发生可能性相对最高(但其实也很小)。对 LDC 来说,最小的灾难就是某个单元由于一些原因(局部插座断开、线路老化、人为操作失误)宕机了。

同城机房间灾备:灾难发生可能性相对更小。这种灾难发生的原因一般是机房电线网线被挖断,或者机房维护人员操作失误导致的。在这种情况下,就需要人工的制定流量挑拨(切流)方案了。

整个切流配置过程分两步,首先需要将陷入灾难的机房中 RZone 对应的数据分区的访问权配置进行修改。

假设我们的方案是由IDC-2机房的RZ2和RZ3分别接管 IDC-1 中的 RZ0 和 RZ1。

那么首先要做的是把数据分区a,b 对应的访问权从RZ0和RZ1收回,分配给RZ2和RZ3。

即将(如上图所示为初始映射):

RZ0* --> a

RZ1* --> b

RZ2* --> c

RZ3* --> d

变为:

RZ0* --> /

RZ1* --> /

RZ2* --> a

RZ2* --> c

RZ3* --> b

RZ3* --> d

然后再修改用户 ID 和 RZ 之间的映射配置。假设之前为:

[00-24] --> RZ0A(50%),RZOB(50%)

[25-49] --> RZ1A(50%),RZ1B(50%)

[50-74] --> RZ2A(50%),RZ2B(50%)

[75-99] --> RZ3A(50%),RZ3B(50%)

那么按照灾备方案的要求,这个映射配置将变为:

[00-24] --> RZ2A(50%),RZ2B(50%)

[25-49] --> RZ3A(50%),RZ3B(50%)

[50-74] --> RZ2A(50%),RZ2B(50%)

[75-99] --> RZ3A(50%),RZ3B(50%)

这样之后,所有流量将会被打到 IDC-2 中,期间部分已经向 IDC-1 发起请求的用户会收到失败并重试的提示。

实际情况中,整个过程并不是灾难发生后再去做的,整个切换的流程会以预案配置的形式事先准备好,推送给每个流量挑拨客户端(集成到了所有的服务和 Spanner 中)。

这里可以思考下,为何先切数据库映射,再切流量呢?这是因为如果先切流量,意味着大量注定失败的请求会被打到新的正常单元上去,从而影响系统的稳定性(数据库还没准备好)。

异地机房间灾备:这个基本上跟同城机房间灾备一致(这也是单元化的优点),不再赘述。

相关文章

网友评论

      本文标题:LDC 单元化的异地多活和灾备

      本文链接:https://www.haomeiwen.com/subject/hqjpxrtx.html