Elasticsearch 丢弃了太多请求——缓冲区会改善情况吗?
Elasticsearch drops too many requests -- would a buffer improve things?
我们有一个工作集群将索引请求发送到一个 4 节点 Elasticsearch 集群。文档在生成时被索引,并且由于工作人员具有高度并发性,Elasticsearch 在处理所有请求时遇到了麻烦。给一些数字,工作人员同时处理多达 3,200 个任务,每个任务通常会生成大约 13 个索引请求。这会生成每秒 60 到 250 个索引请求之间的瞬时速率。
从一开始,Elasticsearch 就有问题,请求超时或返回 429。为了解决这个问题,我们将工作线程的超时时间增加到 200 秒,并增加了 write
线程池队列大小节点到 700.
虽然这不是一个令人满意的长期解决方案,但我一直在寻找替代方案。我注意到,当我在与 elasticdump
相同的集群中复制索引时,write
线程池几乎是空的,我将其归因于 elasticdump
批量索引请求和(可能) 使用批量 API 与 Elasticsearch 通信。
这给了我一个想法,我可以编写一个缓冲区来接收来自工作人员的请求,将它们分成 200-300 个请求的一组,然后仅将一组请求发送到 Elasticsearch。
这样的事情是否已经存在,听起来是个好主意吗?
首先,重要的是要了解当您将索引请求发送到 Elasticsearch 时,幕后发生了什么,以解决问题或找到根本原因。
Elasticsearch 有 several thread pools 但对于索引请求 (single/bulk) 正在使用写入线程池,请根据您的 Elasticsearch 版本检查这一点,因为 Elastic 不断更改线程池(之前有一个单独的用于具有不同队列容量的单个和批量请求的线程池)。
在最新的ES版本(7.10)中,write threadpool的queue capacity从200大幅增加到10000(早期版本存在),可能有以下原因。
- Elasticsearch 现在更愿意缓冲更多的索引请求,而不是拒绝请求。
- 虽然增加队列容量意味着更多的延迟,但这是一种权衡,如果客户端没有重试机制,这将减少数据丢失。
我敢肯定,当容量增加时,您不会迁移到 ES 7.9 版本,但是您可以缓慢增加此队列的大小并通过配置更改轻松分配更多处理器(如果您有更多容量) this official example 中提到。虽然这是一个非常有争议的话题,很多人认为这是一个创可贴解决方案而不是正确的解决方案,但现在 Elastic 自己增加了队列大小,你也可以尝试一下,如果你增加的持续时间很短流量比它更有意义。
另一个关键的事情是找出你的 ES 节点排队更多请求的根本原因,它可以是合法的,比如增加索引流量和基础设施达到其限制。但如果它不合法,您可以查看我的简短提示以改进 one-time indexing performance and overall indexing performance,通过实施这些提示,您将获得更好的索引率,从而减少写入线程池队列的压力。
编辑:正如@Val 在评论中提到的,如果您也在一个接一个地索引文档,那么移动到 bulk index API 会给您最大的提升。
我们有一个工作集群将索引请求发送到一个 4 节点 Elasticsearch 集群。文档在生成时被索引,并且由于工作人员具有高度并发性,Elasticsearch 在处理所有请求时遇到了麻烦。给一些数字,工作人员同时处理多达 3,200 个任务,每个任务通常会生成大约 13 个索引请求。这会生成每秒 60 到 250 个索引请求之间的瞬时速率。
从一开始,Elasticsearch 就有问题,请求超时或返回 429。为了解决这个问题,我们将工作线程的超时时间增加到 200 秒,并增加了 write
线程池队列大小节点到 700.
虽然这不是一个令人满意的长期解决方案,但我一直在寻找替代方案。我注意到,当我在与 elasticdump
相同的集群中复制索引时,write
线程池几乎是空的,我将其归因于 elasticdump
批量索引请求和(可能) 使用批量 API 与 Elasticsearch 通信。
这给了我一个想法,我可以编写一个缓冲区来接收来自工作人员的请求,将它们分成 200-300 个请求的一组,然后仅将一组请求发送到 Elasticsearch。
这样的事情是否已经存在,听起来是个好主意吗?
首先,重要的是要了解当您将索引请求发送到 Elasticsearch 时,幕后发生了什么,以解决问题或找到根本原因。
Elasticsearch 有 several thread pools 但对于索引请求 (single/bulk) 正在使用写入线程池,请根据您的 Elasticsearch 版本检查这一点,因为 Elastic 不断更改线程池(之前有一个单独的用于具有不同队列容量的单个和批量请求的线程池)。
在最新的ES版本(7.10)中,write threadpool的queue capacity从200大幅增加到10000(早期版本存在),可能有以下原因。
- Elasticsearch 现在更愿意缓冲更多的索引请求,而不是拒绝请求。
- 虽然增加队列容量意味着更多的延迟,但这是一种权衡,如果客户端没有重试机制,这将减少数据丢失。
我敢肯定,当容量增加时,您不会迁移到 ES 7.9 版本,但是您可以缓慢增加此队列的大小并通过配置更改轻松分配更多处理器(如果您有更多容量) this official example 中提到。虽然这是一个非常有争议的话题,很多人认为这是一个创可贴解决方案而不是正确的解决方案,但现在 Elastic 自己增加了队列大小,你也可以尝试一下,如果你增加的持续时间很短流量比它更有意义。
另一个关键的事情是找出你的 ES 节点排队更多请求的根本原因,它可以是合法的,比如增加索引流量和基础设施达到其限制。但如果它不合法,您可以查看我的简短提示以改进 one-time indexing performance and overall indexing performance,通过实施这些提示,您将获得更好的索引率,从而减少写入线程池队列的压力。
编辑:正如@Val 在评论中提到的,如果您也在一个接一个地索引文档,那么移动到 bulk index API 会给您最大的提升。