MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

ElasticSearch集群allocation过程的深入解析

2021-03-175.3k 阅读

ElasticSearch 集群分配(allocation)基础概念

在 ElasticSearch 集群中,allocation 是指将分片(shard)分配到集群中的各个节点(node)的过程。ElasticSearch 的核心设计目标之一就是实现数据的高可用性和分布式存储,而 allocation 机制在这一过程中扮演着至关重要的角色。

ElasticSearch 中的每个索引(index)可以被分成多个主分片(primary shard),每个主分片又可以有多个副本分片(replica shard)。主分片负责处理索引和搜索请求,副本分片则用于提供数据冗余和高可用性,当主分片所在节点出现故障时,副本分片可以提升为主分片继续提供服务。

当一个索引被创建时,ElasticSearch 会根据集群的配置和当前节点的状态,决定如何将主分片和副本分片分配到各个节点上。这个分配过程需要考虑多个因素,如节点的负载、磁盘空间、网络状况等,以确保集群能够高效、稳定地运行。

分配决策因素

  1. 节点属性 ElasticSearch 允许为节点定义自定义属性,这些属性可以用于控制分片的分配。例如,可以为节点设置 rack 属性来表示节点所在的机架,然后通过配置让不同的主分片和副本分片分布在不同的机架上,以防止整个机架故障导致数据丢失。 在 ElasticSearch 配置文件 elasticsearch.yml 中,可以通过以下方式设置节点属性:
node.attr.rack: rack1

在索引创建时,可以使用 routing.allocation.includerouting.allocation.exclude 参数来指定根据节点属性进行分片分配。例如,要将索引的分片分配到 rack 属性为 rack1 的节点上,可以这样创建索引:

PUT /my_index
{
    "settings": {
        "index.routing.allocation.include.rack": "rack1"
    }
}
  1. 节点负载 ElasticSearch 会监控节点的负载情况,包括 CPU 使用率、内存使用率、磁盘 I/O 等指标。在分配分片时,倾向于将分片分配到负载较低的节点上,以平衡集群的整体负载。 可以通过 ElasticSearch 的监控 API,如 /_cat/nodes?v 来查看节点的负载信息:
curl -X GET "localhost:9200/_cat/nodes?v"

该命令会返回节点的详细信息,包括负载指标,如下所示:

ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.1.1           20          90   5    0.10    0.20     0.30 mdi       *      node1
192.168.1.2           30          85   3    0.05    0.15     0.25 mdi       -      node2
  1. 磁盘空间 节点的磁盘空间也是 allocation 过程中重要的考虑因素。ElasticSearch 会尽量避免将分片分配到磁盘空间不足的节点上,以防止数据写入失败。 ElasticSearch 通过配置 cluster.routing.allocation.disk.threshold_enabled 来启用磁盘空间检查,默认是启用的。还可以设置 cluster.routing.allocation.disk.watermark.lowcluster.routing.allocation.disk.watermark.high 来定义磁盘空间的高低水位线。当节点磁盘使用率超过高水位线时,ElasticSearch 会尝试将分片迁移到其他磁盘空间充足的节点上。 例如,在 elasticsearch.yml 中可以设置:
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%

分配过程详解

  1. 索引创建时的分配 当创建一个新索引时,ElasticSearch 首先会根据索引设置的主分片数量和副本分片数量,确定总共需要分配的分片数量。然后,根据上述提到的分配决策因素,如节点属性、负载、磁盘空间等,为每个分片选择一个合适的节点进行分配。 假设创建一个索引 my_index,设置主分片数量为 3,副本分片数量为 1:
PUT /my_index
{
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 1
    }
}

ElasticSearch 会首先为 3 个主分片选择节点进行分配,然后为每个主分片的副本分片选择不同的节点(通常情况下,副本分片不会与对应的主分片分配到同一个节点上)。这个过程中,ElasticSearch 的分配器(allocator)会遍历所有节点,评估每个节点的适合度,最终确定分片的分配方案。 2. 节点故障后的重新分配 当集群中的某个节点发生故障时,ElasticSearch 会自动检测到节点的失联,并启动重新分配过程。对于故障节点上的主分片,ElasticSearch 会从对应的副本分片中选择一个提升为主分片,然后重新分配其他副本分片,以确保数据的高可用性和副本数量符合配置要求。 例如,假设节点 node1 发生故障,该节点上有主分片 shard1。ElasticSearch 会从 shard1 的副本分片中选择一个,将其提升为主分片,然后重新分配 shard1 的其他副本分片到集群中的其他健康节点上。 3. 动态调整分配 ElasticSearch 还支持在集群运行过程中动态调整分片的分配。例如,可以通过 API 动态修改索引的副本数量,ElasticSearch 会根据新的配置重新分配副本分片。 要将 my_index 的副本数量从 1 增加到 2,可以使用以下 API:

PUT /my_index/_settings
{
    "number_of_replicas": 2
}

ElasticSearch 会计算需要新增的副本分片数量,并根据节点的负载、磁盘空间等因素,将这些副本分片分配到合适的节点上。

