本文主要讲解“如何在生产环境中运行弹性搜索”。本文的讲解内容简单明了,易学易懂。请跟随边肖的思路,学习学习“如何在生产环境中运行弹性搜索”。
基础知识:集群,节点,索引和分片
如果你是弹性搜索(ES)的新手,我想先解释一些基本概念。本节根本不涉及最佳实践,而是重点解释术语。大多数人可以直接跳过这一部分。
Elasticsearch是一个运行Apache Lucene(基于Java的搜索引擎)的分布式管理框架。Lucene是数据实际保存、索引和搜索的地方。最重要的是,ES允许您并行运行数千个Lucene实例。
ES的最高级别单位是集群。是ES节点和索引的集合。
节点是专家系统的一个实例。它可以是单个服务器,也可以是服务器上运行的一个专家系统进程。与服务器不同,虚拟机或物理服务器可以包含许多专家系统进程,每个专家系统进程都是一个节点。一个节点只能加入一个集群。有不同类型的节点,其中最值得注意的两种类型是数据节点和主合格节点。一个节点可以同时有多种类型。数据节点运行所有数据操作,即存储、索引和检索数据。候选节点有权投票给主节点,用于管理集群和索引。
索引是数据的高级抽象。索引本身并不存储数据,但它们只是实际存储数据的另一种抽象。对数据执行的任何操作(如插入、删除、索引和搜索)都会对索引产生影响。索引可以完全属于一个集群,并且由碎片组成。
Shard是Apache Lucene的一个实例。一个切片可以容纳许多文档。碎片化是数据存储、索引和搜索的实际对象。片段只属于一个节点和索引。有两种类型的碎片:主碎片和副本碎片,它们基本相同并且具有相同的数据,并且搜索在所有碎片上并行运行。在所有具有相同数据的切片中,有一个属于主切片。这是唯一可以接受索引请求的片。如果节点中的主切片挂起,副本将接管并成为主切片。然后,ES将创建一个新副本并复制数据。
综上所述,我们整理出如下图:
更深入了解 Elasticsearch
如果你想运行一个系统,我相信你需要了解这个系统。在这一部分,我将解释弹性搜索的每个部分。如果你想在生产中管理,我相信你需要了解它。这一部分也不涉及具体建议,后面会介绍。这个节目的目的只是介绍必要的背景。
Quorum
理解弹性研究是一个(有缺陷的)选举系统非常重要。节点投票决定谁来管理它们,也就是主节点。主节点运行大量的集群管理进程,并在许多事务中拥有最终决策权。ES选举是有缺陷的,因为只有少数节点,即符合主节点资格的节点,拥有投票权。主节点通过以下配置启用:
node.master: true
当集群启动或主节点离开集群时,所有满足主选举条件的节点将开始选举新的主节点。为此,您需要有2n 1个主要候选节点。否则,可能会出现大脑分裂。例如,如果两个节点同时获得50%的投票,两个分区之一中的所有数据都将丢失。为了不发生。您需要2n个1节点来匹配主要候选节点。
节点如何加入集群
当ES节点启动时,它独自存在于广阔的世界中。它如何知道自己属于哪个集群?有不同的方法来完成这个操作,现在大多数都使用种子宿主的方法。
基本上,Elasticsearch节点将不断地与他们所看到的所有其他节点进行通信。因此,一个节点最初只需要知道其他几个节点就可以知道整个集群。让我们看一个三节点集群的例子:
初态
起初,节点a和c只知道b. B是种子主机。种子主机或者以配置文件的形式提供给专家系统,或者直接放在elasticsearch.yml.
节点a
与 B 连接并交换信息
一旦节点 A 连接到 B,B 就知道 A 的存在。对于 A 而言,没有任何变化。
节点 C 连接并与 B 共享信息
现在,C 连上来。一旦发生这种情况,B 就会告诉 C 有 A 的存在。C 和 B 现在知道群集中的所有节点。一旦 A 重新连接到 B,它也将了解 C 的存在。
段和段合并
上面我说过数据存储分片中,这只是部分正确。最终数据是以文件的形式存储在文件系统中。在 Lucene 和 Elasticsearch 中,这些文件称为段(Segment)。一个分片将具有一到数千个段。
同样,段是实际的真实文件,你可以在 Elasticsearch 安装的 data 目录中查看它。这意味着使用段存在开销。如果要查看段,则必须找到文件并打开它。这意味着需要打开许多文件,并且将会有很多开销。Lucene 中的段是不可变的,这是个问题。它们只能写一次,然后就不能改了。反过来,这意味着你放入 ES 中的每个文档都将创建一个仅包含这个文档的段。显然,一个拥有十亿个文档的集群具有十亿个段,这意味着文件系统上确实有十亿个文件,这样理解对吗?非也。
在后台,Lucene 进行持续的段合并,它不能更改段,但是可以使用两个较小段的数据合并创建新的段。
这样,lucene 会不断尝试使段数(文件数,即开销)保持较小。你也可以使用强制合并。
消息路由
在 Elasticsearch 中,你可以对集群中的任何节点运行任何命令,返回结果是相同的。有趣的是,文档最终将只存在于一个主分片及其副本中,而 ES 不知道它在哪里。没有一个映射来记录某个文档位于哪个分片中。
当执行搜索时,获取请求的 ES 节点会将其广播到索引中的所有分片。即主分片及所有副本。这些分片然后会在包含该文档的所有段中进行查找。
当执行插入时,ES 节点将随机选择一个主分片并将文档放在其中。然后将其写入该主分片及其所有副本。
如何在生产环境运行 Elasticsearch?
本节是实践部分。我前面提到,我管理 ES 的主要目的是为了记录日志,本文将尽力避免这种倾向的影响,但有可能会失败。
大小
需要提出并随后回答自己的第一个问题是关于大小调整。你需要多少规模的 ES 集群?
内存
我首先说的是 RAM,因为 RAM 将限制所有其他资源。
堆
ES 用 Java 编写,Java 使用堆,你可以将其视为 Java 保留的内存。如果将所有堆的重要因素都列出,会使这个文档的大小增加三倍,所以我将介绍最重要的部分,即堆大小。
尽量使用更多内存,但堆大小不得超过 30G。
有一个很多人都不知道的关于堆的秘密:堆中的每个对象都需要一个唯一的地址,即一个对象指针。该地址的长度是固定的,这意味着可以寻址的对象数量是有限的。简单一点来描述就是,超出某个范围时,Java 将开始使用压缩的对象指针而不是未压缩的对象指针。这意味着每个内存访问都将涉及其他步骤,这会严重拖慢速度。因此你 100% 不需要设置超过此阈值(大约 32G)。
我曾经整整一个星期都呆在一个黑暗的房间里,没做别的,只是使用 esrally 基准化测试 Elasticsearch 在不同文件系统、堆大小、文件和 BIOS 设置组合。长话短说,下面就是关于堆大小如何设置的内容:
添加索引延迟,越低越好
命名约定为 fs_heapsize_biosflags。如你所见,从 32G 的堆大小开始,性能突然开始变差。吞吐量也同样情况:
索引附加中值吞吐量。越高越好。
长话短说:如果想幸运一点,请使用 29G 或 30G 的 RAM,并使用 XFS,并尽可能启用 hardwareprefetch 和 llc-prefetch。
文件缓存
大多数人在 Linux 上运行 Elasticsearch,Linux 使用内存作为文件系统缓存。常见的建议是 ES 服务器使用 64G 内存,这样的想法是一半用于缓存,一半用于堆。我尚未测试过文件缓存。但是不难看出,大型 ES 集群(如用于日志记录)可以从配置大文件缓存中受益匪浅。如果你所有的索引都适合放入内存堆,则不会那么多好处。
CPU
这取决于对集群执行的操作。如果进行大量索引,与仅执行日志记录相比,你需要更多更快的 CPU。对于日志记录,我发现 8 个 CPU 核绰绰有余,但是发现很多人使用更大的配置,但是对他的使用场景并没有什么好处。
磁盘
这块也没有想像那么直接。首先,如果索引能放入 RAM,则磁盘仅在节点冷启动时才重要。其次,实际可以存储的数据量取决于索引布局。每个分片都是一个 Lucene 实例,它们都有内存需求。这意味着你可以在堆中容纳最大数量分片是有限的。我将在索引布局部分中详细讨论这一点。
通常,你可以将所有数据磁盘放入 RAID0。你需要在 Elasticsearch 级别进行复制,因此丢失一个节点无关紧要。请勿将 LVM 与多个磁盘一起使用,因为 LVM 一次只能写入一个磁盘,根本就不会带来多个磁盘的好处。
关于文件系统和 RAID 设置,我整理了以下几点:
-
Scheduler:cfq 和 deadline 优于 noop。如果你有 nvme,Kyber 可能会很好,但我还没有测试过
-
QueueDepth:尽可能高
-
预读:请打开
-
Raid chunk size:无影响
-
FS 块大小:无影响
-
FS 类型:XFS > ext4
索引布局
这在很大程度上取决于你的用例。我只能从日志场景(尤其是使用 Graylog)讨论一下。
分片
精简版:
-
对于写入繁重的工作负载,主分片 = 节点数
-
对于读取繁重的工作负载,主分片 * 副本数 = 节点数
-
更多副本 = 更高的搜索性能
可以通过以下公式给出最大写入性能:
node_throughput * number_of_primary_shards 节点吞吐量 * 主分片数量
节点吞吐量 * 主分片数量
原因很简单:如果只有一个主分片,那么写入速度只类似于单节点,因为一个分片只能位于一个节点上。如果确实想优化写入性能,则应确保每个节点上只有一个分片(主节点或副本),因为在此情况下副本可以获得与主节点相同的写入速度,并且写入很大程度上取决于磁盘 IO。注意:如果有很多索引,那么上述的策略可能有问题,性能瓶颈可能是其他原因。
如果要优化搜索性能,可以通过以下公式给出:
node_throughput * (number_of_primary_shards + number_of_replicas) 节点吞吐量 *(主分片数量 + 副本数)
节点吞吐量 *(主分片数量 + 副本数)
对于搜索,主分片和副本基本相同。因此,如果想提高搜索性能,只需增加副本的数量。
大小
关于索引大小,我已经多次讨论过。以下是我的经验:
30G of heap = 140 shards maximum per node 30G 堆内存 = 可以在一个节点最多启动 140 个分片
使用 140 个以上的分片,Elasticsearch 就会进程崩溃并出现内存不足错误。这是因为每个分片都是 Lucene 实例,并且每个实例都需要一定数量的内存。这意味着每个节点可以拥有的分片数量是有限制的。
如果你有大量节点,分片和索引大小,则可以容纳多少个索引可以由以下公式计算:
number_of_indices = (140 * number_of_nodes) / (number_of_primary_shards * replication_factor) 索引数 = (140*节点数)/(主分片数 * 复制因子)
根据磁盘大小,可以很容易地计算出索引的大小:
index_size = (number_of_nodes * disk_size) / number_of_indices 索引大小 = (节点数量 * 磁盘大小)/ 索引数量
然而索引越大搜索越慢。对于日志记录来说,慢一点问题不大,但是对于真正的搜索量大的应用程序,应该根据 RAM 大小来调整索引大小。
段合并
每个段都是文件系统中的一个实际文件,更多的段意味着更大的读取开销。基本上,对于每个搜索查询,它都会转到索引中的所有分片,再转到分片中的所有段。多个段极大地增加集群读取 IOPS,直到它变得不可用。因此,需要尽可能减少段的数量。
force_merge API 允许你将段合并到某个数量,比如 1。如果你执行索引滚动(例如使用 Elasticsearch 做日志记录),那么在集群未使用时执行常规强制合并是一个好建议。强制合并会占用大量资源,并且会显著降低集群的运行速度。因此,最好不要让 Graylog 帮你来做,而是选择在较少使用集群时间自己完成。如果你有很多索引的话,你必须定期执行段合并。否则,集群运行速度将会非常慢并最终挂掉。
集群布局
对于除最小设置外的所有设置,最好使用专用的候选主节点。主要原因是确保始终有 2n + 1 个候选主节点来确保仲裁。但是对于数据节点,可以在任何时候添加新节点,而不必担心这个需求。另外,我们不希望数据节点上的高负载影响主节点。
最后,主节点是种子节点的理想候选节点。请记住,种子节点是在 Elasticsearch 中进行节点发现的最简单方法。由于主节点很少更改,因此它是最佳选择,因为它很可能已经知道集群中的所有其他节点。
主节点可以非常小,一个 CPU 核,4G 的 RAM 已经足够大多数集群使用。当然也需要关注实际使用情况,并进行相应调整。
监控
ES 为你提供了大量的指标,并且以 JSON 的形式提供所有指标,这使得传递给监控工具非常容易。以下是一些有用的监控指标:
-
段数
-
堆使用
-
堆 GC 时间
-
平均 搜索,索引,合并时间
-
IOPS
-
磁盘利用率
感谢各位的阅读,以上就是“怎么在生产环境运行Elasticsearch”的内容了,经过本文的学习后,相信大家对怎么在生产环境运行Elasticsearch这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/67433.html