# 集群的原理
一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同 cluster.name
配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。
当一个节点被选举成为 主 节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。我们的示例集群就只有一个节点,所以它同时也成为了主节点。
作为用户,我们可以将请求发送到 集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。
# 选举原理 Bully 算法
Elasticsearch 采用了 master-slave 模式, ES 会在集群中选取一个节点成为主节点,只有 Master 节点有资格维护全局的集群状态,在有节点加入或者退出集群的时候,它会重新分配分片,并将集群最新状态发送给集群中其它节点,主节点会以周期性 ping 的方式以验证其它节点是否存活。Elasticsearch 的选举算法基于 Bully 选举算法,简单的说,在 bully 算法中,每个节点都有一个编号,只有编号最大的存活节点才能成为 master 节点。1. 选举时间点
选举时间点
- 某个新节点加入了集群或者某个节点从宕机中恢复
- 集群中的某个节点检测到 leader 崩溃
选举流程
- 节点 node 向所有比自己大的节点发送选举消息 (选举为 election 消息)
- 如果节点 node 得不到任何回复 (回复为 alive 消息),那么节点 node 成为 master,并向所有的其它节点宣布自己是 master (宣布为 Victory 消息)
- 如果 node 得到了任何回复,node 节点就一定不是 master,同时等待 Victory 消息,如果等待 Victory 超时那么重新发起选举
Elasticsearch 编号比较
Elasticsearch 编号比较的判断依据有两个,首先是 ClusterState 版本号的比较,版本号越大优先级越高,然后是节点 id 的比较,id 越小优先级越高。ClusterState 是 Master 向集群中各个节点发送的集群状态,这个状态有一个版本号码,如果集群状态发生了变化,比如集群新增了节点成员或者有节点成员退出了,那么这个版本号就会加一,比对这个版本号的目的是让拥有最新状态的节点成为 Master 的优先级最高。
# Bully 算法的缺陷
1 Master 假死
Master 节点承担的职责负载过重的情况下,可能无法即时对组内成员作出响应,这种便是假死。如果上图中的 P6 节点假死,于是 P5 节点成为了 Master 节点,但是在 P6 节点负载减轻之后,P6 节点又对组内成员作出了响应,P6 节点又会成为 Master 节点,如此反复,整个集群状态就会非常不可靠。
Elasticsearch 是如何解决这个问题的呢?在 Bully 算法中,Master 节点 P6 因为负载重,来不及对 P3 节点作出响应,所以 P3 节点通知 P4,P5 节点进行选举。在 Elasticsearch 中,P3 节点发现 Master P6 对自己长时间不作出响应,P3 节点会请求其它节点判断 P6 节点是否存活,如果有 1/2 以上节点都认定 P6 存活,那么 P3 就会放弃发起选举
2 脑裂问题
脑裂问题指的是一个集群中出现了两个及以上的 Master 节点。
比如上图中集群因为网络原因分成了两个部分,一个部分称为 partition1 包含 P3,P5,P6 节点,另一部分称为 partition2 包含 P2,P1,P4 节点,这两个 partition 因为网络原因比如路由器短时故障造成不能相互通信的问题。
脑裂问题解决方案 : Quorum 算法
脑裂问题是所有集群选举算法都要面对的一个问题,Elasticsearch 集群机制采用了最小参与节点的方案解决的。假设 elasticsearch 集群中有资格投票的实例个数是 n,节点想要成为 master 必须要得到 n/2 +1 票数。上述任何一个 master 节点所在的分区集群的候选节点数目都小于 n/2 +1,更不可能得到 n/2 +1 个选票,所以整个 Elasticsearch 集群处于瘫痪状态
我们也可以强制指定 elasticsearch 节点在有 M 个候选节点的情况下能选举出一个主节点,但是如果配置数小于上文提到的 n/2 +1 那么会出现脑裂的情况,M 的配置参数如下
discovery.zen.minimum_master_nodes |
如果产生了脑裂情况,为了避免脑裂的 Master 生成错误数据对整个集群产生影响。Master 更新集群状态时还作出了如下防护,Master 有两种指令,一种是 send 指令,另一种是 commit 指令,Master 将最新集群状态推送给其它节点的时候 (这是 send 指令),Master 节点进入等待响应状态,其它节点并不会立刻应用该集群状态,而是首先会响应 Master 节点表示它已经收到集群状态更新,同时等待 Master 节点的 commit 指令。Master 节点如果在 discovery.zen.commit_timeout
配置时间内都没有收到 discovery.zen.minimum_master_nodes
个数的节点响应,那么 Master 节点就不会向其它节点发送 commit 指令。如果 Master 收到了足够数量的响应,那么 Master 会向集群发出提交状态的指令,此时其它节点应用集群最新状态,Master 节点再次等待所有节点响应,等待时间为 discovery.zen.publish_timeout
,如果任何一个节点没有发出提交响应,Master 再次更新整个集群状态更新。
3 Master 降级
Master 主动降级发生在两种情况。
第一种是 master 发现自己能连接到的其它节点数目小于 n/2 + 1,那么 master 自动降级为 candidate。
第二种是 Master 在 ping 其它节点时候,如果发现了其它 master,那么当前的 master 会比较 cluster_state 的 version,如果当前 master 的 version 小,那么主动降级为 candidate 并主动加入另外一个 master 节点
4 网络负载问题
集群中每个节点成员都会维护和其它所有成员的交互,整个集群维护的网络连接的总数是 n*(n-1),如果集群中节点的数目非常的多,那么网络连接数目也会非常的多,网络负载会比较大,但是好在 elasticsearch 节点数目往往比较少,所以这个缺陷对 elasticsearch 集群来说不会产生什么影响。