Elasticsearch 分片分配与再平衡的底层逻辑:从 allocation decider 到集群扩容抖动

Elasticsearch 分片分配与再平衡的底层逻辑:从 allocation decider 到集群扩容抖动

1. 先从一次扩容抖动说起

假设你维护一个 6 节点的 Elasticsearch 集群,每个节点 4 核 16GB 内存、2TB 数据盘。某天索引写入变慢,你决定横向扩容到 9 节点。新节点启动、加入集群,_cat/nodes 里能看到它们,但过了半小时,_cat/shards 里仍有大量分片集中在老节点上。你重启了几个新节点,分片反而开始来回搬,_cluster/health 从 green 掉到 yellow,写入延迟飙升。问题出在哪?

这不是"节点加得不对",而是 Elasticsearch 的分片分配与再平衡没有按你脑中的节奏走。分片不会因为"新机器有空位"就自动平均迁移,它要先过一整套准入判断,再根据权重决定要不要搬、搬多少、什么时候搬。

先记住一个最小模型:分片分配可以理解为"候选节点过滤 + 权重排序" 。过滤由 allocation decider 完成,判断某个分片能不能去某个节点;排序由 ShardsAllocator 完成,在能去的节点里选一个得分最高的。再平衡只是分配的一种触发场景,扩容抖动则通常由过滤被临时阻断、恢复任务并发不足、磁盘水位线卡住共同造成。

下面这张图先给出全局框架,后续章节按图中的顺序展开。

text 复制代码
集群状态变更(新节点加入 / 节点离线 / 索引创建)
        |
        v
+----------------------------+
|  AllocationService         |  收集待分配分片
|  (分配服务)              |
+-------------+--------------+
              |
              v
+----------------------------+
|  AllocationDecider 链      |  能不能去?
|  路由 / 磁盘水位 / 并发   |
|  副本同节点 / 过滤规则     |
+-------------+--------------+
              |
     能去节点列表
              |
              v
+----------------------------+
|  ShardsAllocator           |  去哪个更均衡?
|  BalancedShardsAllocator   |
+-------------+--------------+
              |
              v
+----------------------------+
|  ClusterState 更新         |  分片进入 INIT / RELOCATING
|  RoutingTable 落盘         |
+-------------+--------------+
              |
              v
+----------------------------+
|  节点执行 shard 恢复       |  先小后大,副本再平衡
+----------------------------+

这张图能帮助你理解"谁先谁后",但它不能替代真实源码中的并发状态机。真实集群里,decider 链会在不同阶段被多次调用,分配结果也可能因为节点状态变化而回滚重试。

2. allocation decider 到底是什么

allocation decider 是一组"准入判断器"。每个 decider 只回答一个问题:某个分片能不能分配到某个节点。所有 decider 依次过滤,只要有一个返回 NO,这个节点就被排除;如果返回 THROTTLE,它不会完全排除节点,而是降低优先级或延后分配。

常见的 decider 包括:

Decider 名称 判断内容 典型触发场景 返回 NO 的后果
SameShardAllocationDecider 同一分片的主副本是否已在目标节点 单节点上已有该分片副本 该节点不可用,强制换节点
DiskThresholdDecider 磁盘使用率是否超过 low/high/flood 水位线 高写入集群磁盘接近满 达到 high 后停止分配新分片,达到 flood 后索引变只读
ShardsLimitAllocationDecider 单节点上同一索引分片数是否超限 索引分片过多、节点少 阻止继续堆积,避免热点
ConcurrentRebalanceAllocationDecider 当前并发再平衡分片数是否超限 集群正在大量搬迁 延迟新再平衡,保护恢复带宽
FilterAllocationDecider 节点属性是否匹配 index.routing.allocation.* 机房、机架、冷热分层 节点被排除,分片去其他节点

看起来这些规则很零散,但它们的共同作用是:把"物理上能放"与"业务上该放"分开。物理上能放,包括磁盘、JVM、并发;业务上该放,包括机架感知、冷热分层、租户隔离。

这里最容易误解的是:decider 不是"一次性全部跑完"。在分片进入 INIT、RELOCATING、UNASSIGNED 等不同状态时,decider 链的输入和结果都会变化。例如节点刚加入时,磁盘水位线判断会把它当作"空闲节点"放行;但当它开始接收分片后,磁盘使用率上升,后续分片就会被重新过滤。

