一、系统可用性

要想理解异地多活,我们需要从架构设计的原则说起。
现如今,我们开发一个软件系统,对其要求越来越高,如果你了解一些「架构设计」的要求,就知道一个好的软件架构应该遵循以下 3 个原则:

  • 高性能
  • 高可用
  • 易扩展

其中,高性能意味着系统拥有更大流量的处理能力,更低的响应延迟。例如 1 秒可处理 10W 并发请求,接口响应时间 5 ms 等等。

易扩展表示系统在迭代新功能时,能以最小的代价去扩展,系统遇到流量压力时,可以在不改动代码的前提下,去扩容系统。

而「高可用」这个概念,看起来很抽象,怎么理解它呢?通常用 2 个指标来衡量:

  • 平均故障间隔 :表示两次故障的间隔时间,也就是系统「正常运行」的平均时间,这个时间越长,说明系统稳定性越高
  • 故障恢复时间 :表示系统发生故障后「恢复的时间」,这个值越小,故障对用户的影响越小

可用性与这两者的关系:

可用性(Availability)= 平均故障间隔  / (平均故障间隔 + 故障恢复时间 ) * 100%

我们都知道,系统发生故障其实是不可避免的,尤其是规模越大的系统,发生问题的概率也越大。这些故障一般体现在 3 个方面:

  • 硬件故障:CPU、内存、磁盘、网卡、交换机、路由器
  • 软件问题:代码 Bug、版本迭代
  • 不可抗力:地震、水灾、火灾、战争

这些风险随时都有可能发生。所以,在面对故障时,我们的系统能否以「最快」的速度恢复,就成为了可用性的关键。

二、单机架构

首先来看看我们的单机架构,只有一台机器,单机部署,直接进行操作,最简单的架构模型

灾备系统 架构图 灾备技术有哪些_数据


像这样的单机架构,一旦出现数据损坏,例如电脑硬盘出现损坏(我自己的电脑就在去年出过这个问题,然后两个重要的个人项目,还有笔记直接无了,提醒大家,像代码,笔记之类的可以上传到git上,顺便熟练git的操作),误删数据等等各种原因,我们所有的数据就都丢了,怎么解决呢?

我们可以采用最简单的方式,进行冗余备份

冗余是什么意思呢?就是多余的意思,我们一开始只有一台机器上有数据,现在我们增加一台多余的机器,在那台机器上进行备份,我们可以在每天的凌晨或者不忙的时候进行数据的备份,因为备份是需要大量资源的。

灾备系统 架构图 灾备技术有哪些_地理位置_02


问题来了,这个方案有什么缺陷呢?

因为采用的是定时备份的方式,我们的数据不会是最新的,例如我们Redis中的RDB,就可以看出,会少很多数据

三、主从复制

既然定时备份不行,那么我们就进行实时备份呗,像我们的Redis中的主从复制,还有Mysql的主从复制,都接近于实时备份,一般情况下,我们的从机会拥有主机的数据,同时,还能帮忙负载读请求

就这样,我们能解决上面的几个问题

  • 数据完整性问题:实时备份解决定时备份的难题
  • 性能问题:从机能帮忙负载读请求
  • 防止数据丢失:从机作为热备,能保存数据,同时提供服务
  • 定时进行冷备:防止刚上线的时候出现脏数据,或者出现重大事故需要用于回滚

灾备系统 架构图 灾备技术有哪些_分布式_03

四、同城灾备

一般来说,我们的机器都是放在一个机房中,但是如果出现断电,火灾,以及其他不可预测的自然灾害等,我们需要对单个机房进行改造,就像我们一开始的那样,我们也可以进行冗余。

我们在同一个城市再添加一个机房,然后利用同城专线进行连接两个机房,A中的机器都是主库,然后将B中的机器都作为从库。主A 机房的数据,定时在 B 机房做实时备份,这样即使整个 A 机房遭到严重的损坏,B 机房的数据不会丢,通过备份可以把数据「恢复」回来,重启服务,将B作为A的热备,当A出现问题,挂掉了,就转为我们的B机房,我们将B机房的机器作为服务支撑,等待A的重新恢复然后上线。

无论是作为热备还是冷备,我们的B机房一般都处于备用状态,所以叫同城灾备

灾备系统 架构图 灾备技术有哪些_定时备份_04

同城双活

我们上面的方案是将我们的机房B作为热备,但是并不会一开始就对机房B进行操作,但是如果现在流量很大,我们的机房A挂了,然后机房B接入,然后B也挂了,所以,我们应该一开始就将B机房也当做可以使用,将部分流量也接入到B中,降低A的流量

灾备系统 架构图 灾备技术有哪些_分布式_05

六、两地三中心

上面的架构能解决我们的断电,火灾等问题,但是我们的两个机房还是在我们的一个城市中,如果发生像地震等灾害,我们的机房都挂了,怎么办?
既然在一个地方会同时承受灾害,那么我们不在一个地方就行了,鸡蛋不放在一个篮子了
我们将机房放在两个城市,这样一个城市出现灾害,但是另一个城市不会有影响

例如我们在北京部署A,B两个机房,在上海部署C机房,这就是我们的两地三中心,2个城市,三个机房,第三台机器作为备份放在别的地方,这个方案类似于异地多活的低阶版本

异地多活

因为跨机房跨城市之间会需要专门的路线来进行传输,效率也是有限的,会存在调用延迟,例如,我们在A机房调用了B机房的接口,然后之间会从北京到上海这么远的距离进行网络传输,延时会占据很大的开销,所以,我们需要解决这个由于网络距离过远的问题
既然A调B要经过网络传输,那么我们不进行跨机房网络传输不就行了

我们需要在自己的机房中进行数据的闭环,例如,我们在北京的用户就近访问,访问我们的北京机房,然后在北京机房完成所有操作,在上海的用户,就访问上海的机房,然后在上海机房完成所有操作。操作全部在一个机房中完成,不出现北京机房调用上海机房,形成数据闭环。常见的有根据业务类型进行分片,哈希分片,地理位置分片。

  • 业务类型分片:假设我们一共有 4 个应用,北京和上海机房都部署这些应用。但应用 1、2 只在北京机房接入流量,在上海机房只是热备。应用 3、4 只在上海机房接入流量,在北京机房是热备。
  • 哈希分片:最上层的路由层,会根据唯一业务 ID 计算「哈希」取模,然后从路由表中找到对应的机房,之后把请求转发到指定机房内。
  • 地理位置分片:例如外卖肯定是「就近」点餐,整个业务范围相关的有商家、用户、骑手,它们都是在相同的地理位置内的。感觉这个应该用的多一点,毕竟同一个区域的机器间的网络访问应该要更快

同时,每个机房都是一样的节点,不存在主从之类的关系,然后因为都是主,都需要支持读写,所以,之间的数据是不一样的,我们需要考虑机房间的数据一致性,如果进行直接网络调用,就会出现大量的延时,占用资源,同时还可能因为我们的网络问题导致数据丢包等问题。我们可以依靠数据同步中间件来做,我们的机房只需要把带同步的数据交给这个同步中间件,然后中间件完成可靠性等问题的保证,进行异步的同步数据,既不会影响系统性能,还能保证两个机房间都含有同样一份数据,例如我们的canal监听我们的数据库,然后将数据库中binlog解析然后同步给另一个机房

灾备系统 架构图 灾备技术有哪些_地理位置_06