ES集群启动流程

ES集群是主从模式的,其启动的过程主要包括主Master选举,集群元数据选举,索引主分片选取和副本分片选取。其主要过程如下:

1 Master选举

集群启动的第一件事就是选取Master节点,选取的时间点为当集群启动的备选master节点过半时,开始集群的选举,这一点和zookeeper是类似的。例如集群有7个节点,有5个节点设置了node.master:true 当这5个备选节点中有超过discovery.zen.minimum_master_nodes(避免脑裂该值应该是半数已上)个节点启动时,就可以开始选举主节点。当主节点得票超过半数后,当前节点被选择为主节点。

2 元数据选举(恢复)

主节点确定之后,主节点会向所有的节点询问元数据信息,当收到的元数据过半之后,对比元数据的版本号将版本号最大的元数据作为最新的元数据,并将元数据广播到集群中。这里的过半指的是候选元数据节点。因为只有这两个节点可以持久化元数据到磁盘。这里涉及到三个参数:

  • gateway.excepted_nodes:预期节点数,当加入集群的节点数大于该值时即可开始恢复元数据。
  • gateway.recovery_after_time:在到达预计节点数之前等待的最长时间,如果在该时间段内,集群还未达到预期节点数,则元数据也开始恢复。默认值为5min
  • gateway.recovery_after_nodes:只要加入集群的节点数量达到当前配置数量则开始恢复元数据。

元数据类型

  • MetaData(集群级),主要存储clusterID,settings,templates;
  • IndexMetaData(索引级),主要存储numberOfShards,mappings;
  • ShardStateMetaData(分片级),主要存储version,indexUUID,primary。
    集群在持久化时不会保存哪个分片位于哪个节点上,这些信息是在在集群元数据和索引元数据恢复完成后,发布一个异步的任务来确定去完成构建路由表的过程。

3 选取分片

在元数据选举完成后,开始数据分片的选择。ES为了保证数据的高可用,设计了分片及副本分片,作为准备模式。

3.1 选取主分片

对于主分片,应选取集群中的最新分片。在ES5.X之前,Master会询问其他节点关于分片的信息,这种情况下,Master节点在短时间内会接收到节点数*分片数的信息,然后选取每个分片最新的信息,这样在短时间内,传输的数据量较大,在ES5.X之后,ES为每个分片设置了一个shardUUID,并在元数据中保存着哪个分片是主分片。因为ES写的顺序是先写主分片,然后并发写副本分片,这样的机制保证了主分片的数据是最新的。因此元数据记录的最新主分片即为重启后的主分片。在重新启动时,主分片所在的节点可能无法正常启动,这时候会在in-sync列表里选取一个分片作为主分片。

3.2 选取副本分片

主分片分配完成后,分片汇总信息中的其他分片作为副本分片,如果还不够,则说明有的分片所在的节点已经无法启动,这时候集群会在其他节点重新分配副本分片。ES并没有强制要求相同分片的副本不能再同一个节点分配。而kafka则有这样的要求。

4 分片恢复

在分片分配完成后,则开始了分片数据的恢复。

4.1 主分片恢复

主分片的恢复不会等到副本分片全部选取之后才开始。他是一个独立的过程。主分片需要恢复的原因是在上次关机或者集群异常退出时,有些数据可能还没有刷盘。每次刷盘都会记录一个syncid,tranlog需要重放syncid后的写操作。并简历Lucene索引。

4.2 副本分片恢复

副本分片恢复是一个较为复杂的流程,这个流程经过了多次的修改,这个修改的过程与Redis的主从复制面临着同样的问题,解决思想也比较相似。

4.2.1 初始版本

初始版本分为两个阶段:

  • phase1:副本节点向主节点发送请求复制,这时候主节点会将已刷盘的数据制作快照,并将快照发送到副本节点。同时在translog上加锁,为了保留在恢复的过程中执行的写操作。
  • phase2:将translog做快照,快照中包括从phase1开始,到执行translog过程中新增的索引数据,将这些translog回放。

这个版本的恢复存在的问题是,不管副本分片之前有无数据都需要复制主分片的所有数据。当数据量较大时,phase1需要执行很长时间,这回带来两个问题:

  • 不必要的数据传输,如果副本分片之前存在大部分数据,或者整体的数据,phase1的数据不需要进行。
  • phase1如果执行时间较长,这时候主节点的translog由于被锁住,长时间不能刷盘,translog无法被清理。

4.2.2 最终版本

基于以上的不足,副本的恢复经过,视图版本,将translog分成多个文件,进化到最终的基于序列号的最终版本。分片在每次刷盘是都会记录当前分片刷盘的sequenceNumber。副本在恢复时会将自己的sequenceNumber发送给主分片,如果sequenceNumber在translog中,则直接使用translog恢复,否则才制作phase1中的快照。

4.2.3 值覆盖问题解决

当副本分片执行完phase1后就可以接收集群的写入请求了。这时候会存在一个问题,恢复过程中旧值被新值覆盖的问题。例如文档ID为docId的值刚开始为4。这个值在translog中,主副本分片都没有来及刷盘服务器重启了,当phase1执行完之后,集群接收到请求将docId设置为4,这时候如果副本分片先执行了修改值,然后重放translog。这时候docId的值就会被覆盖为3。
ES引入了版本号来解决这个问题。版本号由主分片分配,当发现存在旧版本数据覆盖新版本数据时,会放弃覆盖来解决这个问题。

posted @ 2021-06-26 22:37  arax  阅读(1295)  评论(0编辑  收藏  举报