3. 一次分片分配的完整过程

现在让一次"新索引创建"完整走一遍。假设你创建了一个 3 主 1 副本的索引,集群有 3 个数据节点。

第一步,主节点收到 create index 请求,生成新的索引元数据,并把所有主分片放入 UNASSIGNED。

第二步,AllocationService 扫描路由表,发现 3 个主分片都未分配,于是对每个分片调用 decider 链。对于主分片,decider 会检查:目标节点是否已有同一分片的副本?磁盘是否超过水位线?节点是否被过滤规则排除?

第三步,能去的节点形成候选列表。BalancedShardsAllocator 会计算每个候选节点的权重。权重不是简单的"分片数最少",它还会考虑索引级均衡、节点容量、分片大小等因素。最终每个主分片选择一个节点。

第四步,主节点更新集群状态,分片进入 INITIALIZING,目标节点开始从主分片或快照恢复数据。副本分片不会和主分片同节点,分配到其他节点后进入 INITIALIZING,等待主分片恢复完成后复制。

这个过程可以用下面的时序图表示:

text 复制代码
客户端         主节点              数据节点 A        数据节点 B
  |              |                     |                 |
  | create index |                     |                 |
  |------------->|                     |                 |
  |              | 生成 UNASSIGNED     |                 |
  |              | 调用 decider 链     |                 |
  |              | 计算节点权重        |                 |
  |              | 选择 A 作为主分片   |                 |
  |              |-------------------->|                 |
  |              |                     | 分片 INIT       |
  |              | 选择 B 作为副本     |                 |
  |              |------------------------------------->|
  |              |                     |                 | 分片 INIT
  |              | 等待主分片恢复完成  |                 |
  |              |                     | 恢复完成        |
  |              |<--------------------|                 |
  |              | 副本开始复制        |                 |
  |              |------------------------------------->|
  |              |                     |                 | 副本恢复完成
  |<-------------|                     |                 |
  | 索引可用     |                     |                 |

这个顺序说明了:主分片先恢复,副本分片再跟进。如果主分片恢复慢,副本会一直等待,集群健康度会先显示 yellow,直到副本完成。

4. 分片再平衡:不是"越多越好"

再平衡是分配的一种,但目标不同。分配解决"分片有没有地方去",再平衡解决"分片分布是否足够均匀"。Elasticsearch 默认会在节点之间移动分片,让每个节点的分片数尽量接近,但再平衡受两个约束:

第一,不能破坏主副本分离。副本必须和主分片在不同节点,否则再平衡会把副本搬到主分片所在节点,触发 decider 的 NO。

第二,不能压垮恢复带宽。再平衡会搬运实际数据,如果同时搬太多分片,网络、磁盘、CPU 都会被占满,影响正常搜索和写入。因此 cluster.routing.allocation.cluster_concurrent_rebalance 默认值是 2,表示整个集群同时最多搬 2 个分片。

这里有一个常见的扩容误区:节点加进来后,不一定立刻发生再平衡 。因为再平衡的触发条件包括分片分布差异超过阈值、节点被加入分配过滤、索引级别设置了 index.routing.allocation.total_shards_per_node 等。如果新节点一开始没有满足这些条件,它只会"站着看",不会自动接盘。

你可以用下面命令观察再平衡情况:

bash 复制代码
GET _cat/shards?v&h=index,shard,prirep,state,docs,store,node
GET _cat/recovery?v&active_only=true
GET _cluster/settings?include_defaults=true&flat_settings=true | grep -E "rebalance|concurrent"

第一条看分片分布,第二条看正在恢复的分片,第三条看再平衡相关配置。如果你发现 RELOCATING 长期不结束,先看 _cat/recovery 里是否有分片卡在 TRANSLOG 或 FINALIZE 阶段,再检查磁盘水位线和网络带宽。

5. 集群扩容为什么会"抖"

扩容抖动不是单一原因,通常是下面四个因素叠加:

第一,并发恢复不足 。默认 cluster.routing.allocation.node_concurrent_recoveries 是 2,意味着每个节点同时最多恢复 2 个分片。新节点加入后,如果它同时被分配大量分片,恢复会排队,集群看起来"没反应"。

第二,副本分片先搬,主分片后搬。再平衡优先搬运副本,因为副本数据可以从主分片复制,风险低。但如果副本很多,搬迁会占用大量网络和磁盘。

