ITPub博客

首页 > 数据库 > 数据库开发技术 > LinKedIn YARN集群10000节点性能优化实战

LinKedIn YARN集群10000节点性能优化实战

原创 数据库开发技术 作者:BigData之路 时间:2022-03-14 18:00:00 0 删除 编辑

前言

目前Yarn在小米大数据体系下担任着非常重要的角色,小米集团内部最大的一个Yarn集群已经接近6K节点的规模,并且呈快速增长趋势,最近的一些Case表明,在不久的将来我们就会触摸到单集群的调度性能的天花板。

恰巧最近看到了LinkedIn的文章,挺有借鉴价值的。顺便也来练练下我蹩脚的英文。

今天我们先分享一下,看看LinkedIn在Yarn集群接近10000个节点的时候,如何解决集群调度性能变慢的问题。



LinkedIn Hadoop介绍

在LinkedIn内部,使用Hadoop作为大数据分析与机器学习的底座,公司的整体数据量呈指数级的趋势增长,公司在机器学习和数据科学方面进行了大量投资,为了匹配计算工作负载的增长,我们的集群规模每年会翻一番,目前最大的集群约10000个节点,可能是地球上最大的的Hadoop集群之一。Hadoop YARN的扩容性已成为我们基础设施多年来最具挑战性的任务。

YARN集群遇到了问题

相比分布式文件存储HDFS的Namenode来说,YARN的元数据存储在一个独立的节点上,而YARN的resourcemanger非常的轻量,只维护了少量的元数据。我们在HDFS碰到的扩展性问题比YARN更早,早在2016年就开始在HDFS的扩展性上投资了,但Hadoop的计算组件YARN,在很长时间,一直是我们的基础服务中非常稳定的一部分。

我们的集群每年增长2倍,我们知道迟早有一天YARN的扩展性会成为一个问题,resourcemanager单线程调度的性能是无法维持无限增长的,尽管如此,我们从来没有在了解YARN的扩展性上花费精力,并且一直假设他可以持续服役直到下一个技术诞生。这样的做法一直持续到2019年年初。

历史上我们在其中一个数据中心部署了两个Hadoop集群,主力集群服务于主流量的业务,并且存储和计算资源都是绑定到一起的。第二集群主要是存储使用,而计算资源被闲置了,为了提高资源利用率,我们将第二个集群中的计算节点作为一个独立的分区(实际上就是标签调度),合并到主力集群中。

不幸的是,两个月后集群开始出现问题。

现象

在合并计算节点后,集群中有两个分区,一个约4000节点(主力集群),另一个约2000节点(第二集群),Hadoop集群的用户在作业提交运行之前碰到小时级别的延迟,然而整个集群的可用资源非常充足。

当我们在找延迟原因的时候,我们最开始怀疑是Hadoop YARN在处理分区的时候有Bug,但是我们在debug排查那块代码后并没有发现任何问题。我们怀疑集群规模增加了50%的导致resourcemanager过载了,致使调度性能跟不上。

我们仔细查看了队列的AggregatedContainerAllocation,他的含义是container分配的速度。在节点合并之前,主集群的container平均分配吞吐在500个每秒,次集群是250个每秒。合并之后到达了600个每秒,但是分配速度经常降到50个container每秒,并持续几个小时

我们进行了几轮分析,发现了一些成本高昂的操作,比如DNS部分,因为标记了 @synchronized注释,导致限制了并发。在我们将这些操作移除出了同步阻塞后,我们观察吞吐提升了10%,但是对用户来说延迟的情况依旧很明显。

重新定义公平来减轻压力

在解析resourcemanager的审计日志后,我们注意到调度器在切换到其他队列之前,经常调度container到一个独立的队列中并持续很长时间。甚至在性能正常的时候(600container每秒),一些队列上的用户依然会面临小时级别的延迟,而其他队列上的用户却没有感知到任何延迟。一些队列container分配的速度是正常的,但是对于其他队列却几乎已经下降到0。这个现象让我们再次关注到调度器如何决定哪一个队列优先去调度container。在LinkedIn内部,我们使用容量调度器,并基于使用率进行排序,率先分配container给低利用率的队列。

