原创:小姐姐味道,欢迎分享,转载请保留出处。
两地三中心,是有钱的公司,为保障数据安全和高可用,一个常见的需求,通常指的是 “同城双活,异地备份”。
2 1 = 3,从描述上来看,就知道它们之间是有阶级属性的。
异地备份的机房,level上自然就比同城双活的两个机房低了一个档次,否则也不会沦为备胎。辩证的看待这个问题,我们就能够自如的处理感情上脚踏多只船的问题。
1. 部署结构
为了描述方便,我们把同城的两个机房,称为A
和B
。把可怜的备份机房,称作机房C
。
同城的两个机房,距离上自然就近了一些。我们可以用图直观的表示一下这个距离差异。
所以这个备份机房,非常的没有存在感。实际上,它也非常的有自知之明,只把自己放在一个备份的场景,能够接受非常大的请求延迟和比较长的数据不一致窗口。
这么算下来,就只剩下A和B两位陪你玩了,此之为双活。
2. 奇数节点的意义
双活的意思,是两个机房要同时对外提供服务。运行在不同机房的服务,分为两种,一种是有状态的,一种是无状态的。
无状态的服务,由于自身并不存储数据,只是作为传话筒,处理上自然行云流水,没什么值得好讨论的。
难搞的是有状态的服务。即使它像鱼一样记忆只有5秒,这部分记忆依然会对整个系统提出了高标准的要求------
我们需要有个集中的地方来存储这些数据。
大家都是搞技术的,那就举例几个常见的组件。
- Zookeeper动物园,需要做集中的配置中心或者分布式协调工作
- Redis Cluster需要处理一些全局的缓存数据
- ElasticSearch进行数据存储
无数个案例告诉我们,要部署这些服务,得部署奇数个节点才行。为什么不能部署偶数个?因为有个脑残的问题,那就是脑裂。
我们拿Zookeeper来说,假如我们部署了6个节点,那么你要两个集群能够可用,需要至少4个存活才行。你要是设置成了3个,那它就会出现问题。
如下图,在6个节点的场景中,A和B机房网络产生了闪断。A机房的三个节点发现不能再连接B机房的节点,于是它们三个自己组个集群,并写入了 a = 100, b = 300两条数据;同理,B机房也组了个局,写入了a = 100, b = 600两条记录。
而且它们都写成功了。
一个集群变成了两个,并写入了不同的数据。那我到底以谁的数据为准呢?真是要了命。
这就是脑裂问题,我们不能把集群要求的最小节点设置成3,而是起码要为4。
所以你看不管是ES还是raft协议,不管是paxos和zab,都推荐部署奇数个节点,然后把最小可用集群节点设置成 (n / 2 1) --- 此所谓有一半以上节点投票才成,且有更好的容错性。
3. 如何部署奇数个节点
那这个问题该如何解决呢?
假如是同城三活,那么我们只需要在每个机房部署一个节点就可以了。但即使是双活,都是公司非常有钱才能搞得起。现在搞个三活,你大概率会赢得老板一个心虚的白眼。
当然也可以采用 2 2 1的模式。
找不到一个专用的机房部署一套集群,但找几个第三方的服务器,部署一下我们的几个服务节点倒是可以的。
听起来很美好,但实际上不会这么做。因为这批第三方的服务器,对带宽、延迟 、安全、稳定的要求,一点都不低。
还是老老实实的在两个中心玩吧,野花野草闻着香,但大概率有毒。
实际上,即使是姐妹花,A和B总是有些差异。只要我们别把A和B看的太对等,问题就好处理。
如上图,在A机房部署3个节点,在B机房部署2个节点。只要你这么部署了,在你的脑子里,A就是要B的level高一些,虽然你对外宣称它们是一样的。
就像你脚踏两只船,你和2人说都很爱ta。但一旦ta俩有冲突,你还是会毫不犹豫的选一个。
这就是考验。
我们切回上图,看一下几种情况。在这种部署情况下,当发生脑裂,B机房的2个节点是无法提供服务的,所以也不会有异常数据进入。
当B机房整个发生问题,A机房还是能够正常运行。
当A机房整个发生问题,B机房此时只有2个节点,不满足最小的3个节点。这个时候该怎么办呢?
没错,我们手动启动一个。你看节点6的边框是虚线的,也就意味着它是一个待命状态,随时待命转正,完全的接管A的工作。
代价也是有的,毕竟A才是你心中的No.1。ta离你而去,给你造成了困扰。自己的选择,就是含着泪,你也得把B给顶上去。
相信我,不过是小时段的阵痛,你很快会再次进入双活的世界。到时候你是把B当作No.1,还是继续换回A,都没有问题。
而且这选择很没意义。
比起谁的level高,你想要双活的根本原因,那就是谁都不相信。所以,就把未来交给薛定谔的猫吧
谁让你是个多情又多疑的程序员呢。