今天主要讲一下跟分布式系统有关的几个名词。
羊群效应
什么是羊群效应呢?
有人曾做过一个实验:
在一群羊面前设置了一个栅栏,领头的羊纵身一跃跳过栅栏,后面的羊也跟着跳过去。
接下来的一幕就有趣了,工作人员将栅栏移走,后面的羊走到这里时,仍像前面的羊一样跳了一下,就好像栅栏还存在一样。
这就是“羊群效应”。
“羊群效应”可以理解为一种从众心理,跟风、随大流,别人干什么,我也干什么。
比如基于Zookeeper来实现分布式锁,常用的实现方式是:
所有的client去create一个/lock znode,率先创建好znode的client获取到锁。其他client发现/lock znode已经存在,则watch该znode是否被删除。当该znode被删除的时候,client收到通知并试图create /lock,重新进行锁的竞争。
这里面的/lock znode就相当于羊群效应里面的头羊,client就是羊群,羊群中的所有羊都监视着头羊的一举一动。
如果有1000个客户端watch一个znode的exists调用,当这个节点被创建的时候,将会有1000个通知被发送。由于1个被watch的znode变化,导致大量的通知需要被发送,将会导致在这个通知期间的其他操作提交的延迟,即触发了羊群效应。
如何解决上述问题呢?
每个client去创建一个顺序的znode /lock/lock-xxx,ZooKeeper会自动添加顺序号/lock/lock-xxx,我们可以通过/lock getChildren去拿到最小的顺序号。如果client不是最小的序列号,就再比自己小一点的znode上添加watch。
通过这种方式,每个节点只watch单个变化,从而避免了羊群效应。
脑裂
脑裂(split-brain)就是“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”,我们都知道,如果一个人有多个大脑,并且相互独立的话,那么会导致人体“手舞足蹈”,“不听使唤”。
脑裂通常会出现在集群环境中,比如ElasticSearch、Zookeeper集群,而这些集群环境有一个统一的特点,就是它们有一个大脑,比如ElasticSearch集群中有Master节点,Zookeeper集群中有Leader节点。
下面以Zookeeper集群为例来讲解脑裂现象。
对于一个集群,想要提高这个集群的可用性,通常会采用多机房部署,比如现在有一个由6台zkServer所组成的一个集群,部署在了两个机房:
正常情况下,此集群只会有一个Leader,那么如果机房之间的网络断了之后,两个机房内的zkServer还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个Leader。
这就相当于原本一个集群,被分成了两个集群,出现了两个“大脑”,这就是脑裂。
对于这种情况,我们也可以看出来,原本应该是统一的一个集群对外提供服务的,现在变成了两个集群同时对外提供服务,如果过了一会,断了的网络突然联通了,那么此时就会出现问题了,两个集群刚刚都对外提供服务了,数据该怎么合并,数据冲突怎么解决等等问题。
为了解决脑裂,Zookeeper在进行Leader选举时,引入了过半机制。
如果现在集群中有5台zkServer,那么half=5/2=2,那么也就是说,领导者选举的过程中至少要有三台zkServer投了同一个zkServer,才会符合过半机制,才能选出来一个Leader。
那么有一个问题我们想一下,选举的过程中为什么一定要有一个过半机制验证?
因为这样不需要等待所有zkServer都投了同一个zkServer就可以选举出来一个Leader了,这样比较快,所以叫快速领导者选举算法。
拜占庭问题
在很久很久以前,拜占庭是东罗马帝国的首都。那个时候罗马帝国国土辽阔,为了防御目的,因此每个军队都分隔很远,将军与将军之间只能靠信使传递消息。
在打仗的时候,拜占庭军队内所有将军必需达成一致的共识,才能更好地赢得胜利。但是,在军队内有可能存有叛徒,扰乱将军们的决定。
这时候,在已知有成员不可靠的情况下,其余忠诚的将军需要在不受叛徒或间谍的影响下达成一致的协议。
莱斯利·兰伯特( Leslie Lamport )通过这个比喻,表达了计算机网络中所存在的一致性问题。这个问题被称为拜占庭问题。
分布式系统首要解决的是如何保持节点之间数据的一致性, 或者说各节点如何达成共识?
根据拜占庭问题的定义,可以将现有的共识算法分为:
- 非拜占庭问题共识解决方案: Raft , Paxos;
- 拜占庭问题共识解决方案: PBFT(所谓拜占庭算法) , DBFT(授权拜占庭容错算法), POW(比特币中算法)。