假设我们有两个队列A和B,A队列10%的利用率,B队列20%的利用率。调度器在向队列B服务之前之前会先向队列A调度container。在大多数的场景下都是这么工作的。然而,在container高速流失的环境下会产生一个短暂的死锁。比方说B队列中运行的都是时间长的作业,A队列运行的都是时间非常的短的作业。当队列A的使用率仅有10%时,container将会被调度到A而不是B,因为队列A的container流失率比队列B的高,调度器在队列A上完成一整次的调度工作之后。队列A的利用率保持不变甚至下降。但依然比队列B使用率低,比如9.5%。此时队列B的利用率小幅下降到19%。在队列A的利用率超过B之前,调度工作是不会在队列B上进行的。这也就导致队列有着不同的负载特征。从观察到的点上看,调度器一直在队列A进行资源调度,但队列B上却处于资源匮乏的状态。

我们也在问自己为什么在两个集群合并之后才遇到问题。因为主分区上的队列包括AI训练和数据分析,并且都是长时间运行的Spark作业,次分区队列中运行的是container流失率快的MapReduce作业,如果resourcemanager可以任意的调度container,它就不会是个问题。集群合并之后明显降低了调度速度,调度公平性的问题浮出水面。

我们采取的缓解办法是在调度器分配container的时候,以相等的概率选择队列。换言之,我们随机的选择队列而不是基于使用率的。我们的问题得到了临时的缓解,我们也将这个patch贡献给了Apache Hadoop。

效率低的根本原因

虽然队列公平性的问题得到了缓解,但是调度缓慢的根本原因还没有解决。我们知道YARN集群的扩展性仍旧是一个迫在眉睫的问题,需要进行深入的挖掘。

我们在回看一下集群合并前后的调度吞吐,最好的情况下我们拥有80%的性能,大约调度600个container每秒。最坏的场景下只有7%的性能,大约调度50个container每秒,巨大的差距让我们重新看了分区的调度逻辑,其中的不规则问题引发了我们的注意。

默认情况下,YARN的resourcemanager是同步调度的,伴随着nodemanager向resourcemanager的心跳,会触发调度调度器在该节点上分调度未分配的container。这时未分配的container被调度到主分区或者次分区上。如果container的分区和节点的分区不一致(也就是说该节点不在label内),则该container将不会分配到对应节点上。

当向队列调度任务时,调度器会按照先进先出的顺行进行调度。现在假设主分区的中的一个节点向resourcemanager进行心跳。调度器选择队列A进行调度,队列A中前面100个未完成的作业向次分区申请资源,我们发现调度器尝试将这些任务的container去匹配节点非常低效,尽管匹配经常失败。两个分区的都是负载很高的,这也给每次心跳带来了非常大的开销 ,进而导致缓慢。

为了应对这个挑战,我们优化了逻辑,如果一个主分区或者次分区中的节点向resourcemanager发送心跳。调度器在调度的时候会考虑任务提交到主分区还是次分区。在改变之后,我们观察到在集群合并前后平均吞吐是相同的。并且在两个分区都是繁忙状态的最坏情况下性能提升了9倍。我们同样把这个patch贡献给了社区。

下一篇我们看下LinkenIn在扩展性上还做了哪些努力。

译自<https://engineering.linkedin.com/blog/2021/scaling-linkedin-s-hadoop-yarn-cluster-beyond-10-000-nodes>




「原创推荐」


「好文推荐」
「最佳实践」


你的支持是我写作的动力。可以加我好友进入「交流群」,谈技术、说职场、聊聊生活感悟。关注公众号更有大数据学习资料链接,「上百本大数据电子书」 && 「3000G学习视频」等着你!



欢迎关注公众号 加我好友
大数据之路上 携手前行



原文作者:BigData之路;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2018-04-22

  • 博文量
    24
  • 访问量
    8859