Elasticsearch 扩展(第一部分):如何加快索引速度
Kenna Security是什么?
刷新间隔
批量处理
整理您的文件
回顾:加速大规模索引
提前规划
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
每个人都希望 Elasticsearch 集群的索引和搜索速度更快,但大规模优化这两项性能却并非易事。2015 年,Kenna 的集群存储了 5 亿份文档,我们每天处理 100 万份。当时,Elasticsearch 是我们基础设施中最不稳定的部分,随着数据量的增长,它几乎无法应对。如今,我们的集群存储了超过 40 亿份文档,每天轻松处理超过 3.5 亿份。
构建一个能够满足我们所有索引和搜索需求的集群并非易事。但凭借着坚持不懈的努力和几次“糟糕!”的惊险时刻,我们最终完成了任务,并且在此过程中积累了丰富的经验。在这篇分为两部分的博客中,我将分享我们在 Kenna 团队中使用的技术,正是这些技术让我们取得了今天的成就。不过,在深入探讨 Elasticsearch 的方方面面之前,我想先简单介绍一下 Kenna 公司。
Kenna Security是什么?
Kenna 帮助财富 500 强企业管理网络安全风险。平均每家公司拥有 6 万个资产。资产基本上是指任何拥有 IP 地址的设备。同时,平均每家公司还存在 2400 万个漏洞。漏洞是指攻击者可以利用的攻击手段。面对如此庞大的数据量,企业很难确定应该优先关注和修复哪些问题。而这正是 Kenna 的用武之地。在 Kenna,我们会收集所有这些数据,并运用我们独有的算法进行分析。这些算法会告诉客户哪些漏洞对其基础设施构成最大风险,从而帮助他们明确需要优先修复的问题。
我们最初将所有这些数据存储在 MySQL 数据库中,MySQL 是我们的数据来源。然后,我们将资产和漏洞数据索引到 Elasticsearch 中:
Elasticsearch 让我们的客户能够根据自身需求对数据进行各种切分和分析,因此搜索速度至关重要。同时,数据也在不断变化,所以索引也极其重要。
我们先来说说如何扩展索引容量。尽管起步艰难,但我们从一开始就做对了一件事,那就是设置刷新间隔。
刷新间隔
首先,什么是 Elasticsearch 刷新?Elasticsearch 刷新是指 Elasticsearch 清空其内存缓冲区,并将最近索引的数据提交到段中。提交到段实际上就是将数据写入磁盘。最初索引数据时,数据会像这样保存在缓冲区中:
然后,当页面刷新时,这些数据会被提交到某个细分市场,并可进行搜索。此过程如下图所示。
Elasticsearch 的刷新间隔决定了 Elasticsearch 执行刷新的频率。默认情况下,Elasticsearch 使用1 秒的刷新间隔。这意味着它每秒都会刷新一次缓冲区。刷新索引会占用大量资源,从而减少可用于索引的资源。加快索引速度最简单的方法之一是增加刷新间隔。增加刷新间隔可以减少执行的刷新次数,从而释放资源用于索引。我们将其设置为 30 秒。
我们的客户端数据更新由后台作业处理,因此等待额外 30 秒才能搜索数据并不会造成太大影响。如果 30 秒对您的使用场景来说太长,可以尝试 10 秒或 20 秒。大于 1 秒的延迟都能提升索引速度。
设置好刷新间隔后,一切都很顺利——直到我们接到第一个大客户。这个客户拥有 20 万个资产和超过 1 亿个漏洞。将数据导入 MySQL 后,我们开始将其索引到 Elasticsearch 中,但进展缓慢。索引工作持续了几天后,我们不得不告诉客户,索引所有数据需要两周时间。两周!😬 显然,这无法长期奏效。解决方案是批量处理。
批量处理
我们将它们归为一组,并使用批量请求一次性对它们进行索引。
我们发现,每次批量请求索引 1000 个文档可以最大程度地提升性能。批次大小取决于文档大小。有关如何找到最佳批次大小的技巧,请参阅Elastic 的批量处理建议。
单靠批量处理就足以支撑我们度过稳健增长的一年。然而,去年 MySQL 进行了重大升级,Elasticsearch 突然无法应对。在索引高峰期,节点 CPU 使用率会达到峰值,我们开始收到大量 429(请求过多)错误。
没错,这确实是我们节点在一次索引高峰期的屏幕截图!我们的集群无法处理我们试图塞入的海量数据,开始拒绝请求。在阅读了大量文档和搜索之后,我们突然意识到线程以及它们在索引中扮演的角色。这引出了我的最后一条建议:路由你的文档!
整理您的文件
在对一组文档进行索引时,完成请求所需的线程数取决于这些文档所属的分片数量。我们来看两批文档:
索引每个批次需要四个线程,因为每个线程都需要与四个分片通信。减少每次请求所需线程数的一个简单方法是按分片对文档进行分组。回到我们的例子,如果按分片对文档进行分组,就可以将执行请求所需的线程数减少一半。
看起来很简单,对吧?但是,如何知道一个文档应该放在哪个分片上呢?答案是路由。Elasticsearch 在确定将文档放在哪个分片上时,会使用以下公式:
路由值默认为文档本身_id,您也可以自行设置。如果您自行设置,则可以在索引文档时使用它。我们再来看一个例子。由于路由值与文档所属的分片相对应,我们可以利用这一点对文档进行分组,从而减少执行每个请求所需的线程数。
在 Kenna,资产和漏洞之间存在父子关系。这意味着父级(即 asset_id)用于路由。在对漏洞进行索引时,我们会按 asset_id 对其进行分组,以减少处理每个请求所需的线程数。
按文档的路由进行分组,使我们能够大幅提升索引速度,同时保持集群的稳定运行。
回顾:加速大规模索引
- 切换刷新间隔
- 批量处理文件
- 提交您的文件
提前规划
这些技术使 Kenna 能够每天处理超过 3.5 亿份文档,而且我们还有增长空间。当你的集群规模较小,处理的数据量也不大时,这些小的调整很容易被忽略。但是,随着规模的扩大,我保证这些技术将发挥至关重要的作用。提前规划并立即开始实施这些索引策略,以避免将来出现速度下降的情况。
现在,索引速度只是问题的一半。在 Kenna,搜索也是我们客户的首要关注点。在本篇博文的第二部分,我将深入探讨 Kenna 如何在扩展集群的同时提升搜索速度。
这篇博客最初发布在elastic.co上。
文章来源:https://dev.to/molly/scaling-elasticsearch-part-1-how-to-speed-up-indexing-2pel