第三,磁盘水位线阻断 。当节点磁盘使用率超过 cluster.routing.allocation.disk.watermark.low(默认 85%),新分片不会分配到该节点;超过 high(默认 90%),Elasticsearch 会尝试把分片移走;超过 flood(默认 95%),索引变成只读,写入直接失败。

第四,分片恢复和写入竞争。恢复分片时,节点既要读远端数据、写本地磁盘,又要处理正常写入。如果恢复并发太高,写入延迟会上升;如果太低,扩容后均衡太慢。

下面这张表对比了扩容时三种典型现象:

现象 可能原因 观察命令 处理方向
新节点分片数为 0 再平衡阈值未触发、磁盘水位高、过滤规则排除 _cat/allocation?v、_cluster/allocation/explain 检查水位线与过滤规则,必要时手动调整
分片一直 RELOCATING 恢复带宽不足、目标节点磁盘慢、并发恢复数低 _cat/recovery?v&active_only=true 提高并发恢复数,但不要超过磁盘承受能力
集群健康 yellow 转 red 主分片恢复失败、磁盘 flood 只读 _cluster/health、_cat/shards 先解除磁盘只读,再排查主分片

6. shard 恢复:先小后大,先主后副

分片恢复不是简单复制文件。Elasticsearch 的恢复过程大致是:

  1. 目标节点向主分片所在节点发起恢复请求。
  2. 源节点创建快照,把分段文件传输到目标节点。
  3. 目标节点接收文件、校验、写入本地磁盘。
  4. 目标节点重放 translog,补齐恢复期间的新写入。
  5. 分片进入 STARTED,开始对外服务。

这个过程决定了两个重要事实:恢复时间与分片大小正相关,但与恢复期间写入量也正相关。一个 50GB 的分片,如果恢复期间还有持续写入,translog 重放会拖长恢复时间。

你可以用 _cat/recovery 看到每个阶段的耗时:

bash 复制代码
GET _cat/recovery?v&active_only=true&h=index,shard,time,stage,source_node,target_node,files_percent,translog_ops_percent

字段 stage 常见值有 INIT、INDEX、TRANSLOG、FINALIZE、DONE。如果卡在 TRANSLOG,说明文件已传完,但在重放写入;如果卡在 FINALIZE,通常是目标节点在做最终校验和状态切换。

这里容易改错的地方是:不要为了加快恢复而无限提高并发 。恢复并发受节点磁盘 IO、网络带宽、JVM 堆影响。把 node_concurrent_recoveries 从 2 提到 8,可能导致正常查询超时,因为恢复线程和搜索线程抢 CPU 和 page cache。

7. 磁盘水位线:从根上决定能不能写

磁盘水位线是分配和写入的共同约束。它有三个级别:

水位线 默认值 作用 触发后的行为
low 85% 不再向该节点分配新分片 新分片去其他节点,可能不均衡
high 90% 尝试把分片移走 触发再平衡搬离,搬不动则一直尝试
flood 95% 索引变只读 写入失败,需要清理磁盘或调高水位线

水位线判断的是"磁盘使用率",不是"剩余空间"。在数据盘大小不同的集群里,这会导致小盘节点先触发 high,大盘节点还有空间却接不到分片。因此生产上建议让数据节点磁盘规格一致,或者按磁盘大小设置不同的水位线。

下面的命令可以查看各节点磁盘使用率和分片分布:

bash 复制代码
GET _cat/allocation?v&h=node,shards,disk.used_percent,disk.avail,disk.total
GET _cluster/settings?include_defaults=true&flat_settings=true | grep -E "disk.watermark"
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%"
  }
}

注意:调高水位线只是争取时间,不是解决方案。真正要做的是清理旧索引、扩容磁盘、或者把冷数据迁移到对象存储。

8. 用 allocation explain 定位卡点

当分片迟迟不分配时,Elasticsearch 提供了一个非常直接的排查工具:_cluster/allocation/explain。它会告诉你哪个 decider 返回了 NO,以及为什么。

假设你有一个未分配的分片,可以执行:

bash 复制代码
GET _cluster/allocation/explain
{
  "index": "orders-2024.06",
  "shard": 0,
  "primary": false
}

返回结果中会包含 can_allocate、allocate_explanation、node_allocation_decisions。如果 can_allocate 是 no,往下看 deciders 数组,找到 decision 为 NO 的项。常见输出包括:

  • disk threshold:磁盘超过 high 水位线。
  • same shard:目标节点已有同一分片。
  • filter:节点属性不匹配 index.routing.allocation.include/exclude。
  • concurrent rebalance:并发再平衡分片数已满。

