PB 级大规模 Elasticsearch 集群运维
|
N 天后,架构师 A 直接在微信群里反馈:bellen, 客户反馈这边的 ES 集群性能不行啊,使用 logstash 消费 kafka 中的日志数据,跑了快一天了数据还没追平,这是线上的集群,麻烦紧急看一下吧。 我一看,一脸懵, 什么时候已经上线了啊,不是还在测试中吗? XX 公司运维 B: 我们购买了 8 核 32G*10 节点的集群,单节点磁盘 6TB, 索引设置的 10 分片 1 副本,现在使用 logstash 消费 kafka 中的数据,一直没有追平,kafka 中还有很多数据积压,感觉是 ES 的写入性能有问题。 随后我立即查看了集群的监控数据,发现 cpu 和 load 都很高,jvm 堆内存使用率平均都到了 90%,节点 jvm gc 非常频繁了,部分节点因为响应缓慢,不停的离线又上线。 经过沟通,发现用户的使用姿势是 filebeat+kafka+logstash+elasticsearch, 当前已经在 kafka 中存储了有 10 天的日志数据,启动了 20 台 logstash 进行消费,logstash 的 batch size 也调到了 5000,性能瓶颈是在 ES 这一侧。客户 8 核 32G*10 节点的集群,理论上跑 10w qps 没有问题,但是 logstash 消费积压的数据往 ES 写入的 qps 远不止 10w,所以是 ES 扛不住写入压力了,只能对 ES 集群进行扩容,为了加快存量数据的消费速度,先纵向扩容单节点的配置到 32 核 64GB,之后再横向增加节点,以保证 ES 集群能够最大支持 100w qps 的写入(这里需要注意的是,增加节点后索引的分片数量也需要调整)。 客户的游戏上线有一个月了,原先预估每天最多有 10TB 的数据量,实际则是在运营活动期间每天产生 20TB 的数据,原先 6TB*60=360TB 总量的数据盘使用率也达到了 80%。针对这种情况,我们建议客户使用冷热分离的集群架构,在原先 60 个热节点的基础上,增加一批 warm 节点存储冷数据,利用 ILM(索引生命周期管理)功能定期迁移热节点上的索引到 warm 节点上。 通过增加 warm 节点的方式,客户的集群磁盘总量达到了 780TB, 可以满足最多三个月的存储需求。但是客户的需求还没有满足: XX 公司运维老大:给我们一个能存放一年数据的方案吧,总是通过加节点扩容磁盘的方式不是长久之计,我们得天天盯着这个集群,运维成本很高!并且一直加节点,ES 会扛不住吧? bellen: 可以尝试使用我们新上线的支持本地盘的机型,热节点最大支持 7.2TB 的本地 SSD 盘,warm 节点最大支持 48TB 的本地 SATA 盘。一方面热节点的性能相比云盘提高了,另外 warm 节点可以支持更大的磁盘容量。单节点可以支持的磁盘容量增大了,节点数量就不用太多了,可以避免踩到因为节点数量太多而触发的坑。 XX 公司运维老大:现在用的是云盘,能替换成本地盘吗,怎么替换? bellen: 不能直接替换,需要在集群中新加入带本地盘的节点,把数据从老的云盘节点迁移到新的节点上,迁移完成后再剔除掉旧的节点,这样可以保证服务不会中断,读写都可以正常进行。 XX 公司运维老大:好,可以实施,尽快搞起来! 云盘切换为本地盘,是通过调用云服务后台的 API 自动实施的。在实施之后,触发了数据从旧节点迁移到新节点的流程,但是大约半个小时候,问题又出现了: XX 公司运维小: bellen, 快看一下,ES 的写入快掉 0 了。 然后再进一步查看集群日志,发现有"master not discovered yet..."之类的错误日志,检查三个 master 节点,发现有两个 master 挂掉,只剩一个了,集群无法选主。 登陆到挂了的 master 节点机器上,发现保活程序无法启动 es 进程,第一直觉是 es 进程 oom 了;此时也发现 master 节点磁盘使用率 100%, 检查了 JVM 堆内存快照文件目录,发现有大量的快照文件,于是删除了一部分文件,重启 es 进程,进程正常启动了;但是问题是堆内存使用率太高,gc 非常频繁,master 节点响应非常慢,大量的创建索引的任务都超时,阻塞在任务队列中,集群还是无法恢复正常。 看到集群 master 节点的配置是 16 核 32GB 内存,JVM 实际只分配了 16GB 内存,此时只好通过对 master 节点原地增加内存到 64GB(虚拟机,使用的腾讯云 CVM, 可以调整机器规格,需要重启),master 节点机器重启之后,修改了 es 目录 jvm.options 文件,调整了堆内存大小,重新启动了 es 进程。 3 个 master 节点都恢复正常了,但是分片还需要进行恢复,通过 GET _cluster/health 看到集群当前有超过 10w 个分片,而这些分片恢复还需要一段时间,通过调大"cluster.routing.allocation.node_concurrent_recoveries", 增大分片恢复的并发数量。实际上 5w 个主分片恢复得是比较快的了,但是副本分片的恢复就相对慢很多,因为部分副本分片需要从主分片上同步数据才能恢复。此时可以采取的方式是把部分旧的索引副本数量调为 0, 让大量副本分片恢复的任务尽快结束,保证新索引能够正常创建,从而使得集群能够正常写入。 总结这次故障的根本原因是:集群的索引和分片数量太多,集群元数据占用了大量的堆内存,而 master 节点本身的 JVM 内存只有 16GB(数据节点有 32GB), master 节点频繁 full gc 导致 master 节点异常,从而最终导致整个集群异常。所以要解决这个问题,还是得从根本上解决集群的分片数量过多的问题。 目前日志索引是按照小时创建,60 分片 1 副本,每天有 24*60*2=2880 个分片,每个月就产生 86400 个分片,这么多的分片可能会带来严重的问题。有以下几种方式解决分片数量过多的问题:
和客户沟通过后,客户表示可以接受方式 1 和方式 2,但是方式 3 和 4 不能接受,因为考虑到存在磁盘故障的可能性,必须保留一个副本来保证数据的可靠性;另外还必须保证所有数据都是随时可查询的,不能关闭。 场景 6:有点坑的 ILM
在上文中,虽然通过临时给 master 节点增加内存,抗住了 10w 分片,但是不能从根本上解决问题。客户的数据是计划保留一年的,如果不进行优化,集群必然扛不住数十万个分片。所以接下来需要着重解决集群整体分片数量过多的问题。前文也提到了,客户可以接受开启 shrink 以及降低索引创建粒度(经过调整后,每两个小时创建一个索引),这在一定程度上减少了分片的数量,能够使集群暂时稳定一阵。 (编辑:鹰潭站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

