问题:为什么 Elasticsearch 中的段合并需要停止写入索引

我希望在 ES 最新版本中运行现在称为 forcemerge API 的优化(ES 1.X)。在阅读了一些文章后,例如这个和这个。似乎我们应该只在只读索引上运行它,引用官方 ES 文档:

只能针对只读索引调用强制合并。针对读写索引运行强制合并可能会导致生成非常大的段(每段>5Gb)

但我不明白

  1. 在运行 forcemerge 或优化 API 之前将索引设置为只读模式的原因。

  2. 正如上面的 ES 文档中所解释的,它可能会导致非常大的段,这不应该是我所理解的情况,新的更新首先写入内存中,当刷新发生时写入段,那么为什么在forcemerge 可以产生非常大的段吗?

如果我们不想将索引置于只读模式并仍然运行强制合并以删除删除,是否有任何解决方法。

如果我需要提供任何其他信息,请告诉我。

解答

forcemerge可以显着提高查询的性能,因为它允许您将现有数量的段合并为较少数量的段,这对于查询更有效,因为段是按顺序搜索的。合并时,所有标记为删除的文档也会被清理。

作为 Elasticsearch 基于合并策略的内务管理的一部分,合并会在后台定期自动进行。

棘手的事情是:合并策略只考虑最大 5 GB 的段。将 forcemerge API 与允许您指定结果段数的参数一起使用,您将面临结果段变得大于 5GB 的风险,这意味着将来的合并请求将不再考虑它们。只要您不删除或更新文档,就没有错。但是,如果您继续删除或更新文档,Lucene 会将现有段中的旧版本文档标记为已删除,并将新版本的文档写入新段中。如果您删除的文档位于大于 5GB 的段中,则不会对它们进行更多的内务处理,即标记为删除的文档将永远不会被清理。

通过在执行强制合并之前将索引设置为只读,您可以确保您最终不会得到包含大量遗留文档的巨大段,这会消耗内存和磁盘中的宝贵资源并减慢查询速度。

refresh正在做一些不同的事情:您想要索引的文档首先在内存中处理,然后再写入磁盘是正确的。但是,允许您实际查找文档(“段”)的数据结构不会立即为每个文档创建,因为这将非常低效。仅当内部缓冲区已满或发生refresh时才会创建段。通过触发刷新,您可以使文档立即可供查找。起初该段仍然只存在于内存中,因为 - 再次 - 在创建每个段后立即将其同步到磁盘将是非常低效的。内存中的段会定期同步到磁盘。即使您在同步到磁盘之前拔掉插头,您也不会丢失任何信息,因为 Elasticsearch 维护一个 translog,这将允许 Elasticsearch “重播”所有尚未进入磁盘段的索引请求。

Logo

欢迎大家访问Elastic 中国社区。由Elastic 资深布道师,Elastic 认证工程师,认证分析师,认证可观测性工程师运营管理。

更多推荐