集群启动过程指集群完全重启时的启动过程,期间经历选举主节点、主分片、数据恢复等。
2.1 选举主节点
集群启动时,需要从已知活跃的机器列表中选择一个作为主节点,选主之后的流程由主节点触发。
参选人数过半时选出临时Master、得票过半确定Master、当节点离开时检测集群节点数等。
选取的时间点为:当集群启动的备选master节点过半时开始选举,例如ES集群有7个ES实例组成,5个ES实例设置了node.master=true(选主备选),所以当这个5个实例超过::discovery.zen.minimum_master_nodes::个节点启动就可以开始选举主节点,当节点得到投票超过半数时,当前节点被选为主节点。
2.2 元数据恢复
主节点确定后,会向所有的节点获取元数据信息,当收到发回元数据信息的候选节点超过半数后,对比当前拿到的元数据信息集合,选择版本号最大的元数据信息作为最新的元数据,并广播到所有的节点。
- gateway.excepted_nodes : 预期节点数,当加入集群的节点数大于该值时即可开始恢复元数据。
- gateway.recovery_after_time : 在达到预期节点数之前等待的最长时间,如果在该时间段内,集群还未达到预期节点数,则元数据也开始恢复。默认值为5min
- gateway.recovery_after_nodes : 只要加入集群的节点数量达到当前配置数量则开始恢复元数据。
元数据信息
- MetaData(集群级),主要存储clusterID、settings、templates;
- IndexMetaData(索引级),主要存储numberOfShards、mappings;
- ShardStateMetaData(分片级),主要存储version、indexUUID、primary。
集群在持久化时不会保存哪个分片位于哪个节点上,这些信息是在在集群元数据和索引元数据恢复完成后,发布一个异步的任务来确定去完成构建路由表的过程。
2.3 分配分片
2.3.1 分配主分片
ES5.X之后,ES为每个分片设置了一个shardUUID,并在元数据中保存着哪个分片是主分片。因为ES写的顺序是先写主分片,然后并发写副本分片,这样的机制保证了主分片的数据是最新的。因此元数据记录的最新主分片即为重启后的主分片。在重新启动时,主分片所在的节点可能无法正常启动,这时候会在in-sync列表里选取一个分片作为主分片。
2.3.2 分配副本分片
主分片分配完成后,分片汇总信息中的其他分片作为副本分片,如果还不够,则说明有的分片所在的节点已经无法启动,这时候集群会在其他节点重新分配副本分片。ES并没有强制要求相同分片的副本不能再同一个节点分配。
Kafka则强制要求同一个分片的多个副本不能分配到同一个节点。
2.4 分片恢复
分片分配成功后进入recovery流程。
::主分片的recovery不会等到副本分片分配完成后才开始,但是副本分片的recovery需要等到主分片recovery完成后才开始。::
- 为什么需要recovery流程?
对于主分片来说,上次集群停机后可能有一些数据没来得及刷盘
对于副分片来说,一是没刷盘,二是主分片写完了,副分片还没来得及写,主副分片数据不一致。
2.4.1 主分片recovery
由于每次写操作都会记录事务日志,因此最后一次提交(Lucene的一次提交即一次fsync刷盘过程)之后的translog中进行重放,建立Lucene索引,此时完成主分片的recovery。
2.4.2 副本分片recovery
副本分片需要恢复成与主分片数据一致,并且副本分片恢复期间允许新的索引操作。
- 副本恢复分为两个阶段进行:
- 副本节点向主节点发送请求复制,这时候主节点会将已刷盘的数据制作快照,并将快照发送到副本节点。同时在translog上加锁,为了保留在恢复的过程中执行的写操作。
- 将translog做快照,快照中包括从上一阶段开始,到执行translog过程中新增的索引数据,将这些translog回放。
- 这个版本的恢复存在的问题是,不管副本分片之前有无数据都需要复制主分片的所有数据。当数据量较大时,phase1需要执行很长时间,这回带来两个问题:
- 不必要的数据传输,如果副本分片之前存在大部分数据,或者整体的数据,phase1的数据不需要进行。
- phase1如果执行时间较长,这时候主节点的translog由于被锁住,长时间不能刷盘,translog无法被清理。
基于以上不足,ES改为通过序列号保证,分片在每次刷盘是都会记录当前分片刷盘的sequenceNumber。副本在恢复时会将自己的sequenceNumber发送给主分片,如果sequenceNumber在translog中,则直接使用translog恢复,否则才制作phase1中的快照。
总结
当一个索引的主分片分配成功时,该分片可以进行写操作。
当一个索引所有的主分片分配成功时,该索引由Red变为Yellow。
当一个集群所有索引的主分片分配成功时,整个集群由Red变为Yellow。
当一个集群所有索引的所有分片分配成功时,整个集群变为Green。