这个工具的价值在于:它把"为什么不分配"从猜测变成证据。很多扩容抖动问题,最后都能在 explain 输出里找到一条明确的 decider 拒绝记录。

9. 完整示例一:用 Java 创建索引并观察分配

下面这个最小 Java 示例使用 Elasticsearch Java API Client,创建一个 3 主 1 副本的索引,并打印分片分布。它的目标是让你把"索引创建"和"分片分配"连起来。

前置环境:JDK 17、Maven、Elasticsearch 8.x 本地单节点或三节点集群。

xml 复制代码
<dependency>
  <groupId>co.elastic.clients</groupId>
  <artifactId>elasticsearch-java</artifactId>
  <version>8.13.0</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.0</version>
</dependency>
java 复制代码
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.cluster.HealthResponse;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;

public class CreateIndexAndCheckAllocation {
    public static void main(String[] args) throws Exception {
        RestClient restClient = RestClient.builder(
                new HttpHost("localhost", 9200, "http"))
                .build();
        RestClientTransport transport = new RestClientTransport(
                restClient, new JacksonJsonpMapper());
        ElasticsearchClient client = new ElasticsearchClient(transport);

        try {
            CreateIndexResponse response = client.indices().create(c -> c
                    .index("orders-2024.06")
                    .settings(s -> s
                            .numberOfShards("3")
                            .numberOfReplicas("1"))
                    .mappings(m -> m
                            .properties("orderId", p -> p.keyword(k -> k))
                            .properties("amount", p -> p.double_(d -> d)))
            );
            System.out.println("索引创建结果: " + response.acknowledged());

            HealthResponse health = client.cluster().health(h -> h
                    .index("orders-2024.06")
                    .waitForStatus(co.elastic.clients.elasticsearch._types.HealthStatus.Yellow));
            System.out.println("集群健康: " + health.status());
            System.out.println("活动分片: " + health.activeShards());
            System.out.println("未分配分片: " + health.unassignedShards());
        } catch (Exception e) {
            System.err.println("创建索引失败: " + e.getMessage());
        } finally {
            transport.close();
            restClient.close();
        }
    }
}

关键步骤是:先建立客户端连接,再创建索引并设置分片和副本,最后等待集群健康到 yellow 并打印分片统计。预期输出会显示 acknowledged=true,健康状态为 yellow,活动分片数为 3 或 6,未分配分片数取决于集群节点数。

容易改错的地方:如果本地只有一个节点,副本无法分配,waitForStatus(Yellow) 可能超时;如果集群是 green,waitForStatus 会直接返回。这个例子适合验证"主分片先分配、副本再分配"的顺序。

10. 完整示例二:用 Spring Boot 触发再平衡并记录状态

这个示例更贴近企业实践:Spring Boot 应用启动后,检查集群是否需要再平衡,并打印每个节点的分片数。它的目标是让你看到"应用侧如何观察扩容抖动"。

前置环境:Spring Boot 3.x、Elasticsearch Java API Client 8.x、一个至少两节点的集群。

java 复制代码
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.cat.NodesResponse;
import co.elastic.clients.elasticsearch.cat.ShardsResponse;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class EsAllocationProbeApplication {
    public static void main(String[] args) {
        SpringApplication.run(EsAllocationProbeApplication.class, args);
    }

    @Bean
    CommandLineRunner probe(ElasticsearchClient client) {
        return args -> {
            try {
                NodesResponse nodes = client.cat().nodes(n -> n
                        .h("name", "node.role", "disk.used_percent", "heap.percent"));
                System.out.println("节点状态:\n" + nodes.valueBody());

                ShardsResponse shards = client.cat().shards(s -> s
                        .h("index", "shard", "prirep", "state", "node")
                        .v(true));
                System.out.println("分片分布:\n" + shards.valueBody());
            } catch (Exception e) {
                System.err.println("探针执行失败: " + e.getMessage());
            }
        };
    }
}

关键步骤是:用 cat().nodes() 查看节点磁盘和堆使用率,用 cat().shards() 查看分片状态。预期输出中,如果新节点磁盘使用率低,但分片数为 0,说明再平衡还没有触发,或者被过滤规则排除。

