【Elasticsearch】存在数据的分片分配流程梳理

由于master节点只保存了cluster级别和indices级别的元数据,但没有shard在哪个node上的元数据,需要走一遍allocation流程确定每个shard分配到哪个节点,allocation使用allocator和deciders进行节点选择,allocator负责整个流程会找出哪些节点可以分配,deciders通过多个decider判断该节点能否分配,很多分片分配的配置都是通过decider实现的,例如primary和replica不能分配在同一个节点、磁盘容量大于85%不能分配。

I. Master node

  1. gateway阶段结束后,触发reroute分配分片
  2. shuffle 所有未分配的分片。作用是避免一些有问题的分片影响其他分片分配。例如,集群分片分配的并发是1,有一个分片因为文件损坏无法分配,如果不进行shuffle,每次分片分配的都是这个有问题的分片,直到到达次数上限
  3. 对unassigned shard按优先级排序,首先比较index.priority,其次是index create time,最后index name。
    没错,鉴权相关的索引优先级最高,确保集群接口最快可用
  4. 首先使用primaryShardAllocator对所有primary进行分配,根据每个shard向所有节点异步发起fetchData请求,拉取shard的元数据
  5. 由于请求是异步的,当前还没有元数据,因此reroute结束

II. Data node

  1. 从磁盘目录加载shard元数据,包含allocationId, boolean primary, discovery node。
  2. 尝试调用Lucene从shard目录打开索引,如果遇到异常则加入返回信息中,例如磁盘故障就会抛出异常
  3. 将allocationId, boolean primary, discovery node,store exception返回给master节点

III. Master node

  1. 当fetchData请求的response返回后,会保存结果,触发reroute来继续分配分片
  2. 将该分片在所有节点的返回结果进行排序,排序依次比较no excepiton 和 primary
  3. 使用deciders将节点分为三组yes(可以分配) no(不能分配) throttled(分配受到并发限制)
  4. 如果yes不为空,则将shard分配给列表中的第一个节点
  5. 如果yes和throttle为空,no不为空,则尝试是否能够forceAllocate,forceAllocate会将no返回为yes,yes和throttle正常返回
  6. 如果结果为yes则将分片分配给对应节点,更新相关数据结构,否则分片标记ignore,避免分片走到新建分片分配流程
  7. 遍历replica shard,使用replicaShardAllocator进行allocate
  8. 先通过deciders判断一下,是否至少有一个节点可以分配shard,如果分配不了就省略后面逻辑
  9. 和primary一样,拉取分片元数据,不过元数据不同

IV. Data node

  1. 从内存或者磁盘获取StoreFilesMetadata,其中包含retention lease, MetadataSnapshot(shard Lucene文件元数据)
  2. 返回StoreFilesMetadata给master

V. Master node

  1. 需要对返回结果的node按照replica数据的落后程度进行排序,优先数据较全的。最匹配的节点的排序方式是

    • 无需回放操作(replica SeqNo(从retention lease获取) > primary SeqNo或者replica sync flush id = primary https://www.elastic.co/guide/en/elasticsearch/reference/6.0/indices-synced-flush.html) 。顺便说一句,Elasticsearch 跟踪每个分片的索引活动。 5 分钟内未收到任何索引操作的分片将自动标记为非活动状态。 这为 Elasticsearch 提供了减少分片占用资源并执行一种特殊类型的刷新(称为synced flush)的机会。 同步刷新执行正常刷新,然后将生成的唯一标记(sync_id)添加到所有分片。

      由于sync id标记是在没有正在进行的索引操作时添加的,因此它可以用作检查两个分片的 lucene 索引是否相同的快速方法。 这种快速sync ID 比较(如果存在)在恢复或重新启动期间使用,以跳过该过程的第一个也是成本最高的阶段。 在这种情况下,不需要复制段文件,并且可以立即开始恢复的事务日志重播阶段。 请注意,由于sync ID 标记与刷新一起应用,因此事务日志很可能为空,从而进一步加快恢复速度。

    • retenton lease的seq No较大(意味着需要回放的操作少)

    • Checksum相同的文件大小较大的

  2. 使用decider对最匹配的节点进行决策,如果throttle则返回,如果是yes或者no则返回yes

  3. 如果最匹配的节点都没有数据则replica shard进行延迟分配

  4. reroute完成后构建集群新的状态。最后master将新的集群状态广播下去

VI. Data node

  1. 数据节点收到cluster state change后,应用变化,创建或更新shard
  2. 节点上无该shard时,createshard,进行shard recovery,主分片从本地恢复,副本从主分片恢复

总结

  1. fetch data过程会发送shard num * node num个请求,并且会将结果保存在内存中。当集群规模较大时,master节点内存会被打满,150节点 7w分片 master节点10GB内存时就出现过。可以考虑将sync allocation id和node的映射保存在cluster state,或者按分片并发数进行限流
  2. 利用retention lease和synced id加速replica的恢复过程,synced id用于快速比较,retention lease减少回放的doc数。有个问题是为什么不通过sync allocation id列表来给replica排序呢

你可能感兴趣的:(elasticsearch,java,大数据,搜索引擎,系统架构)