分配策略与算法

  1. 默认分配策略 ElasticSearch 的默认分配策略旨在平衡数据的分布和副本的冗余。它会尽量将主分片均匀地分布在不同的节点上,以避免单个节点承载过多的主分片导致负载过高。对于副本分片,默认策略会确保副本分片与对应的主分片不在同一个节点上,并且尽量均匀地分布在其他节点上。
  2. 分配算法 ElasticSearch 的分配算法较为复杂,它结合了多种因素进行综合评估。在选择节点分配分片时,算法会考虑节点的负载、磁盘空间、节点属性等因素,并为每个节点计算一个“得分”。得分越高的节点,越有可能被选中分配分片。 例如,对于负载较低、磁盘空间充足且符合节点属性要求的节点,其得分会相对较高。算法会遍历所有节点,根据节点的当前状态和索引的分配要求,为每个分片找到最合适的节点。

分配相关的 API 与操作

  1. 查看分片分配状态 可以使用 /_cat/shards API 来查看集群中所有分片的分配状态。该 API 会返回每个分片所在的节点、分片的状态(如 STARTEDUNASSIGNED 等)等信息。
curl -X GET "localhost:9200/_cat/shards?v"

返回结果示例:

index     shard prirep state      docs store ip         node
my_index  0     p      STARTED    100  50mb 192.168.1.1 node1
my_index  0     r      STARTED    100  50mb 192.168.1.2 node2
my_index  1     p      STARTED    120  60mb 192.168.1.2 node2
my_index  1     r      STARTED    120  60mb 192.168.1.3 node3
my_index  2     p      STARTED    110  55mb 192.168.1.3 node3
my_index  2     r      STARTED    110  55mb 192.168.1.1 node1
  1. 强制重新分配分片 在某些特殊情况下,如节点负载严重不均衡或需要手动调整分片分布时,可以使用 /_cluster/reroute API 来强制重新分配分片。该 API 允许手动指定分片的移动操作,例如将某个分片从一个节点移动到另一个节点。
POST /_cluster/reroute
{
    "commands": [
        {
            "move": {
                "index": "my_index",
                "shard": 0,
                "from_node": "node1",
                "to_node": "node3"
            }
        }
    ]
}

使用该 API 时需要谨慎,因为不当的操作可能会导致集群性能下降或数据丢失。

分配过程中的常见问题与解决方法

  1. 分片长时间处于 UNASSIGNED 状态 当分片长时间处于 UNASSIGNED 状态时,意味着 ElasticSearch 无法为该分片找到合适的节点进行分配。这可能是由于节点故障、磁盘空间不足、网络问题等原因导致的。 解决方法:
  • 检查节点状态:使用 /_cat/nodes API 查看节点是否正常运行,是否有节点处于故障状态。
  • 检查磁盘空间:通过 /_cat/nodes?v 查看节点的磁盘空间使用情况,确保有足够的磁盘空间来分配分片。
  • 检查网络连接:确保节点之间的网络连接正常,没有网络隔离或高延迟的情况。
  1. 分配导致集群性能下降 如果在分配过程中,大量分片同时进行迁移或分配,可能会导致集群性能下降,如搜索响应时间变长、写入速度变慢等。 解决方法:
  • 控制分配速度:可以通过设置 cluster.routing.allocation.cluster_concurrent_rebalance 来控制集群中同时进行的重新平衡操作的数量,默认值为 2。可以根据集群的实际情况适当调整该值,以避免对集群性能造成过大影响。例如,在 elasticsearch.yml 中设置:
cluster.routing.allocation.cluster_concurrent_rebalance: 1
  • 分阶段调整:如果需要进行大规模的分片分配或调整,建议分阶段进行,每次调整少量分片,给集群足够的时间来适应和恢复性能。

高级分配配置与优化

  1. 感知机架的分配 在大型数据中心中,节点通常分布在多个机架上。为了提高数据的可用性,防止整个机架故障导致数据丢失,可以配置 ElasticSearch 进行感知机架的分配。 首先,为每个节点设置 rack 属性,如前面所述。然后,在索引创建时,可以使用 index.routing.allocation.require.rack 参数来确保主分片和副本分片分布在不同的机架上。
PUT /my_index
{
    "settings": {
        "index.routing.allocation.require.rack": "_name"
    }
}

这里 _name 表示所有不同名称的机架,ElasticSearch 会自动将分片分配到不同的机架上。 2. 基于权重的分配 ElasticSearch 支持为节点设置权重,以影响分片的分配。权重越高的节点,在分配分片时越有可能被选中。 可以通过在 elasticsearch.yml 中设置 node.weight 来为节点设置权重,例如:

node.weight: 2

默认权重为 1,设置为 2 表示该节点在分配分片时的优先级是默认权重节点的两倍。在索引创建或动态调整时,ElasticSearch 会根据节点的权重来进行分片分配,以实现更灵活的资源利用和负载均衡。

通过深入理解 ElasticSearch 集群的 allocation 过程,我们可以更好地配置和管理集群,确保数据的高可用性和集群的高效运行。在实际应用中,需要根据具体的业务需求和集群环境,合理调整分配策略和配置参数,以达到最佳的性能和可靠性。同时,密切关注分配过程中的状态和问题,及时采取相应的解决措施,也是保障集群稳定运行的关键。