Elasticsearch shrink操作需满足四条件:索引设为read-only、所有主分片active、新分片数为原数约数、原索引不可含routing_partition_size;执行时须用POST指定新索引名及shards数,且shrink后需验证数据一致性与分片状态。
Shrink前必须满足的硬性条件
Elasticsearch 的
操作不是“随时点一下就能缩”的通用功能,它对索引状态有强制约束。最常踩的坑是直接对活跃写入的索引执行 shrink,结果卡在
或更隐蔽的
错误。
目标索引必须处于
状态(通过
设置)
所有主分片(primary shards)必须是
,不能有正在恢复、relocating 或 unassigned 的分片
新索引的分片数必须是原索引分片数的
约数
(例如 12 → 6、12 → 4、12 → 3 都合法;12 → 5 不合法)
原索引不能使用
(即不能是 routing partitioned index)
实际操作中,建议先用
确认分片状态,再用
写入
—— 注意:这步不会阻断查询,只停写入。
执行 shrink 的标准请求结构与参数含义
是一个同步 API,但底层会触发分片合并和数据重分配,耗时取决于数据量。它的核心不是“复制”,而是把多个分片的数据重新组织进更少的分片里,所以新索引的每个分片实际承载更多数据。
请求路径中的
是新索引名,必须不存在,且符合 Elasticsearch 索引命名规则(小写、不能以
开头等)
必须在请求体
中显式指定,不能省略或从原索引继承
可以设为 0 临时加速(后续再用
调整),但要注意:shrink 过程中 replica 分片也会被重建,设太高会延长完成时间
不支持在 shrink 请求里改
或
,这些得在 shrink 完成后再单独操作
shrink 后常见数据异常与验证方式
shrink 成功返回
并不等于数据完整无误。最容易被忽略的是 routing 行为变化导致的查询结果偏差。
原索引若用了自定义
字段,shrink 后该字段仍生效,但分片数变少,相同 routing value 可能落到不同物理分片,
不影响正确性,但影响局部性
(比如原来某 user_id 总落在 shard 2,现在可能落在 shard 0)
使用
查不到数据?先检查是否忘了删掉原索引的
block:
数据量明显变少?大概率是原索引存在大量已删除文档(
doc),shrink 会跳过它们——这是正常行为,不是丢数据
验证是否真正收缩成功:对比
和
的行数,同时检查
的
是否与原索引一致
为什么不能 shrink 正在 rollover 的索引
滚动索引(rollover)本质是创建新索引并切换别名指向,而 shrink 要求源索引完全静止。如果在
还没关写就去 shrink 它,即使设置了
block,rollover 触发后别名可能已指向
,而你 shrink 的还是旧索引 —— 这会导致后续写入继续打到新索引,旧索引变成“僵尸”,没人管又没法删。
正确做法:确保 rollover 已完成、且旧索引明确进入只读归档阶段(比如按天 rollover 后,昨天的索引才允许 shrink)
如果用 ILM(Index Lifecycle Management),shrink 是一个独立 phase,必须放在
或
之前,且 ILM 会自动处理
block 和分片检查 —— 但前提是策略里
设置合理,别让 shrink 在 rollover 刚完成时就触发
shrink 看似简单,但依赖索引生命周期的精确控制。一旦在分片未完全稳定、或别名关系混乱时强行操作,轻则任务卡住,重则需要手动清理残留分片或重建索引。
shrinkblocked by: [FORBIDDEN/12/index read-only / allow delete (api)];all primary shards must be active and relocatingread-onlyindex.blocks.write=trueactiverouting_partition_sizeGET /my-index/_stats?level=shardsPUT /my-index/_settings{"index.blocks.write": true}shrink
POST /my-index/_shrink/my-index-shrunken
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
my-index-shrunken_number_of_shardssettingsnumber_of_replicasPUT /my-index-shrunken/_settingsmappingsaliases"acknowledged": true_routingGET /my-index-shrunken/_search?q=*writePUT /my-index/_settings {"index.blocks.write": null}deletedGET /my-index/_cat/shardsGET /my-index-shrunken/_cat/shardsGET /my-index-shrunken/_stats/docscountlogs-000001writelogs-000002freezedeletewritemin_age