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

B站线下多机房架构实践_0

时间:2023-03-12 06:28:28 科技观察

01背景随着B站业务的快速发展,业务数据的生产速度越来越快,线下集群规模迅速扩大。可预见的不久的将来,机房容量将达到上限,阻碍业务的发展。因此,如何解决单个机房的容量瓶颈成为了亟待解决的问题。目前业界针对机房容量问题主要有两种解决方案:1)整个集群迁移到更大容量的机房(scaleup)。本方案为垂直扩容方案,即将现有集群迁移至容量更大的机房,为集群扩容提供空间。现实中,集群迁移一般不会影响业务发展,即不保证宕机。因此在迁移过程中,需要两个规模相近的集群进行全量迁移,或者需要一个具有一定规模的过渡集群进行批量迁移;对于大型集群来说,迁移的经济成本是巨大的;此外,迁移后的新机房将面临再次达到容量上限的风险。2)多机房方案(scaleout),即一个机房容量有限,扩展为多个机房。同时对现有架构进行修改,保证用户视角依然是机房。这可以根据业务需求,采用灵活的方式增量扩容,从而在一定程度上避免容量冗余的问题。但该方案会存在跨机房的数据交互,一般存在机房网络带宽瓶颈;同时,网络抖动或网络断开可能导致跨机房服务异常。因此,该方案需要考虑/解决网络带宽不足的影响和网络抖动/掉线问题,技术成本高于整体集群迁移方案。就我们目前的自建机房而言,中短期内没有清理现有机房(全部搬迁到新机房)的计划,长期会有多个机房;另外,相对于方案2的技术成本,我们更难以接受方案1的经济成本和容量风险。因此,方案2是我们解决机房容量问题的首选。02多机房解决方案2.1面临的问题如上所述,多机房解决方案面临带宽等网络问题,多机房解决方案的设计受其制约。带宽瓶颈离线场景主要是批处理场景,是对海量历史数据进行离线分析/处理的场景。该场景对时延不敏感,但由于处理的数据量巨大,会消耗大量网络带宽等资源;另外,生产场景中的job数量普遍较多,执行时间不受控制。如果将两个机房内的主机简单叠加在一起成为一个集群,可能会有大量的跨机房互访,会产生大量的随机流量来填满有限的跨机房带宽,在这次除了线下受到影响外,还可能影响到其他跨机房的服务。因此,如何防止跨机房的随机流量占满跨机房带宽是多机房解决方案需要解决的重要问题。NetworkJitter&Connectivity跨城网络会受到供应商服务质量(或建设)的影响而造成抖动(或断网),远低于机房CLOS架构的网络质量。如果将两个机房的主机作为一个集群,如图1中的HDFS示例,当网络出现波动时,不仅会增加跨机房读写的延迟,还会影响到IBR进程DN,导致服务性能和稳定性下降;当网络出现严重问题,网络断开时,远程机房的数据将不可用,远程机房的DN也会丢失。这会导致大量的区块低于预期的副本数,触发NN补足大量副本。因此,如何降低网络抖动和网络连通性问题的影响,是多机房解决方案中另一个不可忽视的问题。图1HDFS架构2.2设计选型如前所述,多机房的主要矛盾是网络带宽不足、稳定性差和离线海量数据处理任务的高效输出之间的矛盾。如何解决这一主要矛盾的核心问题?减少跨机房带宽的消耗,如何减少网络稳定性问题的影响。经过研究,单元化架构是为解决多中心、多中心问题演化而来的部署架构。单元是指能够完成所有业务操作的自成一体的集合。该集合包含业务所需的所有服务。以及分配给本机的数据[1-2]。根据单元化的思想,在多机房场景下,可以将每个机房作为一个单元,每个单元提供作业执行所需的所有服务和数据,保证作业在本单元内完成,从而解决了上述多机房面临的核心问题Problem;单元化拆分后,任何单元的故障只会影响局部,不会造成整体瘫痪;选择采用单元化的思路设计多房间方案后,多房间方案的核心问题仅限于如何决定作业和数据的放置,以及如何让作业近距离访问数据减少跨房间带宽的消耗和网络稳定性问题的影响。带着以上核心问题,我们调研了业界主要厂商的多机房解决方案[3-7]。在计算层面,为了防止Shuffle等中间结果数据造成机房间流量,每个机房独立部署一个计算集群,符合本层面单元化的思想;但是在存储和存储上是有区别的,如图2所示。根据数据和远程机房的数据副本是否属于同一个NameSpace(NS)组,大致可以分为多个机房单集群解决方案和多机房多集群解决方案。图2多机房解决方案分类[3-5]采用多机房单集群解决方案。在此解决方案中,使用了块级数据副本。数据和数据副本属于一组NS,不存在数据一致性问题。其中一个机房无法有效处理网络连通性问题,Namenode远程副本管理(BlockPlacementPolicy)及相关工具(Mover、Balancer等)改造成本较高。此外,该方案的可扩展性还受到单个集群规模的限制。[6-7]采用了多机房多集群的方案,整体上符合单元化的思路。其中,[6]应用于云梯搬迁机房场景。它首先通过FastCopy将文件元数据分离到同一个机房??的两个NS,然后在同一个NS中通过DN-to-DN的跨机房Copy将数据复制到远程机房。该方案在一定程度上可以有效应对跨机房网络风险,但难以保证两份副本的时效性,而且数据节点也存在异地,本质上存在改造成本和多机房单集群解决方案的可扩展性;[7]阿里愚公(Yugong:Geo-DistributedDataandJobPlacementatScale)基于MetaStore面向分区表场景,通过降低跨机房带宽消耗调整工作安置和数据安置;如图3所示,计算A、B有跨机房访问行为。通过调整(调换)计算A、B的位置,有效降低跨机房访问流量;计算C和D同时跨机房消费同一个数据3。如果数据3是通过dataCopy复制到机房2,让C和D依赖机房2数据3的副本,这样可以减少一次跨机房的消耗数据流量。但是对于我们采用开源大数据架构的场景,需要对各种计算框架(属于多个子部门)进行改造以适应其基于MetaStore的数据副本管理和数据路由,以及改造的实施成本相对较高;另外,其他基于MetaStore的设计只能解决表(SQL)场景下的多机房问题,无法覆盖我们对非表场景提供多机房支持的需求;但是这个方案通过“作业放置-数据复制”解决带宽瓶颈问题的思路非常值得我们借鉴。图3跨机房任务随机分配综上所述,我们参考愚公“作业放置-数据复制”的思路,使用有限单元化设计多机房方案;如图4所示,每个机房部署了一套完整的独立集群(YARN&HDFS),为一个机房作业的执行提供了最基本的服务保障,从而减少交叉出现异常时的影响范围-机房网络;同时,通过合理的岗位安排和有计划的数据复制,杜绝跨机房的随机性。以达到降低带宽消耗、访问流量和跨机房数据重复消耗等问题的目的;此外,我们结合内部基础设施条件,同时满足表和非表场景的需求,我们选择了基于扩展的HDFSRouter(RBF)多个挂载点来实现数据副本管理和数据路由功能,并自动路由数据通过ClientIP感知请求到最近的机房;还引入了Version服务来解决数据复制带来的一致性问题等,如图所涉及的组件将在实现部分进行介绍。图4多机房架构2.3总体流程图图5为上述设计思路下的总体流程,以Hive作业为例。图中的绿色模块是我们新增或修改的组件。首先,通过定期分析作业之间的依赖关系和依赖数据的大小,确定作业放置信息并持久化(DataManager用于管理作业放置信息等),作业调度平台(Archer和Airflow)B站提交作业放置作业时,先获取放置作业的机房信息,查看预期机房的数据副本是否准备好。如果准备就绪,请提交作业。否则,阻塞提交,等待数据复制服务完成数据的复制。/SparkDriver生成可执行计划,将作业提交到预期DC的Yarn集群,等待作业被拉取。同时我们在Yarn层面也做了改造。基于YarnFederation架构,我们实现了基于app标签和队列的机房调度策略。这也将在下面介绍;最后,当pull的job请求HDFS数据时,HDFSRouter根据ClientIP的DC信息,自动将请求路由到离Client较近的数据副本所在机房的NS,并将结果返回给Client.图5多机房作业调度执行流程多机房核心流程包括作业放置、数据复制、数据路由、版本控制、数据限流、跨机房流量分析等几个阶段。上面的job提交过程并没有完全涵盖,下面的实现部分我们会详细描述各个阶段。03多机房解决方案的实现下面章节将介绍多机房的核心环节,包括作业放置、数据复制、数据路由、引入数据版本服务和带宽控制限流服务,保证数据副本一致性,以及后处理简介一款跨机房流量分析工具,用于发现非预期的跨机房行为并指导调整。3.1就业安置依赖分析大数据离线场景,作业数量多,作业之间的依赖关系复杂。比如大数据离线报表处理业务,从数据的采集、清洗,到报表各层级的汇总计算,再到最终的数据导出到外部业务系统,一个完整的业务流程可能涉及数百个相互依赖的关联作业。就作业安置而言,复杂的作业依赖关系的管理和分析非常重要,而我们自主研发的调度平台Archer等DAG工作流调度系统具有强大的作业依赖管理能力。因此,我们只需要Focusedjobdependencyanalysis来确定迁移哪些业务。基于作业之间的依赖关系和待处理数据的大小,我们探索了一种基于社区检测的考虑跨机房带宽成本的作业关系链分区模型。该模型首先根据调度系统管理的作业之间的依赖关系构造DAG图,然后从DAG图中圈出内聚度较高(相对闭环)的业务子单元,最后结合相互依赖的子单元之间的数据量选择。units可以迁移的子单元;图6所示的简单DAG,我们假设图中的正方形代表计算,圆圈代表数据,圆圈的大小代表数据大小,那么我们以虚线为界划分DAG分成两个子单元,分别调度到两个机房,可以达到低数据传输成本的目的。当然,整个过程除了考虑跨机房数据访问的成本外,还需要考虑机房的计算和存储资源是否能够满足需求。图6依赖划分一般来说,实际生产中的ETL等周期性调度作业是比较稳定的,不会经常变化,甚至有些作业不会变化。因此,确定作业所在机房的依赖分析过程可以按天或周周期性离线计算生成;另外,从管理的角度来看,一个公司一般会有多个相对独立的业务部门,每个业务部门又会纵向划分为多个业务子单元。单位,企业内部各业务之间的联系程度远大于企业之间;同时,一个业务(单位)也是多机房实施过程中的资源管理单位和通信单位;因此,在实践中,往往以业务单元为边界进行依赖划分。b.作业调度我们的生产环境中有多个作业调度平台,比如Archer、Airflow等平台。机房作业的信息维护不可能覆盖任何平台的所有作业,所以我们引入了DataManager服务(在整个系统中图4的位置见图4)作为接入层,用于管理作业放置的IDC信息和需要复制的路径信息。Archer/Airflow等调度平台通过连接该服务连接到多机房系统;下面以自主开发的DAG调度平台Archer为例,对工作流程进行说明如下:前期工作:Archer通过DataManager接口设置作业的位置信息,以及路径模式、作用域等信息,以及相关数据的生命周期。Archer访问DataManager以确定用于作业放置的IDC信息,并为作业选择与IDC匹配的作业配置信息。Archer询问IDC中的作业数据是否准备就绪。如果是,将apptag设置为IDC,通过YarnRMProxy将作业提供给计算集群;否则挂机,等待数据准备好再尝试重新提交;其中,数据是否就绪,是通过DataManager将请求转发给数据复制服务获得的。另外,由于我们业务部在Yarn上和一级队列是一对一映射的,一旦某个业务部的数据整体迁移到新机房,我们会设置队列映射策略将RMProxy中的部门对应到新机房,使得调度平台或其他用户客户端提交的作业即使没有连接到DataManager也能正确路由到新机房的计算集群,计算回收旧机房的存储资源。图7Yarn调度策略3.2数据复制a.复制服务作业放置,将密切相关的作业放置在一个机房,减少跨机房访问,从而降低跨机房网络带宽消耗;对于无法消除的跨机房依赖,尤其是在异地机房使用频率大于1的数据,需要在异地机房进行数据拷贝,以减少网络带宽消耗;因此,我们提供数据复制服务进行复制。数据复制服务基于社区提供的DistCp工具实现,在正确性、原子性、幂等性、传输效率等方面进行了增强。还支持流量控制和多租户传输优先级(优质作业可以获得更多跨度机房流量和计算资源配额)、副本生命周期管理等功能。b.复制过程数据复制主要针对定期调度的作业进行,一般是固定的。通过分析作业的历史运行记录,可以推断作业的输入和输出,包括数据路径和使用数据的范围。(防止长时间跨度大量复制刷新任务)等信息。因此,在确定要迁移的作业后,可以提取数据路径规则(规则)并持久化到DataManager的规则库中(规则库会随着作业放置的变化而定期更新)。然后,使用规则库为不同的场景提取路径。以Hive表场景为例,描述数据复制过程。如图8所示,首先将HiveMetaStore挂载的表/分区相关的事件信息收集到Kafka服务中,然后通过实时的Flink任务Clean上述规则库中符合规则的路径。当检测到并生成新的热点表分区时,会传输到数据复制服务(DRS),生成远程机房的副本。DRS本质上是一个DistCp作业。管理服务,传输完成后,数据复制服务持久化副本信息(包括路径、版本、TTL等),对副本数据进行全生命周期管理(删除过期的跨机房副本,释放存储空间),目前B站上线了100+个设置了跨机房复制策略的Hive热点表路径。图8数据复制过程上述复制过程采用了自动发现和主动复制的策略,可以快速捕获和准备数据副本。据统计,我们生产中的数据拷贝延迟PT90可以控制在1min以内,PT99可以控制在5min以内,可以有效满足离线场景下的业务需求;但是,上述自动发现和主动复制的策略可以有效解决增量数据拷贝的问题,但是对于需要迁移的作业来说,可能在很长一段时间内仍然依赖于存量数据。为了解决这个问题,我们除了通过提前启动复制过程来准备存量数据外,针对需要快速迁移的场景,引入了基于Snapshot的数据迁移策略进行初始复制。由于Snapshot是社区成熟的技术,这里就不细说了。3.3数据路由上一节中,数据拷贝完成后,两个机房都会有某条路径的数据拷贝。当作业放在IDC中时,如何定位正确的数据是数据路由服务要解决的关键问题;我们在《HDFS在B站的探索和实践》中提出在基于HDFSRouter的多挂载点实现的MergeFs的基础上,实现镜像挂载点,实现数据路由功能。为了描述方便,我们约定原始数据为主数据,传输到远程机房的数据为副本数据(也叫镜像数据,只能读取和删除),第一个挂载点在镜像挂载点是约定的主数据,后面的挂载点是拷贝数据(理论上可以扩展多个机房)。为了在路由层面对用户透明,我们在镜像挂载点Awareness功能的处理逻辑中加入了请求源的IP地址,可以通过获取请求源的位置信息来判断请求源的DC请求源IP,将请求路由到对应DC的HDFS。如图9示例所示,如果数据请求来自DC1,Router将数据请求重定向到DC1的HDFS集群,从DC2重定向到DC2的HDFS集群(图中同色线表示请求小路)。图9基于Router的数据路由为了减少跨机房带宽的消耗,原则上我们规定所有的数据读取操作只允许在本地机房(即Client所在的机房)进行),否则先复制到本地机房。但是在特殊情况下,如图10所示,如果数据复制服务短时间异常无法修复或者ns长期异常,我们允许降级为跨机房限流读取(副本没有准备好,一定时间没有在服务器上)如果目标机房读取数据,就会降级),限流部分在后面详细介绍章节。图10数据路由容错另外,由于历史原因,我们生产中有一个专门的临时库,用于管理用户SQL作业中创建的短期临时表(Temporarytable,七日自动清理).临时表的表名不固定(比如有些ETL作业会在临时表名上加上日期后缀),这也会导致表类路径不固定;对于类路径不固定的情况,不能使用上面的镜像挂载点,因此我们引入一个多挂载点IDC_FOLLOW,用于挂载多个机房的临时库路径;读写临时表时,会根据Client所在的DC选择DC中的HDFSNS。加载访问数据的路径,解决临时表的跨机房流量问题。3.4在版本服务的分布式场景下,通过数据复制产生副本,必然会导致一致性问题。因此,当数据副本存在于多个机房时,除了上述路由选择问题外,还必须考虑数据版本一致性问题。我们通过引入版本服务(Version)来解决这个问题;为了简化版本服务的设计,同时针对大数据离线场景写少读多的特点,所有操作都可以对数据进行,复制数据只允许读/删除操作;在此前提下,我们引入了一个基于HDFSEditlog的版本服务,如图11所示,该服务作为观察者监听HDFSJournalNodes(JN)订阅路径的变化行为,并使用操作ID(transactionid)识别数据版本;如果订阅路径中的数据发生变化,会通过editlog传给JN,然后JN通知Version更新版本;因为所有对数据的更改操作都会记录在editlog中。因此无论SQL场景还是非SQL场景,只要数据有变化,都可以被版本服务捕获,可以有效保证数据的一致性。图11数据版本工作流程上文2.3节整体流程中提交作业时,在获取到作业期望放置的机房后,检查依赖数据是否就绪的工作也包括版本检查;当作业需要复制数据时,它会使用数据传输服务检查传输的数据副本的版本是否与版本服务中订阅的最新版本一致。如果一致,则允许作业提交使用数据副本;否则,作业暂时被阻塞,待传输服务更新副本数据后,才允许提交作业。;如果目标机房在一定时间内没有读取数据,则降级为读取主数据。3.5限流服务在我们的场景中,跨机房的带宽是有限的(大约4Tbps),带宽是共享给在线服务、实时服务等对时延比较敏感的服务。为了防止线下跨机房流量(尤其是计划外的跨机流量)满带宽影响线上业务,所以我们引入了基于令牌桶的限流服务。图12令牌桶令牌桶限流的核心思想是,当某个操作需要令牌时,需要从令牌桶中取出相应数量的令牌。如果获得了令牌,则继续操作,否则将被阻塞并用完。之后没有必要把它放回去。基于这个思路,我们设计了全局中心化限流服务。基于HDFSDistributedFileSystem类,我们实现了具有读写限流功能的ThrottledDistributedFileSystem。当用户使用该类读写HDFS文件时,ThrottledDistributedFileSystem会根据RBF返回的LocatedBlock中的clientIDC信息和BlockIDC信息来判断读写流量是否会穿越机房。如果是,它会先尝试向ThrottleService发送一个跨机房带宽(Token)的请求。获取到token后,后续HDFSreadWrite,如果请求流量用完,向ThrottleService申请新的带宽Token;除了利用令牌桶的固有特性,我们在令牌桶的基础上实现了队列优先级和加权公平性,限流服务队列的优先级和调度系统中的作业优先级也映射为一个一个保证多租户情况下重要服务优先获取Token;在稳定性方面,为了减轻限流服务的压力,我们设置每个Token代表一个比较大的流量单元,以减少Token获取次数过多带来的性能影响;为了防止限流服务宕机导致的作业阻塞,我们加入了降级到本地固定带宽的策略,随着计算引擎持续访问限流服务,服务本身的稳定性和请求级别变得针对瓶颈(单机100K+qps),我们通过水平扩展服务提升了限流服务的性能。3.6跨机房流量分析随着多机房项目的逐步推进,跨机房流量也日益增加,高峰时段专线带宽偶尔会爆满。为了有效控制跨机房带宽流量,我们需要了解哪些作业对跨机房流量的贡献最大,从而进行针对性的管理。从离线操作的角度来看,网络流量的来源主要有3个:作业执行过程中通过在不同Executors/Task之间shuffle数据从上游读取数据和向下游表写入数据。每个机房都有一个独立的Yarn集群。Job不会跨机房跑,不会有跨机房的Shuffle数据。所以只需要在读写HDFS文件的同时,考虑读写HDFS文件过程中产生的跨机房流量。跨机房的流量可以分为计划流量和计划外流量两类:计划流量:3.2节描述的数据拷贝服务产生的流量,我们称之为计划流量,这部分数据是大概率的它将被多次使用。计划外流量:即非数据复制业务产生的数据流量。它被使用一次(或多次)。主要来源如下:历史刷新,依赖数据副本过期销毁b.周期性的调度任务(漏迁移/错迁移/新增等)放置在不合理的位置,可以通过优化作业放置c来消除。即席查询、突发流量、单次(或多次)使用、临时生产需求,无法预测所需数据,无法通过流量分析工具进行预处理在实际生产过程中,计划外流量是不可避免的,为了有效控制跨机房流量,我们引入了跨机房流量分析工具,我们在引擎端和DN端做了如下修改::在DataXceiver中埋点,从ClientName中解析出JobId,根据JobId和客户端IP网段合并读写流量,每30秒将统计结果输出到流量日志中。我们实时采集各个DN上的跨机房流量日志,通过Flink汇总到ClickHouse上,然后聚合分析得到一个时间段内Top10的跨机房流量操作,方便跨机房管理房间流量(包括搬迁、紧急查杀、工作优化等)。图13流量日志采集链接以下是我们跨机房流量分析的监控面板:图14跨机房流量分析Adhoc流量治理与优化针对Adhoc类的非计划流量,由于其随机性,在多机环境下本文描述的房间系统“数据复制-作业放置-数据路由”的方法不适用;因此,我们采用了一些其他的优化方式,比如通过runtimeSQLScan扫描出依赖的数据大小和位置信息,主要目的是节省多机房的带宽。结合集群的实际负载,确定SQL调度到哪个机房,例如:访问单表:作业调度到数据所在机房访问多表和同机房多表,作业调度到数据所在机房,多张表在不同机房,作业调度到数据量大的表所在机房;对于小表,限流读取,或者阻塞通知副本服务副本另外,对于像Presto这样具有多源查询能力的引擎,我们利用它的Connector多源查询能力,连接各个机房作为一个Connector,在多表访问场景,将子查询下推,发送到远程机房处理,减少断线机房的流量带宽。详见《Persto在B站的实践》5.2多机房架构。04总结&展望本文介绍B站离线多机房解决方案,该方案已顺利运行半年多。迁移数据量近300PB,作业数量占集群所有作业的1/3。从实际效果来看,该方案很大程度上解决了跨机房网络带宽不足、稳定性差、离线任务高效输出的矛盾。鉴于目前大数据部分关键组件的单元化进程,抵御网络连接风险的能力还有很大提升空间。未来,我们将继续推进单元化进程,进一步缩小网络问题的范围。同时,我们会赋予一些高度优化的作业“双活”能力。另外,随着新机房的不断扩容(旧机房无法扩容,新机房部署新节点),我们也需要继续将更多的工作迁移到新机房。为了提高迁移速度,我们需要尽量减少对上下游业务的影响(例如,要求业务方协助分工和梳理子业务),因此,我们需要实现更智能、更自动化的流程用于自动划分待迁移的数据和作业,并进一步加强社区检测算法的使用,可以将DAG自动划分为多个具有高内聚性的子集/社区,并根据社区的粒度进行迁移工作。