《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.20.Refresh/flush(上) https://developer.aliyun.com/article/1229332
Elasticsearch 中的 flush
Flush 实质上意味着将内存缓冲区中的所有文档都写入新的 Lucene Segment,如下面的图所示。 这些连同所有现有的内存段一起被提交到磁盘,ES 6.7 之后,为了支持 CCR 跨集群复制,translog 默认会保留12小时。commit 本质上就是 Lucene commit。
Flush 会每30分钟定期触发,也可以在 Translog 达到 512MB 大小时触发。 这些设置可以防止 Lucene 提交带来的不必要的成本。
Segment 段合并
由于自动刷新流程每秒会创建一个新的段,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。 每一个段都会消耗文件句柄、内存和 CPU 运行周期。更重要的是,每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。
Elasticsearch 通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。
段合并的时候会将那些旧的已删除文档从文件系统中清除。被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。
启动段合并不需要你做任何事。进行索引和搜索时会自动进行。这个流程像在下图中表示的, “两个提交了的段和一个未提交的段正在被合并到一个更大的段” 中提到的一样工作:
1、当索引的时候,刷新(refresh)操作会创建新的段并将段打开以供搜索使用。
2、合并进程选择一小部分大小相似的段,并且在后台将它们合并到更大的段中。这并不会中断索引和搜索。
两个提交了的段和一个未提交的段正在被合并到一个更大的段
3、一旦合并结束,老的段被删除,说明合并完成:
l 新的段被刷新(flush)到了磁盘。 写入一个包含新段且除旧的和较小的段的新提交点。
l 新的段被打开用来搜索。
l 老的段被删除。
合并大的段需要消耗大量的 I/O 和 CPU 资源,如果任其发展会影响搜索性能。Elasticsearch 在默认情况下会对合并流程进行资源限制,所以搜索仍然 有足够的资源很好地执行。
Forcemerge 强制合并
forcemerge API 是强制合并 API。它会将一个分片强制合并到 max_num_segments 参数指定大小的段数目。 这样做的意图是减少段的数量(通常减少到一个),来提升搜索性能。
forcemerge API 不应该被用在一个正在被活跃使用或者一个正积极更新的索引。后台合并流程已经可以很好地完成工作。forcemerge 会阻碍这个进程。不要干扰它!
在特定情况下,使用 forcemerge API 颇有益处。例如在日志这种用例下,每天、每周、每月的日志被存储在一个索引中。 老的索引实质上是只读的;它们也并不太可能会发生变化。
在这种情况下,使用 forcemerge 优化老的索引,将每一个分片合并为一个单独的段就很有用了;这样既可以节省资源,也可以使搜索更加快速:
POST /my-index-000002/_forcemerge?max_num_segments=1
合并索引中的每个分片为一个单独的段
请注意,使用 forcemerge API 触发段合并的操作不会受到任何资源上的限制。这可能会消耗掉你节点上全部的 I/O 资源, 使其没有余裕来处理搜索请求,从而有可能使集群失去响应。如果你想要对索引执行 forcemerge,你需要先使用分片分配把索引移到一个安全的节点再执行,或者在业务低峰期执行。
《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.20.Refresh/flush(下) https://developer.aliyun.com/article/1229329