社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Elasticsearch

携程:大规模 Elasticsearch 集群管理心得

高效运维 • 6 年前 • 872 次点击  


ElasticSearch 目前在互联网公司主要用于两种应用场景:

  • 其一是用于构建业务的搜索功能模块且多是垂直领域的搜索,数据量级一般在千万至数十亿这个级别;

  • 其二用于大规模数据的实时OLAP,经典的如ELKStack,数据规模可能达到千亿或更多。

这两种场景的数据索引和应用访问模式上差异较大,在硬件选型和集群优化方面侧重点也会有所不同。一般来说后一种场景属于大数据范畴,数据量级和集群规模更大,在管理方面也更有挑战。

应Medcl大大的邀请,为ES中文社区做今年的Advent开篇,分享一下我在管理自家公司用于日志分析的ES集群方面的一点心得,蜻蜓点水,泛泛而谈,希望大方向上能对大家提供一些帮助。

这里的自家,即是携程旅行网。从2013年开始接触ES,我们团队先后实践过0.9.x -> 5.0.0中间各个版本,从最初只用于运维内部IIS日志的分析,到如今支持IT、呼叫中心、安全、测试、业务研发等多个部门超过200种日志型数据的实时检索与分析。 一路走来,愉悦了大家,也死磕了自己。

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

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

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

  • 历史数据保留时长根据业务需求制定,从10天 - 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全部记录下来。通过分析访问记录,可以在集群出现性能问题时,快速找到问题根源,对于问题排查和性能优化都很有帮助。

最后就是多上手实践,遇到问题多查官方资料,多Google看是否有其他人遇到同类问题,精力充足有编程背景的同学也可以多刨刨源码。

本文转载自公众号「hadoop 技术学习」
原文链接:https://elasticsearch.cn/article/110


END


更多相关文章阅读

DevOps,就是开发吃掉运维?

硬盘什么时候坏?基于AI的科学算命告诉您

腾讯业务监控的修炼之路

微信月活9亿的高效运维之路

从鹿晗恋爱事件看运维的节假日准备工作

Linux Bash 提示符的一些骚操作

我们离 Google SRE 还有多远?

六个人如何运维一万台服务器?

运维需要懂的那些安全技能

运维的耻辱感



点击阅读原文关注大会官网


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/8iwufYNlqc
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/4001
 
872 次点击