8.3 分片管理 (Shards API) Elasticsearch.x 集群管理与运维:深入分片管理 (Shards API) 1. 分片 (Shards) 的重要性 在深入 Shards API 之前,我们首先需要理解分片在 Elasticsearch 中的核心作用。Elasticsearch 索引实际上是由一个或多个分片组成的。分片是 Elasticsearch 中数据存储和处理的最小单元。每个分片都是一个独立的 Lucene 索引,可以分布在集群的不同节点上。 分片的主要作用包括: 水平扩展性: 通过将索引数据分割成多个分片,Elasticsearch 可以将数据分布在集群中的多个节点上,从而实现水平扩展,处理海量数据。
1. 分片 (Shards) 的重要性
在深入 Shards API 之前,我们首先需要理解分片在 Elasticsearch 中的核心作用。Elasticsearch 索引实际上是由一个或多个分片组成的。分片是 Elasticsearch 中数据存储和处理的最小单元。每个分片都是一个独立的 Lucene 索引,可以分布在集群的不同节点上。
分片的主要作用包括:
水平扩展性: 通过将索引数据分割成多个分片,Elasticsearch 可以将数据分布在集群中的多个节点上,从而实现水平扩展,处理海量数据。
提高性能: 查询可以并行在多个分片上执行,从而提高查询速度和吞吐量。
高可用性: Elasticsearch 允许为每个主分片创建副本分片。副本分片可以分布在不同的节点上,当主分片所在的节点发生故障时,副本分片可以自动提升为主分片,保障数据和服务的可用性。
为了更好地理解分片的概念,我们可以使用 Mermaid 的 graph TD 图来可视化索引和分片的关系:
图示说明:
Elasticsearch Cluster: 代表整个 Elasticsearch 集群。
Node 1, Node 2, Node 3: 代表集群中的三个节点。
Index: 代表一个 Elasticsearch 索引。
Shard1_Primary, Shard2_Primary: 代表索引的主分片 1 和主分片 2。
Shard1_Replica, Shard2_Replica: 代表索引的分片 1 和分片 2 的副本分片。
图中展示了一个简单的索引 Index 被分割成两个主分片 (Shard 1 Primary, Shard 2 Primary),并且每个主分片都有一个副本分片 (Shard 1 Replica, Shard 2 Replica)。主分片和副本分片被分布在集群的不同节点上。
2. Shards API 概览
Elasticsearch 的 Shards API 提供了一系列接口,用于获取和管理集群中分片的各种信息和状态。通过 Shards API,我们可以实现以下功能:
监控分片状态: 查看分片的健康状况、所在节点、大小、角色 (主分片/副本分片) 等信息。
查看分片分配: 了解分片在集群节点上的分布情况,以及分配原因。
手动控制分片分配: 在特定情况下,手动将分片移动到指定的节点,或者取消分片的分配。
查看分片恢复状态: 监控分片恢复的进度和状态。
Shards API 主要通过以下几个端点进行操作:
/_cat/shards: 以简洁的表格形式展示分片信息,适用于快速查看集群分片概览。
/_cluster/state: 返回集群的完整状态信息,包含分片的详细分配信息、路由表等。
/_cluster/reroute: 用于手动控制分片的分配和移动。
/_recovery: 用于查看分片的恢复状态。
接下来,我们将分别详细介绍这些 API 的使用方法和代码实践。
3. 使用 /_cat/shards API 查看分片信息
/_cat/shards API 是最常用的分片信息查看接口。它以易于阅读的表格形式展示分片的关键信息。
请求方法: GET
基本语法:
GET /_cat/shards?v
?v 参数表示显示表头 (Verbose),使输出更易读。
代码示例:
curl -X GET "localhost:9200/_cat/shards?v&pretty"
输出示例:
index shard prirep state docs store ip node my_index 0 p STARTED 1000 1mb 192.168.1.1 node-1 my_index 0 r STARTED 1000 1mb 192.168.1.2 node-2 my_index 1 p STARTED 1500 2mb 192.168.1.2 node-2 my_index 1 r STARTED 1500 2mb 192.168.1.3 node-3 your_index 0 p UNASSIGNED your_index 0 r UNASSIGNED
输出字段解释:
index: 分片所属的索引名称。
shard: 分片 ID (从 0 开始)。
prirep: 分片类型,p 表示主分片 (primary),r 表示副本分片 (replica)。
state: 分片状态,常见的状态包括:
INITIALIZING: 分片正在初始化。
STARTED: 分片已启动,可以正常提供服务。
RELOCATING: 分片正在被重新分配到另一个节点。
UNASSIGNED: 分片未被分配到任何节点。
RECOVERING: 分片正在从其他分片恢复数据。
POST_RECOVERY: 分片恢复后正在进行后续操作。
docs: 分片中包含的文档数量。
store: 分片占用的磁盘空间大小。
ip: 分片所在的节点 IP 地址。
node: 分片所在的节点名称。
常用参数:
index 参数: 过滤指定索引的分片信息。例如,/_cat/shards/my_index?v 只显示 my_index 索引的分片信息。
h 参数: 指定需要显示的列头。例如,/_cat/shards?v&h=index,shard,state,node 只显示索引、分片 ID、状态和节点列。
s 参数: 指定排序字段。例如,/_cat/shards?v&s=node 按照节点名称排序。
bytes 参数: 控制 store 列的单位,可选值包括 b (bytes), k (kilobytes), m (megabytes), g (gigabytes), t (terabytes), p (petabytes)。例如,/_cat/shards?v&bytes=m 以 MB 为单位显示 store 列。
health 参数: 过滤指定健康状态的分片,可选值包括 green, yellow, red。例如,/_cat/shards?v&health=red 只显示健康状态为 red 的分片。
代码示例 (过滤指定索引和状态):
curl -X GET "localhost:9200/_cat/shards/my_index?v&state=STARTED&pretty"
该命令只显示 my_index 索引中状态为 STARTED 的分片信息。
4. 使用 /_cluster/state API 获取详细分片分配信息
/_cluster/state API 返回集群的完整状态信息,包含了分片分配的详细信息,例如分片路由表、分配原因等。
请求方法: GET
基本语法:
GET /_cluster/state?filter_path=routing_table.indices.*.shards,routing_nodes.nodes.*.shards
为了减少返回数据量,我们可以使用 filter_path 参数来过滤只返回我们关心的信息。上面的示例中,filter_path 参数指定只返回 routing_table.indices 和 routing_nodes.nodes 下的分片相关信息。
代码示例:
curl -X GET "localhost:9200/_cluster/state?filter_path=routing_table.indices.*.shards,routing_nodes.nodes.*.shards&pretty"
输出示例 (部分):
{ "routing_table" : { "indices" : { "my_index" : { "shards" : { "0" : { "0" : { "state" : "STARTED", "primary" : true, "node" : "node-1", "relocating_node" : null, "shard" : 0, "index" : "my_index", "allocation_id" : { "id" : "xxxxxxxxxxxxxxxxxxxxxx" }, "unassigned_info" : null }, "1" : { "state" : "STARTED", "primary" : false, "node" : "node-2", "relocating_node" : null, "shard" : 0, "index" : "my_index", "allocation_id" : { "id" : "yyyyyyyyyyyyyyyyyyyyyy" }, "unassigned_info" : null } }, "1" : { "0" : { "state" : "STARTED", "primary" : true, "node" : "node-2", "relocating_node" : null, "shard" : 1, "index" : "my_index", "allocation_id" : { "id" : "zzzzzzzzzzzzzzzzzzzz" }, "unassigned_info" : null }, "1" : { "state" : "STARTED", "primary" : false, "node" : "node-3", "relocating_node" : null, "shard" : 1, "index" : "my_index", "allocation_id" : { "id" : "aaaaaaaaaaaaaaaaaaaaaa" }, "unassigned_info" : null } } } } } }, "routing_nodes" : { "nodes" : { "node-1" : { "shards" : [ { "state" : "STARTED", "primary" : true, "node" : "node-1", "relocating_node" : null, "shard" : 0, "index" : "my_index", "allocation_id" : { "id" : "xxxxxxxxxxxxxxxxxxxxxx" }, "unassigned_info" : null } ] }, "node-2" : { "shards" : [ { "state" : "STARTED", "primary" : false, "node" : "node-2", "relocating_node" : null, "shard" : 0, "index" : "my_index", "allocation_id" : { "id" : "yyyyyyyyyyyyyyyyyyyyyy" }, "unassigned_info" : null }, { "state" : "STARTED", "primary" : true, "node" : "node-2", "relocating_node" : null, "shard" : 1, "index" : "my_index", "allocation_id" : { "id" : "zzzzzzzzzzzzzzzzzzzz" }, "unassigned_info" : null } ] }, "node-3" : { "shards" : [ { "state" : "STARTED", "primary" : false, "node" : "node-3", "relocating_node" : null, "shard" : 1, "index" : "my_index", "allocation_id" : { "id" : "aaaaaaaaaaaaaaaaaaaaaa" }, "unassigned_info" : null } ] } } } }
输出字段解释 (部分):
routing_table.indices.[index_name].shards.[shard_id].[replica_id]: 包含了每个索引、每个分片、每个副本的详细路由信息。
state: 分片状态。
primary: 是否为主分片。
node: 分片所在的节点名称。
allocation_id.id: 分片分配 ID,用于唯一标识一个分片实例。
unassigned_info: 如果分片未分配,会包含未分配的原因信息。
routing_nodes.nodes.[node_name].shards: 包含了每个节点上分配的分片信息。
常用参数:
filter_path 参数: 用于过滤返回的 JSON 字段,可以根据需要选择返回特定的信息,例如只返回 routing_table.indices.*.shards.state 来查看所有分片的状态。
local 参数: 设置为 true 时,只从本地节点获取集群状态信息,默认为 false。
master_timeout 参数: 设置等待连接主节点的超时时间,默认为 30s。
5. 使用 /_cluster/reroute API 手动控制分片分配
/_cluster/reroute API 允许管理员手动控制分片的分配和移动。这在某些特殊场景下非常有用,例如:
节点维护: 在节点维护前,可以将该节点上的分片移动到其他节点。
集群负载均衡: 手动调整分片分布,优化集群负载均衡。
故障恢复: 在某些故障情况下,手动重新分配未分配的分片。
请求方法: POST
请求体 (JSON): 请求体中需要指定要执行的操作,主要有以下几种操作类型:
move: 将指定分片从一个节点移动到另一个节点。
allocate_replica: 为指定分片分配一个新的副本分片到指定的节点。
cancel: 取消指定分片的分配。
基本语法 (move 操作):
POST /_cluster/reroute?retry_failed=true&pretty { "commands": [ { "move": { "index": "<index_name>", "shard": <shard_id>, "from_node": "<source_node_name>", "to_node": "<target_node_name>" } } ] }
代码示例 (将 my_index 索引的 0 号主分片从 node-1 移动到 node-3):
curl -X POST "localhost:9200/_cluster/reroute?retry_failed=true&pretty" -H 'Content-Type: application/json' -d' { "commands": [ { "move": { "index": "my_index", "shard": 0, "from_node": "node-1", "to_node": "node-3" } } ] } '
基本语法 (allocate_replica 操作):
POST /_cluster/reroute?retry_failed=true&pretty { "commands": [ { "allocate_replica": { "index": "<index_name>", "shard": <shard_id>, "node": "<target_node_name>" } } ] }
代码示例 (为 my_index 索引的 0 号分片分配一个副本分片到 node-3):
curl -X POST "localhost:9200/_cluster/reroute?retry_failed=true&pretty" -H 'Content-Type: application/json' -d' { "commands": [ { "allocate_replica": { "index": "my_index", "shard": 0, "node": "node-3" } } ] } '
基本语法 (cancel 操作):
POST /_cluster/reroute?retry_failed=true&pretty { "commands": [ { "cancel": { "index": "<index_name>", "shard": <shard_id>, "node": "<node_name>", "allow_primary": true // 如果取消的是主分片,需要设置为 true } } ] }
代码示例 (取消 my_index 索引的 0 号副本分片在 node-2 上的分配):
curl -X POST "localhost:9200/_cluster/reroute?retry_failed=true&pretty" -H 'Content-Type: application/json' -d' { "commands": [ { "cancel": { "index": "my_index", "shard": 0, "node": "node-2" } } ] } '
重要注意事项:
手动分片分配操作应该谨慎使用,错误的操作可能导致数据丢失或集群不稳定。
在执行 cancel 操作取消主分片分配时,需要设置 allow_primary: true,并且需要确保集群有足够的副本分片来保障数据安全。
retry_failed=true 参数表示如果 reroute 操作失败,则将其添加到失败队列中,稍后重试。
6. 使用 /_recovery API 查看分片恢复状态
/_recovery API 用于查看分片的恢复状态,可以监控分片恢复的进度和详细信息。当节点重启、主分片故障或者新节点加入集群时,可能会触发分片恢复操作。
请求方法: GET
基本语法:
GET /_recovery?active_only=true&detailed=true&pretty
active_only=true 参数表示只显示正在进行中的恢复操作。
detailed=true 参数表示显示更详细的恢复信息。
代码示例:
curl -X GET "localhost:9200/_recovery?active_only=true&detailed=true&pretty"
输出示例 (部分):
{ "my_index" : { "shards" : { "0" : { "index" : { "stage" : "INDEX", "time" : { "total_time_in_millis" : 1234, "throttle_time_in_millis" : 0 }, "source" : { "id" : "node-1", "host" : "192.168.1.1", "transport_address" : "192.168.1.1:9300", "attributes" : { } }, "target" : { "id" : "node-3", "host" : "192.168.1.3", "transport_address" : "192.168.1.3:9300", "attributes" : { } }, "translog" : { "recovered" : 100, "total" : 1000, "percent_completed" : "10.0%", "total_on_disk" : "10mb" }, "files" : { "recovered" : 5, "total" : 10, "percent_completed" : "50.0%", "total_bytes" : "100mb", "reused_bytes" : "50mb", "details" : [ ] }, "total_bytes" : { "reused" : "50mb", "recovered" : "50mb", "total" : "100mb", "percent_completed" : "50.0%" }, "bytes" : { "reused" : "50mb", "recovered" : "50mb", "total" : "100mb", "percent_completed" : "50.0%" } }, "type" : "REPLICA", "stage" : "INDEX", "primary" : false, "start_time" : "2024-01-01T10:00:00.000Z", "start_time_in_millis" : 1704093600000, "total_time_in_millis" : 1234, "source_node" : "node-1", "target_node" : "node-3" } } } }
输出字段解释 (部分):
stage: 恢复阶段,常见的阶段包括:
INIT: 初始化阶段。
INDEX: 索引数据恢复阶段。
TRANSLOG: 事务日志恢复阶段。
FINALIZE: 完成阶段。
time.total_time_in_millis: 总恢复时间 (毫秒)。
translog.percent_completed: 事务日志恢复进度百分比。
files.percent_completed: 文件恢复进度百分比。
total_bytes.percent_completed: 总字节恢复进度百分比。
source.id: 数据来源节点 ID。
target.id: 数据目标节点 ID。
常用参数:
index 参数: 过滤指定索引的恢复状态,例如 /_recovery/my_index?active_only=true&detailed=true&pretty。
active_only 参数: 设置为 true 只显示正在进行的恢复操作,设置为 false 显示所有恢复操作 (包括已完成的)。
detailed 参数: 设置为 true 显示更详细的恢复信息,设置为 false 显示简略信息。
7. 分片管理最佳实践
合理规划分片数量: 索引分片数量需要在性能和资源利用率之间进行权衡。过少的分片可能限制水平扩展能力,过多的分片会增加集群管理的复杂度和资源开销。通常建议每个分片大小在 20GB-50GB 之间。
监控分片健康状态: 定期使用 /_cat/shards API 监控分片状态,及时发现和处理 UNASSIGNED 或 RECOVERING 等异常状态的分片。
关注分片分配: 使用 /_cluster/state API 了解分片在集群节点上的分布情况,确保分片均匀分布,避免节点负载不均衡。
谨慎使用手动分片分配: 除非必要,尽量避免手动干预分片分配,让 Elasticsearch 自动进行分片管理。
关注分片恢复进度: 在节点故障或重启后,使用 /_recovery API 监控分片恢复进度,确保数据快速恢复。
定期优化索引和分片: 根据业务需求和数据增长情况,定期优化索引设置,例如调整副本数量、刷新间隔等,并考虑是否需要进行索引滚动更新或分片拆分/合并等操作。
8. 总结
Shards API 是 Elasticsearch 集群管理和运维的重要工具。通过本文的详细介绍和代码实践,相信读者已经对 Shards API 的各个方面有了深入的理解。熟练掌握 Shards API 的使用,能够帮助我们更好地监控、管理和优化 Elasticsearch 集群的分片,保障集群的稳定性和性能,为构建高效可靠的搜索和分析服务奠定坚实的基础。在实际运维工作中,结合监控工具和告警机制,可以更有效地利用 Shards API 进行集群管理,确保 Elasticsearch 集群的健康运行。