容易改错的地方:cat().shards() 的 v(true) 是显示表头,不是"verbose"的意思;h() 里的字段名必须和 Elasticsearch 返回字段一致,否则会得到空列。这个示例适合放在运维探针或健康检查接口里,定时记录分片分布,帮助判断扩容后是否均衡。

11. 完整示例三:生产排障案例------磁盘水位线导致写入失败

这个案例不写完整 Java 类,而是给出一个可复现的排障流程。输入是"某个索引写入返回 403 或 cluster_block_exception",步骤和结果如下。

第一步,查看集群健康说明:

bash 复制代码
GET _cluster/health?level=indices

如果返回里出现 index.blocks.read_only_allow_delete,说明磁盘 flood 水位线已触发。

第二步,确认磁盘使用率:

bash 复制代码
GET _cat/allocation?v&h=node,shards,disk.used_percent,disk.avail,disk.total

找到 disk.used_percent 超过 95% 的节点。

第三步,临时解除只读:

bash 复制代码
PUT _all/_settings
{
  "index.blocks.read_only_allow_delete": null
}

第四步,清理旧索引或扩容磁盘,然后把水位线调回安全值。如果你只是临时调高水位线,要记录变更并在清理后恢复。

预期结果是写入恢复,但根因仍在磁盘。这个案例的边界是:解除只读不会自动清理磁盘,如果磁盘仍然超过 flood 水位线,下一次写入还会被阻断。

12. 设计取舍:均衡、恢复速度与写入延迟

分片分配与再平衡的取舍,本质上是三个目标的平衡:

目标 倾向配置 代价
均衡优先 提高并发再平衡、降低水位线 恢复占用网络和磁盘,写入延迟上升
恢复速度优先 提高 node_concurrent_recoveries 搜索和写入可能抢不到 CPU
写入稳定优先 降低并发恢复、保守水位线 扩容后均衡慢,热点可能持续

没有一组参数适合所有集群。判断依据是:你的集群是读多写少还是写多读少?扩容时能否接受短时延迟上升?数据节点磁盘是否一致?把这些条件写清楚,再决定参数。

一个实用原则是:先保证不触发 flood 水位线,再谈均衡。因为 flood 会让写入直接失败,而均衡只是"不够快"。在磁盘紧张的集群里,盲目提高再平衡并发,只会让磁盘更快被写满。

13. 常见误区

第一个误区:以为"加节点就会自动均衡"。实际上,再平衡受 decider 过滤和并发阈值约束,新节点可能因为过滤规则、水位线、分片数限制而接不到分片。

第二个误区:把 cluster_concurrent_rebalance 和 node_concurrent_recoveries 混为一谈。前者控制整个集群同时搬多少分片,后者控制单个节点同时恢复多少分片。两者影响的范围不同。

第三个误区:认为副本分片越多越安全。副本越多,写入要同步的节点越多,恢复时搬运的数据也越多。分片和副本数量要结合数据量、节点数和写入吞吐来定。

第四个误区:磁盘水位线只看剩余空间。Elasticsearch 默认按使用率百分比判断,不是按绝对值。小磁盘节点更容易触发 high 和 flood。

14. 生产实践建议

第一,保持数据节点磁盘规格一致。如果必须混用,按最小磁盘设置统一水位线,或者用 index.routing.allocation 把大索引绑定到大磁盘节点。

第二,扩容前先确认 _cat/allocation 里没有节点接近 high 水位线。否则新节点加入后,老节点仍在触发搬离,会和新节点接收分片叠加,造成更大抖动。

第三,给恢复留出带宽。在业务低峰期执行扩容,或者临时降低搜索负载。恢复和搜索共享 page cache,磁盘随机读会互相影响。

第四,用 _cluster/allocation/explain 做第一诊断工具。不要一上来就重启节点,重启会触发更多恢复,可能让问题更糟。

第五,监控分片分布和恢复队列。至少记录每个节点的分片数、磁盘使用率、_cat/recovery 中的活动恢复数。

15. 排障清单

