怎么解析大规模Elasticsearch集群管理

65次阅读
没有评论

共计 4529 个字符,预计需要花费 12 分钟才能阅读完成。

这篇文章将为大家详细讲解有关怎么解析大规模 Elasticsearch 集群管理,文章内容质量较高,因此丸趣 TV 小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

ElasticSearch 目前在互联网公司主要用于两种应用场景,其一是用于构建业务的搜索功能模块且多是垂直领域的搜索,数据量级一般在千万至数十亿这个级别; 其二用于大规模数据的实时 OLAP,经典的如 ELKStack,数据规模可能达到千亿或更多。  这两种场景的数据索引和应用访问模式上差异较大,在硬件选型和集群优化方面侧重点也会有所不同。一般来说后一种场景属于大数据范畴,数据量级和集群规模更大,在管理方面也更有挑战。

目前我们最大的日志单集群有 120 个 data node,运行于 70 台物理服务器上。数据规模如下:

单日索引数据条数 600 亿,新增索引文件 25TB (含一个复制片则为 50TB)

业务高峰期峰值索引速率维持在百万条 / 秒

历史数据保留时长根据业务需求制定,从 10 天 ndash; 90 天不等

集群共 3441 个索引、17000 个分片、数据总量约 9300 亿, 磁盘总消耗 1PB

Kibana 用户 600 多人, 每日来自 Kibana 和第三方的 API 调用共 63 万次

查询响应时间百分位 75%:0.160s 90%:1.640s 95%:6.691s 99%:14.0039s

运维这样大规模的 ES 集群,有哪些值得注意的地方?

一. 必不可少的工具

工欲善其事必先利其器,从一开始,哪怕就只有几个 node,就应该使用分布式配置管理工具来做集群的部署。随着应用的成熟,集群规模的逐步扩大,效率的提升会凸显。  官方提供了 ES Puppet Module 和 Chef Cookbook,熟悉这两个工具的同学可以直接拿过来用。  我们自己则是采用的 Ansible,编写了一套 Playbook 来达到类似的效果。  用熟这类工具,对于集群的初始部署,配置批量更改,集群版本升级,重启故障结点都会快捷和安全许多。

第二个必备利器就是 sense 插件。通过这个插件直接调用集群的 restful  API,在做集群和索引的状态查看,索引配置更改的时候非常方便。语法提示和自动补全功能更是实用,减少了翻看文档的频率。在 Kibana5 里面,sense 已经成为一个内置的控制台,无需额外安装。

二. 硬件配置

我们采用的是 32vcoreCPU + 128GB RAM 的服务器,磁盘配置大部分服务器是 12 块 4TB  SATA 机械磁盘做的 Raid0,少部分机器是刚上了不久的 6 块 800GB SSD  raid0,主要目的是想做冷热数据分离,后面谈到集群架构的时候,再进一步解释一下如何利用硬件资源。

三. 集群的管理

首先很有必要对 ES 的结点做角色划分和隔离。大家知道 ES 的 data  node 除了放数据以外,也可以兼任 master 和 client 的角色,多数同学会将这些角色混入到 data  node。然而对于一个规模较大,用户较多的集群,master 和 client 在一些极端使用情况下可能会有性能瓶颈甚至内存溢出,从而使得共存的 data  node 故障。data  node 的故障恢复涉及到数据的迁移,对集群资源有一定消耗,容易造成数据写入延迟或者查询减慢。如果将 master 和 client 独立出来,一旦出现问题,重启后几乎是瞬间就恢复的,对用户几乎没有任何影响。另外将这些角色独立出来的以后,也将对应的计算资源消耗从 data  node 剥离出来,更容易掌握 data node 资源消耗与写入量和查询量之间的联系,便于做容量管理和规划。

避免过高的并发,包括控制 shard 数量和 threadpool 的数量。在写入量和查询性能能够满足的前提下,为索引分配尽量少的分片。分片过多会带来诸多负面影响,例如:每次查询后需要汇总排序的数据更多; 过多的并发带来的线程切换造成过多的 CPU 损耗; 索引的删除和配置更新更慢 Issue#18776;   过多的 shard 也带来更多小的 segment,而过多的小 segment 会带来非常显著的 heap 内存消耗,特别是如果查询线程配置得很多的情况下。  配置过大的 threadpool 更是会产生很多诡异的性能问题 Issue#18161 里所描述的问题就是我们所经历过的。  默认的 Theadpool 大小一般来说工作得很不错了。

冷热数据最好做分离。对于日志型应用来说,一般是每天建立一个新索引,当天的热索引在写入的同时也会有较多的查询。如果上面还存有比较长时间之前的冷数据,那么当用户做大跨度的历史数据查询的时候,过多的磁盘 IO 和 CPU 消耗很容易拖慢写入,造成数据的延迟。所以我们用了一部分机器来做冷数据的存储,利用 ES 可以给结点配置自定义属性的功能,为冷结点加上”boxtype”:”weak”的标识,每晚通过维护脚本更新冷数据的索引路由设置 index.routing.allocation.{require|include|exclude},让数据自动向冷结点迁移。  冷数据的特性是不再写入,用户查的频率较低,但量级可能很大。比如我们有个索引每天 2TB,并且用户要求保持过去 90 天数据随时可查。保持这么大量的索引为 open 状态,并非只消耗磁盘空间。ES 为了快速访问磁盘上的索引文件,需要在内存里驻留一些数据(索引文件的索引),也就是所谓的 segment  memory。稍微熟悉 ES 的同学知道,JVM heap 分配不能超过 32GB,对于我们 128GB RAM,  48TB 磁盘空间的机器而言,如果只跑一个 ES 实例,只能利用到 32GB 不到的 heap,当 heap 快用饱和的时候,磁盘上保存的索引文件还不到 10TB,这样显然是不经济的。  因此我们决定在冷结点上跑 3 个 ES 实例,每个分配 31GB heap 空间,从而可以在一台物理服务器上存储 30 多 TB 的索引数据并保持 open 状态,供用户随时搜索。  实际使用下来,由于冷数据搜索频率不高,也没有写入,即时只剩余 35GB 内存给 os 做文件系统缓存,查询性能还是可以满足需求的。

