当前位置: 首页 > 科技观察

说说大规模Elasticsearch集群管理

时间:2023-03-23 11:26:00 科技观察

ElasticSearch目前在互联网公司有两个应用场景。一是构建商务搜索功能模块,多在垂直领域搜索。数据量一般在千万级到数十亿级;二是用于大规模数据的实时OLAP,比如ELKStack,数据规模可能达到千亿甚至更多。这两个场景的数据索引和应用访问方式有很大不同,硬件选型和集群优化的侧重点也会不同。一般来说,后一种场景属于大数据范畴,数据量和集群规模更大,管理上的挑战更大。这里的家是携程网。从2013年开始接触ES开始,我们团队在0.9.x->5.0.0之间实践了各种版本。从最初分析IIS内部日志用于运维,到现在支持IT、呼叫中心、安全、测试、业务实时检索和分析来自研发等部门的200多种日志类数据。一路走来,大家都很开心,我自己也很开心。目前我们最大的日志单集群有120个数据节点运行在70台物理服务器上。数据规模:单日600亿条索引数据,新增索引文件25TB(50TB含一份),业务高峰期索引峰值速率维持在百万条/秒,保留历史数据时间根据业务需要确定,从10天到90天,集群共有3441个索引,17000个分片,总数据量约9300亿。总磁盘消耗为1PB。Kibana用户超过600人,每天来自Kibana和第三方API调用的查询总数为630,000响应时间百分位数75%:0.160s90%:1.640s95%:6.691s99%:14.0039s运维这么大规模的ES集群,有哪些需要注意的地方?一、必备工具工欲善其事,必先利其器。从一开始,即使只有几个节点,也应该使用分布式配置管理工具进行集群部署。随着应用的成熟和集群规模的逐步扩大,效率的提升将凸显。提供了官方的ESPuppetModule和ChefCookbook。熟悉这两个工具的同学可以直接使用。我们自己用了Ansible,写了一套Playbooks来达到类似的效果。如果熟悉此类工具,集群的初始部署、批量配置更改、集群版本升级、故障节点重启等都会更快更安全。第二个必备利器是sense插件。该插件直接调用集群的restfulAPI,在查看集群和索引的状态以及更改索引配置时非常方便。语法提示和自动补全功能更实用,减少翻阅文档的频率。在Kibana5中,sense变成了内置控制台,无需额外安装。2.硬件配置我们使用32vcoreCPU+128GBRAM的服务器。大部分服务器都是由12块4TBSATA机械盘组成的Raid0。冷热数据分离。后面讲集群架构的时候,我们会进一步说明如何使用硬件资源。3.集群管理首先,需要对ES节点的角色进行划分和隔离。我们都知道ES的数据节点除了存储数据外,还可以起到master和client的作用。大多数同学会将这些角色混合到数据节点中。但是,对于规模大、用户多的集群,在某些极端用例中,master和client可能会出现性能瓶颈甚至内存溢出,导致共存的数据节点失效。数据节点故障恢复涉及数据迁移,会消耗一定的集群资源,容易造成数据写入延迟或查询变慢。如果master和client分离,一旦出现问题,重启后几乎瞬间恢复,对用户几乎没有影响。另外,这些角色分离后,相应的计算资源消耗也从数据节点分离出来,更容易掌握数据节点资源消耗与写入查询量之间的关系,便于容量管理和规划。避免并发过多,包括控制分片和线程池的数量。在满足写入量和查询性能的前提下,为索引分配尽可能少的分片。太多的分片会带来很多负面影响,比如:每次查询后需要聚合和排序更多的数据;并发过多导致线程切换导致CPU消耗过大;索引删除和配置更新较慢问题#18776;太多的分片也会带来更多的小段,太多的小段会带来非常显着的堆内存消耗,尤其是在配置了很多查询线程的情况下。配置太大的线程池会导致很多奇怪的性能问题。Issue#18161中描述的问题是我们遇到的问题。默认的Theadpool大小通常工作得很好。冷热数据最好分开。对于日志类型的应用,一般每天都会创建一个新的索引,当天写热索引的时候查询会比较多。如果还有很久以前的冷数据,当用户查询大跨度的历史数据时,过多的磁盘IO和CPU消耗很容易导致写入变慢,造成数据延迟。所以我们使用一些机器来存储冷数据,使用ES为节点配置自定义属性,为冷节点添加"boxtype":"weak",每晚通过维护脚本更新冷数据索引路由设置index.routing.allocation。{require|include|exclude}允许数据自动迁移到冷节点。冷数据的特点是不再写入,用户查询频率低,但量级可能很大。比如我们有一个每天2TB的索引,用户要求保留过去90天的数据随时可用。保持如此大量的索引打开不仅会消耗磁盘空间。ES为了快速访问磁盘上的索引文件,需要在内存中存储一??些数据(索引文件的索引),也就是所谓的段内存。稍微熟悉ES的同学都知道JVM堆分配不能超过32GB。对于我们128GBRAM和48TB磁盘空间的机器,如果我们只运行一个ES实例,我们只能使用不到32GB的堆。当堆快要饱和的时候,磁盘上保存的索引文件还不到10TB,显然不经济。因此,我们决定在冷节点上运行3个ES实例,每个实例分配31GB的堆空间,这样一台物理服务器上就可以存储30多TB的索引数据,随时开放供用户查询。在实际使用中,由于冷数据搜索频率不高且没有写入,即使仅留35GB内存给OS缓存文件系统,查询性能也能满足需求。不同数据级别的分片最好隔离到不同的节点组。大家都知道ES会自己平衡集群中的分片分布。这种自动平衡的逻辑主要考虑三个因素。第一,同一个索引下的分片尽可能分布到不同的节点;第二,每个节点上的分片数量尽可能接近;第三,第三个节点的磁盘应该有足够的空闲空间。这种策略只能保证分片数量的均匀分布,不能保证数据大小的均匀分布。在实际应用中,我们有200多个索引,数据量差异很大。大的一天几TB,小的一个月才几GB,而且每种数据的保留时间差别很大。提出的问题是如何平衡和充分利用所有节点的资源。为了解决这个问题,我们仍然通过添加属性标签对节点进行分组,并结合索引路由控制来做一些细粒度的控制。对于不同量级的数据尽量使用不同的节点组,这样每组节点上的数据量更容易自动平衡。定期做indexforcemerge,最好每个shard合并成一个segment。前面说到heap的消耗也和segment的个数有关,forcemerge可以显着降低这个消耗。mergeintoasegment还有一个好处就是对于terms聚合来说,搜索的时候不需要构造GlobalOrdinals,可以提高聚合速度。4、版本选择我们长期稳定运行在2.4版本。比较保守的同学可以上2.4,激进有活力的同学可以考虑最新的5.0。我们的集群在两周前从v2.4.0升级到v5.0.0。除了升级第一周遇到的一个不稳定的问题外,我觉得新版本带来的以下特性还是值得升级的:,MemoryLock,VirtualMemory设置等,如果设置不正确,会拒绝启动并抛出异常。与其以错误的系统参数启动,导致日后出现性能问题,不如在启动失败时告知用户问题是一个很好的设计!索引性能得到改善。升级后,在同样的指标率下,我们可以看到CPU消耗明显下降。除了有助于提高索引率外,还会在一定程度上提高搜索率。新的数值数据结构,更小的存储空间,更快地计算范围和地理位置。InstantAggregation可以缓存用于像now-7d到now这样的范围查询聚合。实际使用后,效果明显。用户在Kibana上运行近一周的数据聚合,前两次刷新比较慢,之后几乎是瞬间刷新!更多保障集群稳定性的保护措施,例如限制一次搜索命中的分片数量,增强断路器功能,更好地防止集群资源被坏查询耗尽。升级第一周,我们的冷数据节点出现间歇性无响应的问题,所以我们发现了3个问题提交给官方:Issue#21595Issue#21612Issue#21611第一个问题确认为bug,后续会5.0.2repair中发布,另外两个暂时还不清楚根因,貌似只是在我们的应用场景中遇到的。幸运的是,我们已经找到了所有问题的规避措施。实施这些措施后,我们的集群在过去一周内已经恢复到之前2.4版本的稳定状态。5.建议没钱又没时间担心监控的就买官方的xpack。如果你有精力,可以使用ES的各种richstatsAPI,用熟悉的监控工具采集数据,可视化。监控指标这么多,最关键的有以下几类:各种Threadpool的使用情况,active/queue/reject可视化。判断集群是否有性能瓶颈,看业务高峰期各个队列是否很高,是否经常出现reject,基本就可以了如指掌。堆使用了JVM的百分比和旧GC的频率。如果oldGC频率高,多次GC后heapused%几乎没有下降,说明heap压力太大,需要考虑扩容。(也可能是查询或聚合有问题导致的,需要结合用户访问记录判断)。段内存大小和段数。当节点上存储的索引较多时,这两个指标值得关注。要知道段内存是一个常驻堆,不会被GC回收。因此,当堆压力过大时,可以通过这个指标来判断是否是因为节点上存储的数据过多,需要扩容。段的数量也很关键。如果小segment很多,比如几千个,即使segment内存本身不大,在搜索线程很多的时候也会消耗很多heap。一个segment会在线程本地记录状态信息,这块的堆内存开销与(segment数*线程数)有关。需要记录用户的访问记录。我们只对用户开放httpapi,预装一个nginx作为http代理,通过访问日志记录用户对第三方api的所有访问记录。通过分析访问记录,当集群出现性能问题时,可以快速找到问题的根源,对故障排除和性能优化有很大帮助。