当你遇到扩容抖动或分片不均衡时,按下面顺序检查:

  1. GET _cluster/health?level=indices:是否有 red 或 yellow,是否有只读块。
  2. GET _cat/allocation?v:各节点分片数、磁盘使用率是否异常。
  3. GET _cat/shards?v&h=index,shard,prirep,state,node:是否有长期 RELOCATING 或 UNASSIGNED。
  4. GET _cluster/allocation/explain:具体是哪个 decider 拒绝分配。
  5. GET _cluster/settings?include_defaults=true&flat_settings=true:再平衡、恢复、水位线配置是否被改过。
  6. GET _cat/recovery?v&active_only=true:恢复卡在哪个阶段。
  7. 检查节点日志中是否有 disk watermark、allocation decider、failed to relocate 关键字。

这张清单的顺序是"先看结果,再看原因,最后看配置和日志"。不要跳过第 4 步,它通常能直接给出答案。

16. 面试与复盘问题

  1. allocation decider 的返回值 NO、THROTTLE、YES 分别意味着什么?
  2. 为什么新节点加入后,分片不会立刻平均迁移?
  3. cluster_concurrent_rebalance 和 node_concurrent_recoveries 的区别是什么?
  4. 磁盘水位线的 low、high、flood 三个阶段分别会触发什么行为?
  5. 一个分片长期处于 RELOCATING,你会按什么顺序排查?
  6. 主分片恢复和副本分片恢复的先后关系是什么?
  7. 如何用 _cluster/allocation/explain 判断是磁盘问题还是过滤规则问题?
  8. 扩容时如何避免写入延迟飙升?

这些问题可以用于团队复盘,也可以用于面试中考察候选人对 Elasticsearch 集群行为的理解。

17. 总结

把整篇文章收回到一张框架图:

text 复制代码
触发事件
  |
  v
AllocationService 收集待分配分片
  |
  v
AllocationDecider 链过滤节点
  |  路由 / 磁盘水位 / 并发 / 过滤规则
  v
ShardsAllocator 权重排序
  |
  v
ClusterState 更新,分片进入 INIT / RELOCATING
  |
  v
节点执行 shard 恢复:先主后副,先小后大
  |
  v
再平衡持续调整,直到分布接近均衡

你需要记住三件事:第一,分片分配是"过滤 + 排序",不是简单的轮询;第二,扩容抖动通常来自并发恢复、磁盘水位线和过滤规则,而不是节点数量本身;第三,_cluster/allocation/explain 是定位分配问题的第一入口。

当你能把"谁在什么条件下做了什么、结果怎样"说清楚,Elasticsearch 的分片分配与再平衡就不再是黑盒,而是一套可以观测、可以调参、可以复盘的工程机制。

18. 参考资料

  1. Elasticsearch 官方文档:Cluster-level shard allocation and routing settings
  2. Elasticsearch 官方文档:Shard allocation filtering
  3. Elasticsearch 官方文档:Disk-based shard allocation
  4. Elasticsearch 官方文档:Cluster allocation explain API
  5. Elasticsearch 官方文档:Index recovery
  6. Elasticsearch 官方文档:CAT shards API、CAT allocation API、CAT recovery API
  7. Elasticsearch 官方文档:Java API Client
  8. 《Elasticsearch: The Definitive Guide》,Clinton Gormley、Zachary Tong 著
相关推荐
云风222 小时前
25亿条/小时管道踩坑实录:Hive桶表的4个暗坑,桶裁剪为何静默失效
大数据
FII工业富联科技服务3 小时前
2026年AI技术发展趋势分析:从模型能力突破到工业AI的真实应用
大数据·人工智能·深度学习·机器学习·制造·ai智能体·agentic ai
一隅论数智3 小时前
OWL(Web Ontology Language)介绍与使用举例(二)
大数据·经验分享·笔记·学习·自然语言处理·学习方法·政务
一木 之林3 小时前
DeepSeek Agent 开发(三)
java·大数据·linux
小码哥0684 小时前
Java医院陪诊系统陪护系统陪诊小程序,三端齐全可定制
大数据·小程序·陪诊陪护·陪诊小程序·陪护系统·陪诊系统·陪护小程序
赛博守夜人6 小时前
跨境业务与出海合规之八:面向海外合规监管突击搜查(Dawn Raid)的信息安全应急响应(IR)与合规取证
大数据·数据库
Elasticsearch6 小时前
使用 Lucene 搜索你的 beans —— Facets
elasticsearch
溪语流沙6 小时前
【Web全栈进阶】Alembic数据库迁移:改表结构不再删库
前端·数据库·python·elasticsearch·postgresql
你就是答案 -1486 小时前
2026 企业 AI 办公工具选型指南:匹配业务场景才是核心
大数据·人工智能