官方滚动重启的步骤如文档 Rolling Restarts 所述,很清晰,详细,不再赘述。
但在实际的过程中,会发现,即使禁止了分片路由的功能,节点重启后,重新加入集群,也需要较长的时间恢复,这跟自己想当然的情况不太一样。理论上,由于本地已经有了数据,重启后,应该可以直接从本地的数据中恢复分片,而不应该重新从主分片中拉取数据,而导致比较长的分片恢复时间。当然,这里并不是指所有的分片都需要从主分片中同步,有的分片恢复还是很快的。
Google 了下,发现有不少人有跟我类似的疑问,例如这里 Slow recovery during rolling cluster restarts。
Manual synced flush is worthless in some cases. The sync_ids will be overwritten when shards are marked as inactive, even if a synced flush was executed. This happens after 5 minutes (indices.memory.shard_inactive_time) by default, so it might be a lot quicker to wait for all indices to become inactive, instead of relying on synced flush.
从 issue 中的讨论中大概可以猜测,ES 判断能否从 local disk 恢复分片,可能是根据一个叫 sync_id 的东西,只要分片的这两个值,就会从主分片中同步,而不是从 local disk 中恢复。这也大概可以解释为什么建议重启前执行一次 /_flush/synced
,以及为什么主分片总是可以很快地恢复,只是副本恢复地很慢。
所以问题回到了为什么副本跟主分片的 sync_id 不一致?理论上执行了 /_flush/synced
之后,主从分片的 sync_id 应该是一致的(在停止了 index 的情况下)。issue 里面还提高了可能是 shard 在 indices.memory.shard_inactive_time
时间(默认 5m)后,被分为 inactive,自动 flush,产生新的 sync_id。道理还是有道理的,但是待确认。
另外有个题外的问题是,为什么 ES 做不到即使在 sync_id 不一致的情况下,也能增量恢复?就像 redis 那样,在一定的 offset 内,可以进行增量复制。或许是受限于底层的 Lucene 数据结构?Who knows!