Open Distro for Elasticsearch 能够提供无缝扩展体验的关键在于它能够跨计算机分配其工作负载。此能力通过分片实现。当您创建索引时,可以为该索引设置主分片和副本分片数。Elasticsearch 跨这些分片分配您的数据和请求,还会跨数据节点分配分片。
集群的容量和性能很大程度上取决于 Elasticsearch 如何在节点上分配分片。如果所有流量因为一两个节点包含集群中的活动索引而流向这一两个节点,那么这些节点将显示较高的 CPU、RAM、磁盘和网络使用率。当这几个节点无比忙碌时,您的集群中可能另有数十个或数百个节点处于空闲状态。
在这篇博文中,我将深入探讨 Elasticsearch 的分片分配策略并讨论集群中“热”节点存在的原因。理解这些分析之后,您将可以解决根本问题,获得更好的性能和更稳定的集群。
分片设置不均匀可能导致集群故障
在最佳分片分布中,每台计算机具有均衡的资源利用率:每个分片具有相同的存储空间占用量,各请求由各分片轮流处理,并且各请求均等地使用 CPU、RAM、磁盘和网络资源。当您进行垂直或水平扩展时,额外的节点对于执行集群工作以及增加其容量贡献均等的力量。
最佳情形大致就是如此。实际上,您在集群中运行多个索引时,数据的分布是不均匀的,并且请求在不同节点上以不同的速率处理。在之前的博文中,Jon Handler 解释了存储空间的使用量如何变得不均匀。当分片分布不均匀时,CPU、网络和磁盘带宽的使用量也会变得不均匀。
例如,假设您有一个具有三个索引的集群,每个索引有四个主分片,部署在六个节点上,如下图所示。方形索引的分片全部落在两个节点上,而圆形和圆角矩形索引则分布在四个节点上。如果方形索引接收的流量是其他两个索引的十倍,那么这些节点将需要十倍于其他四个节点的 CPU、磁盘、网络和 RAM(可能)。您要么基于方形索引的要求进行超额扩展,要么在针对其他节点扩展之后眼睁睁看着集群出现故障。
六个 Elasticsearch 节点的图表,其中三个索引显示出不均匀、偏重于某部分的 CPU、RAM、JVM 和 I/O 使用量。
正确的分配策略应该做出符合系统要求的明智决策。这是一个难题,Elasticsearch 很好地解决了它。让我们深入探讨 Elasticsearch 的算法。
ShardsAllocator 确定设置分片的位置
ShardsAllocator 是 Elasticsearch 的一个接口,负责实现分片放置。当分片因任何原因未指定时,ShardsAllocator 将决定在集群中的哪些节点放置分片。
ShardsAllocator 将在以下条件下确定分片位置:
索引创建 – 当您向集群添加索引(或从快照恢复索引)时,ShardsAllocator 会决定放置其分片的位置。当您增加索引的副本数时,它会决定新副本的位置。
节点故障 – 如果某节点从集群中脱离,ShardsAllocator 会找出放置该节点上分片的新位置。
集群大小调整 – 如果在集群中添加或删除节点,ShardsAllocator 将决定如何重新均衡集群。
磁盘高使用率标记 – 当节点上的磁盘使用量达到高使用率标记(默认为 90% 已满)时,Elasticsearch 会使用 ShardsAllocator 从该节点移出分片。
手动分片路由 – 当您手动路由分片时,ShardsAllocator 还会移动其他分片以确保集群保持均衡。
路由相关设置更新 – 当您更改影响分片路由的集群或索引设置(例如分配感知)时,可排除或包含某节点(按 IP 或节点属性),或筛选索引以包含/排除特定节点。
分片放置策略可以拆分为两个较小的子问题:要作用于哪个分片,以及要放置于哪个目标节点。默认的 Elasticsearch 实施程序 BalancedShardsAllocator,将其职责划分为三个主要存储桶:分配未指定的分片、移动分片和重新均衡分片。其中每个都在内部解决原始子问题并为分片决定一个动作:是将其分配到特定节点、将其从一个节点移动到另一个节点,还是简单地保持原样。
当存在可能影响分片放置的集群状态更改时,将调用整体放置操作,这在 Elasticsearch 中称作重新路由。
节点选择
Elasticsearch 通过处理一系列 Allocation Decider 来获得符合资格的节点列表。节点资格可能因分片和节点上的当前分配而异。不是所有节点都有资格接受特定分片。例如,Elasticsearch 不会将副本分片与主分片放置于同一节点。如果节点的磁盘已满,则 Elasticsearch 不能在其上放置另一个分片。
对于分片放置,Elasticsearch 遵循一种“贪婪”的方法:它作出本地最优的决策,并希望达成全局最优。将节点的分片资格抽象为权重函数,然后将每个分片分配给当前最有资格接受它的节点。将此权重函数视为一个数学函数,给定一些参数就可以返回节点上分片的权重。分片最合适的节点是权重最小的节点。
AllocateUnassigned
重新路由进行的第一个操作是 allocateUnassigned。每次创建索引时,其分片(主分片和副本分片)都是未指定的。当节点离开集群时,该节点上的分片将丢失。对于那些丢失的主分片,它们幸存的副本分片(如果有)将被提升为主分片(这由不同的模块完成),并且相应的副本分片将被取消指定。所有这些分片都将在此操作中被分配至节点。
对于 allocateUnassigned(),BalancedShardsAllocator 遍历所有未指定的分片,找到有资格接受分片的节点子集(Allocation Decider),并从中选出具有最小权重的节点。
Elasticsearch 依照某种固定顺序选择未指定的分片进行分配。其首先选择主分片,为一个索引分配所有分片,然后再转到下一个索引的主分片。为选择索引,它基于索引优先级、创建数据和索引名称使用比较程序(参见 PriorityComparator)。这确保了 Elasticsearch 为尽可能多的索引指定所有主分片,而不是创建多个仅部分指定的索引。在 Elasticsearch 指定了所有主分片后,它就会移动到各索引的第一个副本分片。然后它会移动到各索引的第二个副本分片,依此类推。
移动分片
考虑需要缩小集群的情况。为响应工作负载的季节性变化,您刚刚经过了高流量的季节,现在又恢复到适度的工作负载。您希望通过删除一些节点来将集群的大小调整适当。如果过快删除保存数据的节点,则可能会删除包含主分片及其副本分片的节点,导致数据永久丢失。更好的方法是排除节点的一个子集,等待所有分片移出,然后终止它们。
或者,考虑一下节点的磁盘已满,必须移出一些分片以释放空间的情况。在这种情况下,必须将一个分片移出节点。此过程由 moveShards() 操作处理,就在 allocateUnassigned() 完成后触发。
对于“移动分片”,Elasticsearch 遍历集群中的每个分片,并检查其是否可以留存在当前节点上。如果不可保留,其从合格节点的子集中(由 Decider 过滤)选出权重最小的的节点,作为此分片的目标节点。然后触发从当前节点到目标节点的分片重定位。
移动操作仅应用于已启动分片;其他状态的分片将被跳过。要从所有节点统一移动分片,moveShards 会使用 nodeInterleavedShardIterator。此迭代程序首先跨节点进行广度处理,从每个节点中选择一个分片,然后是下一个分片,以此类推。因此,所有节点上的所有分片都会评估移动必要性,不存在优先或侧重。
重新均衡分片
当您达到工作负载限制时,您可能决定添加更多节点来扩展您的集群。Elasticsearch 会自动检测这些节点并重新定位分片,以便优化分布。添加或删除节点可能并不总是需要移动分片 – 例如节点的分片很少(假设只有一个),额外的节点只是作为预防性的扩展对策添加的。
Elasticsearch 使用分片分配程序中的权重函数抽象来将此决策一般化。给定某节点上的当前分配,权重函数会为节点上的分片提供权重。具有高权重值的节点较之低权重的节点,不适合放置分片。比较不同节点上分片的权重,我们可以确定重新定位是否能够改善整体权重分布。
为作出重新均衡决策,Elasticsearch 要计算每个节点上每个索引的权重,以及索引的最小和最大可能权重之间的差值。(这可以在索引级别完成,因为索引中的每个分片在 Elasticsearch 中都是平等处理的。) 然后,按照最不均衡索引最先处理的顺序处理索引。
分片移动是一项繁重的操作。在实际重新定位之前,Elasticsearch 会在重新均衡之前和之后对分片权重进行建模;仅当操作可实现权重的更均衡分布时才会重新定位分片。
最后,重新均衡是一个优化问题。超过某个阈值后,移动分片的成本开始超过权重均衡的益处。在 Elasticsearch 中,此阈值当前是固定值,可通过动态设定 cluster.routing.allocation.balance.threshold 来配置。当索引的计算权重增量 – 跨节点的最小和最大权重之间的差值 – 小于该阈值时,该索引被认为是均衡的。
小结
在这篇文章中,我们讨论了在 Elasticsearch 中执行分片放置和均衡决策所依据的算法。每次重新路由调用都要经历分配未指定的分片、移动必须从当前节点撤出的分片以及尽可能重新平衡分片的过程。这些操作可保持集群持久平衡。
在下一篇文章中,我们将深入研究默认权重函数的实现,该函数负责在给定分片位置时,选出最优的放置节点。
本文转载自 AWS 博客。
原文链接:
https://amazonaws-china.com/cn/blogs/china/open-distro-elasticsearch-shard-allocation/
评论