不同数据量级的 shard 最好隔离到不同组别的结点。  大家知道 ES 会自己平衡 shard 在集群的分布,这个自动平衡的逻辑主要考量三个因素。其一同一索引下的 shard 尽量分散到不同的结点; 其二每个结点上的 shard 数量尽量接近; 其三结点的磁盘有足够的剩余空间。这个策略只能保证 shard 数量分布均匀,而并不能保证数据大小分布均匀。  实际应用中,我们有 200 多种索引,数据量级差别很大,大的一天几个 TB,小的一个月才几个 GB,并且每种类型的数据保留时长又千差万别。抛出的问题,就是如何能比较平衡并充分的利用所有节点的资源。  针对这个问题,我们还是通过对结点添加属性标签来做分组,结合 index  routing 控制的方式来做一些精细化的控制。尽量让不同量级的数据使用不同组别的结点,使得每个组内结点上的数据量比较容易自动平衡。

定期做索引的 force merge,并且最好是每个 shard  merge 成一个 segment。前面提到过,heap 消耗与 segment 数量也有关系,force merge 可以显著降低这种消耗。  如果 merge 成一个 segment 还有一个好处,就是对于 terms aggregation,搜索时无需构造 Global  Ordinals,可以提升聚合速度。

四. 版本选择

我们在 2.4 版本上稳定跑了很长时间,比较保守的同学可以上 2.4,激进有精力折腾的可以考虑最新的 5.0。  我们集群两周前从 v2.4.0 升级到了 v5.0.0 这个版本,除了升级第一周遇到一个不稳定的问题以外,感觉新版本带来的以下特性还是非常值得去升级的:

结点启动的 Bootstrap 过程加入了很多关键系统参数设置的核验,比如 Max File Descriptors, Memory Lock, Virtual  Memory 设置等等,如果设置不正确会拒绝启动并抛出异常。与其带着错误的系统参数启动,并在日后造成性能问题,不如启动失败告知用户问题,是个很好的设计!

索引性能提升。升级后在同样索引速率下,我们看到 cpu 消耗下降非常明显,除了对索引速率提升有帮助,也会一定程度提升搜索速率。

新的数值型数据结构,存储空间更小,Range 和地理位置计算更快速

Instant Aggregation 对于类似 now-7d to  now 这样的范围查询聚合能够做 cache 了,实际使用下来,效果明显,用户在 Kibana 上跑个过去一周数据的聚合,头 2 次刷新慢点,之后有 cache 了几乎就瞬间刷出!

更多的保护措施保证集群的稳定,比如对一次搜索 hit 的 shard 数量做了限制,增强了 circuit  breaker 的特性,更好的防护集群资源被坏查询耗尽。

升级第一周,我们的冷数据结点出现间歇性不响应问题,从而刨出 3 个 issue 提交给官方:

Issue#21595 Issue#21612 Issue#21611

第一个问题确认为 Bug,将在 5.0.2 修复,其他两个目前还不清楚根源,看起来也只在我们的应用场景里遇到了。所幸问题都找到了了规避措施,实施这些措施以后,最近一周我们的集群重新回到以前 2.4 版本时期的稳定状态。

五. 监控

不差钱没空折腾的建议还是买官方的 xpack 省心,有精力折腾的,利用 ES 各种丰富的 stats api,用自己熟悉的监控工具采集数据,可视化出来就好了。  那么多监控指标,最最关键的还是以下几类:

各类 Thread pool 的使用情况,active/queue/reject 可视化出来。  判断集群是否有性能瓶颈了,看看业务高峰期各类 queue 是不是很高,reject 是不是经常发生,基本可以做到心里有数。

JVM 的 heap used% 以及 old GC 的频率,如果 old GC 频率很高,并且多次 GC 过后 heap  used% 几乎下不来,说明 heap 压力太大,要考虑扩容了。(也有可能是有问题的查询或者聚合造成的,需要结合用户访问记录来判断)。

Segment memory 大小和 Segment 的数量。节点上存放的索引较多的时候,这两个指标就值得关注,要知道 segment  memory 是常驻 heap 不会被 GC 回收的,因此当 heap 压力太大的时候,可以结合这个指标判断是否是因为节点上存放的数据过多,需要扩容。Segement 的数量也是比较关键的,如果小的 segment 非常多,比如有几千,即使 segment  memory 本身不多,但是在搜索线程很多的情况下,依然会吃掉相当多的 heap,原因是 lucene 为每个 segment 会在 thread  local 里记录状态信息,这块的 heap 内存开销和 (segment 数量 * thread 数量) 相关。

很有必要记录用户的访问记录。我们只开放了 http api 给用户,前置了一个 nginx 做 http 代理,将用户第三方 api 的访问记录通过 access  log 全部记录下来。通过分析访问记录,可以在集群出现性能问题时,快速找到问题根源,对于问题排查和性能优化都很有帮助。

关于怎么解析大规模 Elasticsearch 集群管理就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计4529字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)