微信号:egonetworks

介绍:EGO(Extra Geek Organization),超级极客邦,是极客邦科技旗下高端技术人聚集和交流的组织,由InfoQ中国团队运营,旨在组建全球最具影响力的高端技术人社交网络,线上线下相结合,为会员提供专享服务.

行进中换轮胎——解析美团和大众点评两大数据平台是怎么融合的

2017-09-11 20:17 语宸

本文由“ 美团点评技术团队 ”授权转发 
根据作者在2017年 Arch Summit 的分享记录整理而成。

一、背景

互联网格局复杂多变,大规模的企业合并重组不时发生。原来完全独立甚至相互竞争的两家公司,有着独立的技术体系、平台和团队,如何整合,技术和管理上的难度都很大。2015年10月,「美团」「大众点评」合并为今天的“ 美团点评 ”,成为全球规模最大的生活服务平台。主要分布在北京和上海两地的两支技术团队和两套技术平台,为业界提供了一个很好的整合案例。

本文将重点讲述数据平台融合项目的实践思路和经验,并深入地讨论 Hadoop 多机房架构的一种实现方案,以及大面积 SQL 任务重构的一种平滑化方法。最后介绍这种复杂的平台系统如何保证平稳平滑地融合

两家公司融合之后,从业务层面上,公司希望能做到“ 1+1>2 ”,所以决定将「美团」和「大众点评」两个App的入口同时保留,分别做出各自的特色,但业务要跨团队划分,形成真正的合力。

比如丽人、亲子、结婚和休闲娱乐等综合业务以及广告、评价 UGC 等,都集中到上海团队;而餐饮、酒店旅游等业务集中到北京团队。为了支撑这种整合,后台服务和底层平台也必须相应融合。

点评 App 和美团 App 的数据,原来会分别打到上海和北京两地的机房,业务整合之后,数据的生产地和数据分析的使用地可能是不一样的。同时,随着公司的融合,我们跨团队、跨业务线的分析会越来越多,并且还需要一些常态化的集团级报表,包括流量的分析表交易的数据表,而这些在原来都是独立的。

举个例子,原点评侧的分析师想要分析最近一年访问过「美团」和「大众点评」两个 App 的重合用户数,他需要经过这样一系列的过程:如下图所示,首先他要想办法找到数据,这样就需要学习原美团侧数据平台元数据的服务是怎么用的,然后在元数据服务上去找到数据,才能开始做分析。

而做分析其实是一个人工去做 SQL 分解的过程,他需要把原点评侧的去重购买用户数拉下来,然后发到原美团侧的数据平台,这个环节需要经历一系列的操作,包括申请账号下载数据上传数据,可能还会踩到各种上传数据限制的坑等等。

最终,如果在这些都走完之后想做一个定期报表,那他可能每天都要去人工处理一回。如果他的分析条件变了怎么办?可能还要再重新走一遍这个流程。

所以他们特别痛苦,最终的结果是,分析师说:“ 算了,我们不做明细分析了,我们做个抽样分析吧!”,最后他做了一个在 Excel 里就能做的去重数据量的分析。我们作为平台开发的同学来说,看到这个事情是非常羞愧的。那怎么办呢?

在经过一些磨合后,我们得出一个结论,就是必须进行数据口整合

二、融合实践

1.确立目标

我们定了一个整体的目标,希望最终是能做到一个集群一套数据平台的工具一套开发规范。但是这个目标有点大,怎么把它变的可控起来呢?首先至少看来是一个集群,也就是说从用户访问的角度上来讲,他通过一个 Client 或一套用户视图就能访问。工具方面至少明确已有的两套,哪些是新的员工进来之后还需要学,哪些是未来会抛弃掉的。最终,让大家认同我们有了一套数据平台规范,虽然这套规范短期内还没有办法做到完美。我们做的这些权衡其实是为了从整体上能将问题收敛。

但即使我们把这个目标缩小了,想要达到也是很难的。难点在哪呢?

2.难点

➣ 架构复杂,基础设施限制

如上图所示,整个数据平台基本上分为数据接入数据开发数据分析数据输出等等几个阶段。我这里只列了其中涉及到跨机房跨地域的部分,还有很多数据平台产品的融合,在这里就不赘述了。

在两个公司融合之前,原「点评侧」和「美团侧」都已经在同地域进行多机房的部署了,也都很”默契”地抽象出了离线的机房是相对独立的。在线的业务机房不管是通过消息队列还是原点评自己当时做的 Blackhole(一个类似 DataX 的产品),都会有一系列数据收集的过程、对应任务的调度系统和对应的开发工具,也会有一些不在数据开发体系内的、裸的开源客户端的跳板机。虽然架构大体一致,但是融合项目会牵扯整套系统,同时我们有物理上的限制,就是当时跨机房带宽只有10 Gb 。

➣ 可靠性要求

由于团购网站竞争激烈,两家公司对于用数据去优化线上的一些运营策略以控制运营成本,以及用数据指导销售团队的管理与支撑等场景,都有极强的数据驱动意识,管理层对于数据质量的要求是特别高的。

我们每天从零点开始进行按天的数据生产工作日9点,老板们就坐在一起去开会,要看到昨天刚刚发生过什么、昨天的运营数据怎么样、昨天的销售数据怎么样、昨天的流量数据怎么样;工作日10点,分析师们开始写临时查询,写 SQL 去查数据,包括使用 Presto 、Hive ,一直到22点;同时数据科学家开始去调模型。如果我们集群不能 work ,几千人每天的工作就只能坐在电脑面前看着 Excel 。 

当时的分析是这样,如果考虑回滚的情况下,我们运维的时间窗口在平日只有一个小时,而且要对全公司所有用数据的同学进行通告,这一个小时就是他们下班之后,晚上6点至7点的时候开始,做一个小时,如果一个小时搞不定,回滚还有一个小时。周末的话好一点,可以做4小时之内,然后做全面的通告,相当于整个周末大家都没法加班了,他们是非常不开心的。

➣ 体量

虽然没有到 BAT 几万台节点的规模,但是也不算小了,融合时「原点评」的节点数是500个,数据量是11个 P 原美团的节点数是3000个,现在整体已经上6000了

这里有一个比较关键的数据就是每天生成的数据量,由于我们的集群上面以数仓的场景为主,会有很多重新计算。比如说我要看去年每月的去重,这些都是经过一些时间变化之后会进行重算的。

它对于分析数据的迭代速度要求很高,我每天可能都会有新的需求,如果原来的数据表里面要加一个字段,这个字段是一个新的统计指标,这个时候我就要看历史上所有的数据,就得把这些数据重新跑一遍。这里的生成数据量其中有50%是对历史的替换,50%是今天新增的。这对于后面我们拷数据、挪数据是比较大的挑战。

➣ 平台化与复杂度

两家公司其实都已经慢慢变成一个平台,也就是说数据平台团队是平台化的,没法对数据的结果分析负责,数据平台团队其实对外暴露了数据表和计算任务这两种概念。

平台化以后,这些数据表的 owner 和这些数据任务的 owner 都是业务线的同学们,我们对他们的掌控力其实是非常差的。我们想要改一个表的内容、一个数据任务的逻辑,都是不被允许的,都必须是由业务侧的同学们来做。

两侧的平台融合难免存在功能性的差异,数据开发平台的日活跃就有100和240,如果查询就是每天作分析的日活跃的话,原点评和美团加起来有1000多。所以在平台融合过程中,能让这么多用户觉得毫无违和感是非常有挑战的。

综上,我们做了一个项目拆解。

三、项目拆解

1.数据互访打通

数据互访打通其实是最早开始的,早在公司宣布融合以后,我们两侧平台团队坐在一起讨论先做什么,当时做了一个投入产出比的权衡,首要任务是用相对少的开发,先保障两边分析师至少有能在我们平台上进行分析的能力。接着是让用户可以去配置一些定时任务,通过配置一些数据拷贝任务把两地数据关联起来。

在这方面我们总共做了三件事。

➣ 原始层数据收集

在原「美团侧」把原点评侧线上业务机房一些 DB 数据以及 Server 的 log 数据同步过来。这个时候流式数据是双跑的,已经可以提供两边数据合在一起的分析能力了。

➣ 集群数据互拷

集群数据互拷,也就是 DistCp 。这里稍微有一点挑战的是两边的调度系统分别开了接口,去做互相回调。如果我们有一份数据,我想它 ready 之后就立即拷到另外一边。

比如「原点评侧」有个表,我要等它 ready 了之后拷到「原美团侧」,这个时候我需要在原美团侧这边配一个任务去依赖原点评侧某一个任务的完成,就需要做调度系统的打通。本文主要讨论大数据框架的部分,所以上面的调度系统还有开发平台的部分都是我们工具链团队去做的,就不多说了,下文重点描述 DistCp

其实 Hadoop 原生支持 DistCp ,就是我起一个 MapReduce 在 A 集群,然后并行地去从 B 集群拖数据到A集群,就这么简单。只要你网络是通的,账号能认(比如说你在A集群跑的任务账号能被 B 集群认),并且有对应的读权限,执行端有计算资源,用开源版本的 DistCp 就可以搞定。

这方面我们做了一些权衡:

  1. 首先是因为涉及到带宽把控的问题,所以同步任务是由平台团队来统一管理,业务侧的同学们提需求。

  2. 然后我们两侧集群分别建立一个用于同步的账号,原则是在读的那一端提交任务。

什么叫“ 读的一端 ”?比如说我想把一个「原点评侧」的数据同步到「原美团侧」,「原美团侧」就是要读的那端,我在「原美团侧」起这个任务去读「原点评侧」的数据,然后写到「原美团侧」。这里的主要考虑是读端更多是需求端,所以,他要在他的资源池里去跑。另外,对集群的影响读小于写,我们希望对于被读集群的影响能尽量减少。

当然,这都是一些临时的项目,投入较小,但收益是磨合了两地团队。

➣ Kerberos 跨域认证架构

接着介绍一下认证部分是怎么打通的。「原美团侧」和「点评侧」恰好都用了 Kerberos 去做认证服务,这个 Kerberos 在这我不去详细展开,只是简单介绍一下。首先是 KDC 会拥有所有的 Client 和 Server ,Client 就是 HDFS Client ,Server 就是 Name Node ,KDC 会有 Client 和 Server 的密钥,然后 Client 和 Server 端都会保有自己的密钥,这两个甚至都是明文的。

所有的密钥都不在传输过程中参与,只拿这个密钥来进行加密。基于你能把我用你知道的密钥加密的信息解出来,这一假设去做认证。这也是 Kerberos 架构设计上比较安全的一点。

Kerberos 不细讲了,下面详细讲一下 Kerberos 跨域认证架构

一般公司都不会需要这个,只有像我们这种两地原来是两套集群的公司合并了才需要这种东西。我们当时做了一些调研,原来的认证过程是 Client 和 KDC 去发一个请求拿到对应 Server 的 ticket ,然后去访问 Server ,就结束了。

但是如上图所示,在这里它需要走3次,原来是请求2次。大前提是两边的 Kerberos 服务,KDC 其中的 TGS 部分,下面存储的内容部分分别要有一个配置叫 krbtgt ,它有 A realm 依赖 @ B realm 这样的一个配置。

两边的 KDC 基于这个配置是要一致的,包括其中的密码,甚至是包括其中的加密方式。那这个时候我们认为这两个 KDC 之间实际上是相互信任的。

流程是 Client 发现要请求的 Server 是在另外一个域,然后需要先去跟 Client 所属的 KDC 发请求,拿一个跨域的 ticket ,就是上图中1右边那个回来的部分,他拿到了这个 krbtgt CREALM @ REALM 。然后 Client 拿着跨域的 ticket 去请求对应它要访问 Service 那一个域的 KDC ,再去拿对应那个域的 Service 的 ticket ,之后再去访问这个 Service 。这个流程上看文档相对简单,实则坑很多,下面就讲一下这个。

Kerberos跨域认证的一些要求


首先第一个比较大的要求就是密钥的编码一致。这有一个大坑:就是你必须让两个 KDC 拿到的信息是一样的,它们基于这个信息去互信,去互相访问。然后 krb5.conf 里面有一些比较诡异的 domain_realm 策略,这个在你网络环境不一致的时候会有一定的影响,包括 DNS 也会影响这个。在你的网络环境比较不可知的时候,你需要做做测试,尝试去怎么配,然后在 Hadoop 端有两个配置需要做,分别在 Server 端和 Client 端配置即可。

其中比较恶心的是说,在测试的过程当中,需要去看 Hadoop 的详细日志,需要开一下它的 Debug ,然后去看一下它真正请求的那个域是什么样的。因为我们翻代码发现,Hadoop 底层有对 log ,Client 去请求 realm 的隐改,就是说我认为我应该是这个 realm 啊,它为什么传出来的是另外一个 realm ?这个是比较坑的一点。

我们做完这个项目之后,分析师就可以愉快地配置一些调度任务去同步数据,然后在对应的集群上去关联他们的数据进行分析了。做完这个项目之后,我们两边的团队也相互磨合,相互形成了一定的认可。因为这个小项目涉及到了数据平台的每一个领域,包括工具链、实时计算、离线的团队都做了一些磨合。

➣ 集群融合

粗看起来,打通了数据平台,我们的大目标似乎已经完成了:一个集群、一套数据平台的工具、一套开发规范。把数据拷过来,然后重新改它的任务,就可以形成在统一的一套工具和规范里面用一个集群,然后慢慢把原来团队维护的服务都下掉就好了。事实上不是这样的,这里面有大量的坑。如果接下来我们什么都不做的话,会发生什么情况呢?

数据 RD 会需要在迁移的目标平台重建数据,比如说我们都定了,以后把「原美团侧」平台砍掉,那么好,以后都在「原点评侧」的平台,包括平台的上传工具平台的集群去使用、去开发。这个时候,至少「原美团侧」的同学会说:“ 原点评那边平台的那些概念、流程,可能都跟我不一样啊,我还需要有学习的时间,这都还好 ”。但他们怎么迁移数据呢?只能从源头开始迁移,因为对端什么都没有,所以要先做数据的拷贝,把上游所有的表都拷贝过去。然后一层一层地去改,一整套任务都要完全重新构建一遍。

那我们有多少任务呢?

➣ 集群融合的问题本质

反思一下这个问题的本质,首先我们是不能双跑的,因为一旦双跑,我们必须有常态化的两份数据,然后衍生一系列的校验、存储量、切换策略等问题。所以我们必须得有一套数据,一套任务执行机制。后续任务的改变,不管是替换工具链上的东西,替换计算引擎,比如说让两边 Hive 、Spark 和 UDF 去做一致化的时候,其实本质上是说对单个任务的修改,对每个任务灰度的修改就好了。

所以我们推断出,必须自底向上地去进行融合,先合集群,然后后续再推动上游平台和引擎的融合。

➣ 集群融合的解决思路

整体我们融合的思路是这样的,集群融合先行,两边的 Hadoop 的服务架构和代码先进行统一,其次拷贝原点评侧集群的 Block ,同步到「原美团侧」机房的两个副本。这里有一个大的前提,第一个是「原点评侧」的集群节点数相对来讲确实小,再一个就是「原点评侧」的机房确实放不下了,它当时只能扩容到10月,再往后扩就装不下机器了。

所以我们将「原点评侧」的集群,合并到「原美团侧」机房,然后进行拷贝和切换。我们让整个这个集群变成在「原美团侧」机房一样的样子,然后进行融合。我们会把上面的客户端和元数据统一,使得访问任何一个集群的时候,都可以用一套客户端来做。一旦我们做到这个样子之后,基于统一的数据、集群的元数据和访问入口之后,我们上面的工具链就可以慢慢地去做一个一个机制,一个一个模块的融合了。

简单总结下来就是四步:统一、拷贝、切换、融合,下面我们来展开说一下这四步。

✔︎ 统一

第一优先级要解决的是上图中标红的部分,两边的 Hadoop 版本是不一样的,我们需要将「原上海侧」的版本变成我们的 2.7.1 带着跨机房架构的版本。同时因为我们后面要持续地去折腾 Hadoop 集群,所以必须先把「原上海侧」的 HDFS 架构改全,改成高可用的。

这里有一个小经验就是:我们自研的 patch 对改的 bug 或者是加的 feature ,一定要有一个机制能够管理起来,我们内部是用 Git 去管理的,然后我们自研的部分会有特殊的标签,能一下拉出来。

我们当时其实互相 review 了上百个 patch ,因为当时两个团队都有对集群,包括 Hive 等等这些开源软件的修改。这是统一的阶段,相对容易,就是一个梳理和上线的过程。接下来是拷贝的阶段。

✔︎ 拷贝

上图是最终的效果图,同步在运行的打通任务还是用 DistCp ,然后先把原点评侧的 HDFS 跨机房部署。但是这个时候原点评侧的 YARN 还是在上海机房。在这个过程当中,因为 HDFS 跨机房部署了,所以原新上线的 DataNode 可以承载更多在原点评侧集群的冷数据。这个过程是慢慢进行拷贝的,大概持续了4个月,中间长期都是10 Gbps 的小管子。

✔︎ 切换

这个相当于把「原点评侧」的 NameNode(这个时候还没有彻底下线)切换到「原美团侧」机房,然后把对应的 YARN 重新启动起来。这里有一个小 trick 就是「原美团侧」机房的承载能力,大概是1000多台节点,是「原点评侧」的两倍,所以我们才能做这个事,最近我们刚刚把上海机房的节点迁完。

那整个集群的拷贝和切换是怎么做的呢?其实就是用我们自研的一套 Hadoop 多机房架构。可能做 Hadoop 集群维护管理的同学们对这个有深刻的体会,就是不时地就要从一个机房搬到另一个机房。设计目标是说我们一个 Hadoop 集群可以跨机房去部署,然后在块的力度上能控制数据副本的放置策略,甚至是进行主动迁移。

设计是怎么做的呢?整个 Hadoop 原生的架构其实没有机房这个概念,只支持 Rack 也就是机架,所有服务器都被认为是在同一个机房的。这个时候不可避免地就会有很多跨机房的流量,就如果你真的什么都不干,就把 Hadoop 跨机房去部署的话,那么不好意思,你中间有好多的调用和带宽都会往这儿走,最大的瓶颈是中间机房网络带宽的资源受限。

我们梳理了一下跨机房部署的时候大概都有哪些场景会真正引发跨机房流量,基本上就这3~4个。首先是写数据的时候,大家知道会3副本,3个 DataNode 去建 pipeline ,这个时候由于是机器和机器之间建连接,然后发数据的,如果我要分机房部署的话,肯定会跨机房。

那我要怎么应对呢?我们在 NameNode 专门增加 zone 的概念相当于在 Rack 上面又加了一层概念,简单改了一些代码。然后修改了一下 NameNode 逻辑。当它去建立 pipeline 的时候,在那个调用里面 hack 了一下。建 pipeline 的时候,我只允许你选当前这个 Client 所属的 zone ,这样写数据时就不会跨机房了。

这些 Application 在调度的时候有可能会在两个机房上,比如说 mapper 在 A 机房,reducer 在 B 机房,那么中间的带宽会非常大。我们怎么做的呢?在 YARN 的队列里面,也增加 zone 的概念,我们用的是 Fair Scheduler 。在队列配置里面,对于每一个叶子队列,都增加了一个 zone 的概念

一个叶子队列,其实就是对应了这个叶子队列下面的所有任务,它在分配资源的时候就只能拿到这个 zone 的节点。读取数据的时候有可能是跨机房的,那这个时候没有办法,我们只有在读取块选择的时候本地优先。我们有一些跨机房提交 job 的情况,提交 job 的时候会把一些 job 里面的数据进行上传,这个时候加了一些任务的临时文件上传的是任务所在的目标机房。

这里做一些简单的改动,最重要的是提供了一个功能,就是我们在拷贝数据的时候,其实用 balancer 所用的那一套接口,我们在此基础之上做了一层 Hack ,一层封装。形成了一个工具,我们叫 Zone Transfer ,又由它来按照我们一系列的策略配置去驱动 DataNode 之间的跨机房的 block 粒度的拷贝。

上图是我们跨机房架构的架构图,下面的 Slave 里面有 DN (DataNode) 和 NM (NodeManager) ,上面跑的同颜色的是一个 App 。我们在 RM (ResourceManager) 里面的叶子队列里配置了 zone 的概念,然后在调度的时候如大家所见,一个 App 只会在一个机房。然后下面黑色的线条都是写数据流程,DN 之间建立的 pipeline 也会在一个机房,只有通过 root 去做的,DN 之间做数据 transfer 的时候才会跨机房进行,这里我们基本上都卡住了这个跨机房的带宽,它会使用多少都是在我们掌控之内的。

在上线和应用这个多机房架构的时候,我们有一些应用经验

1.迁移的过程当中我们需要评估一点就是带宽到底用多少,或者说到底多长时间之内能完成这个整体数据的拷贝。

这里需要面对的一个现实就是,我们有很多数据是会被持续更新的。比如我昨天看到这个块还在呢,今天可能由于更新被删,那昨天已经同步过来的数据就白费了。

那我昨天已经同步过来的数据就白费了。所以我们定义了一个概念叫拷贝留存率。经过4个月的整体拷贝,拷贝留存率大概是70%多,也就是说我们只有70%的带宽是有效的,剩下的30%拷过去的数据,后面都被删了。

2.我们必须得有元数据的分析能力,比如说有一个方法能抓到每一个块,我要拷的块当前分布是什么样子。

我们最开始是用 RPC 直接裸抓 Active NameNode ,其实对线上的影响还是蛮大的。后面变成了我们通过 FsImage 去拉文件的列表,形成文件和块的列表,然后再到把请求发到 standby ,那边开了一个小口子,允许它去读。因为 FsImage 里面是没有 block 在哪一个 DataNode 的元信息的。

这里需要注意的一点就是,我们每天都会有一个按天的数据生产,为了保证它的一致性,必须在当天完成。在切换之前,让被切换集群的 NN(NameNode)进入 SafeMode 的状态,然后就不允许写了,所有的写请求停止,所有的任务停止。

我们当时上线大概花了5~6个小时吧,先停,然后再去拷贝数据,把当天的所有新生产的数据都拷过来,然后再去做操作。这里最基本的要做到一点就是,我们离线的大数据带宽不能跟线上的服务的带宽抢资源,所以一定要跟基础设施团队去商量,让他们做一些基于打标签的带宽隔离策略。

✔︎ 融合

当我们把集群搬到了「原美团侧」的机房之后,又做了一层融合。想让它看起来像一个集群的样子,基本上只需要3步。

  1. “把冰箱门打开”,把原点评侧集群的那个 NN 作为一个 federation 合到原美团侧的集群,只需要改 cluster ID ,去客户端改 mount table 配置,cluster ID 是在元数据里面。

  2. 对 Hive 进行元数据的融合。我们恰好两侧元数据存储都是用 MySQL 的,把对应的表导出来,灌到这边,然后持续建一个同步的 pipeline 。它是长期活动的,到时候把上传的服务一切就可以。前面说的那个做了跨域认证的配置我们还是要拆掉的,必须进行服务认证的统一,不然的话以后没法看起来像一个集群。

  3. 把原来的 KDC 里面的账号进行导出,之后逐步地去切换每一个配置,让它慢慢切到新的 KDC 。切的过程当中,我们各种请求还是有跨域情况的,我们认为两个域是一体的,是一样的。等切干净之后,也就是原来的 KDC 没有请求了之后,我们再把它干掉。

2.开发工具融合

集群融合结束后,我们就做了开发工具的融合。由于这个跟大数据基础架构这个主题关系不是特别大,开发工具都是我们内部自研的,涉及的程序也很复杂,是一个特别大的项目,涉及一系列复杂的工具,每个模块的融合、打通。所以这个暂时不讲了。

另外我觉得比较有意思的是下面这一点,就是原点评侧的一个拆库,这个在很多公司的数据平台慢慢扩大的过程当中可能会用到。

3.原点评侧拆库

➣ 难点

先说一下背景,由于「原点评」和「原美团」整体历史上发展经验、周期和阶段不同,如上图所示,「原点评侧」的数据仓库是先有的 Hadoop 集群,后有的数据仓库平台,因此有很多平台完全没法掌控的私有库,但是他们对于数仓所在库的掌控是非常强的,所有的任务都在这一个大的 Hive 库里面,里面有七八千张表。

「原美团侧」是先有的数据平台,后来因为数据平台整个体量撑不住了,底层改成了 Hadoop 。同时在平台化的演进过程中,已经慢慢把各个业务进行独立拆分了,每个业务都有一个独立的私有库,简单来说就是库名和库名的规范不一样。我们希望能让这两套规范进行统一。

我们如何去做呢?

原来任务的内容大概是 insert into 一个 BI 库里面的一张表,接着 select from BI 库里面的某两张表,然后 where group by 。像这样的任务我们有七八千个,它们在我们平台上配置着每天的依赖调度。我们希望把它都改成下图中的样子。所有涉及到的这些表都需要改名字,说白了就是一个批量改名字的事儿。

改名字听起来很简单,实际上并不是,我们有近8000个这样的任务需要改,同时这些任务相互之间都有非常复杂的依赖。

下图是我随便找的一个,「原美团侧」某一个任务所有上游和下游的依赖关系图,如此复杂,任务的平均深度大概有10层,这还是平均数,最严重的可能要有大几十层。如果我们改这里面的任务表达,就只能分层推动。但是,当我们每改其中一个的时候,可能上下游都得跟着改,具体是什么样子的呢?

下图是我们的原始结构,首先这里有一个大前提是每一个任务只对一个结果表。原始的结构中,a 表只依赖 o1 表,b 表依赖 o1、o2 ,然后 c 表只依赖 o2 ,它们之间相互关联。

这时候我希望可以对库名和表名进行一次性的修改。那如果我们逐层地去改写怎么办呢?首先要先把最上层的 mart 表改了,而我一旦改上游的某一个表,所有跟对它有依赖的表都必须改任务内容。每推动一层改动,下面一层都要变动多次,这样一来,我们这个流程就非常受限。

刚刚那个情况基本上是类似的,就是说我们对它们的改动没法批量化、信息化、流水线化,所有的用户和数据开发们,需要跟我们去聊,最近改了多少,然后谁谁谁没改完,谁谁谁又说要依赖他,整个依赖图是非常大的,我们整个项目又不可控了。那怎么办呢?

➣ 解决方案

很简单,我们只干了一件事情,就是在 Hive 层面上进行了一波 Hack 。比如说我要让原来叫 bi.o2 的表未来会变成 mart_b.o2 ,我就同时允许你以 mart_b.o2 和 bi.o2 这两种方式去访问 bi.o2 这张表就好了。

不管是写入还是读取,我们只需要在 Hive 的元数据层面去做一层 Hack ,然后做一个对应表,这个对应表我们是有规范的、能梳理出来的。在这之后,任何一个人都可以把他的任务改写成他希望的样子而不受任何影响,他写的那些表还是原来的那些表,真正在物理上的存在还是 bi. 什么什么这样的表,我们整个项目就 run 起来了。

具体的实施流程是这样,首先先梳理业务,确定整体的映射关系。然后 Hive 元数据入口上去做别名能力,我们是在 Hive metaserver 里面去改的,大部分请求都在这里面,包括 Spark 的、Presto 的、Hive 的等,都能兼容掉,推动分批次改写,单任务内以及任务链条内完全不需要做依赖关系的约束,最终真正实现的是自动化地把 SQL 文本替换掉了。业务的同学们只需要批量看一个检测报告,比如说数据对应上有没有什么问题,然后一键就切了。

我们用了一个季度业务侧来磨合、尝试练习和熟练,同时做工具的开发。然后第二个季度结束后,我们就完成了7000多个任务中90% SQL 任务批量的改写。当任务都切完了之后,我们还有手段,因为所有的请求都是从 Hive 的 metaserver 去访问的,当你还有原有的访问模式的时候,我就可以找到你,你是哪一个任务来的,然后你什么东西改没改,改完了之后我们可以去进行物理上的真正切分,干掉这种元数据对应关系。

物理上的真正切分其实就是把原来都统一的库,按照配置去散到真实的物理上对应的库上,本质还是改 NN 一个事情。

三、总结与展望

1.未来——常态化多机房方案

我们目前正在做的一个项目,就是常态化地把集群跨机房去跑,其中最核心的就是我们需要对跨机房的数据进行非常强的管理能力,本质上是一个 Block 粒度 Cache 的事情,比如说 Cache 的击穿、Cache 的预热或者 Cache 的等待等等,都是一个 Cache 管理的事情。我们会引入一个新的 server ,叫 zone Server ,所有的 Client 请求,NameNode 进行块分布的时候,调整和修改。之后大家会在「美团点评」技术博客上看到我们的方案。

2.反思——技术换运营

数据平台做起来是很痛苦的,痛苦在哪儿呢?第一,数据平台对上层提供的不只是 RPC 接口,它要管的是数据表和计算任务。所以我们做 SLA 很难,但是我们还在努力去做。第二,就是最开始的时候一定是基于开源系统拼接出来的,然后再到平台化,这一定是一个规范的收敛,也是限制增多的过程。在这个过程中,我们必须去推动上面应用的、不符合规范的部分,推动他们去符合新的规范。平台的变更即使做到兼容,我们的整体收尾还是要尽快扫清的,不然整个平台就会出现同时进行大量灰度、每一个模块当前都有多种状态的情况,这是不可维护的。

综上,我们定义了一个概念叫“可运营性”,推动用户去做迁移、做改动是一个”运营的事情”。可运营性基本上的要求如下。

  1. 可灰度。任务的改动是可灰度的。

  2. 可关门。当某一刻,我不允许你再新增不符合新规范的任务、表或者配置,我们内部叫“关门打狗”,就是说先把新增的部分限制住,然后再去慢慢清理老的。

  3. 进度可知。清理老的我们需要有一个进度可知,需要有手段去抓到还有哪些任务不符合我们新的规范。

  4. 分工可知。抓到任务的分工是谁,推动相关团队去改动。

  5. 变更兼容/替代方案。我们肯定过程中会遇到一些人说:不行,我改不动了,你deadline太早了,我搞不定。这时候得有一些降级或者兼容变更的一些方案。

那我们什么时候去使用技术降低运营成本呢?前面已经有两个例子,就集群的迁移和融合,还有Hive表别名去帮助他们改任务名,这都是用技术手段去降低运营成本的。

➣ 怎么做到呢?

第一是找核心问题,我们能否彻底规避运营、能不能自动化?在集群融合的过程当中,其实已经彻底避免了运营的问题,用户根本都不需要感知,相当于在这一层面都抽象掉了。第二,是即使我没法规避,那我能不能让运营变得批量化、并行化、流水线化、自动化?然后当你抓核心问题有了一个方案之后,就小范围去迭代、去测试。最后还有一点,引入架构变更的复杂度最终要能清理掉,新增的临时功能最后是可被下线的。

3.体会——复杂系统重构与融合

最后稍微聊一下复杂系统的重构与融合。从项目管理的角度上来讲,怎么去管控?复杂系统的重构还有融合本质上最大的挑战其实是一个复杂度管理的事情,我们不可能不出问题,关键是出问题后,对影响的范围可控。

从两个层面去拆分,第一个层面是,先明确定义目标,这个目标是能拆到一个独立团队里去做的,比如说我们最开始那四个大的目标,这样保证团队间能并行地进行推动,其实是一点流水线的思路。第二,我们在团队内进行目标的拆分,拆分就相对清晰了,先确定我要变更什么,然后内部 brainstorming ,翻代码去查找、测试、分析到底会对什么东西产生影响,然后去改动、测试、制定上线计划。

内部要制定明确的上线流程,我记得当时在做的时候从11月到12月我们拆分了应该是有11次上线,基本上每次大的上线都是在周末做的,10、11、12月总共有12个周末,一共上线11次,大的上线应该是占了7到8个周末吧。要提前准备好如何管理依赖,如何串行化,然后准备上线,上线完怎么管理,这些都是在整个项目管理过程当中需要考虑的。

其中,两个可能大家都持续提的东西,第一个是监控,要知道改完了之后发生了什么,在改的时候就像加测试用例一样把改动部分的监控加好。第二要有抓手,如果我线上垮了,这个时候重复恢复的成本太高,也就是完全重启、完全回滚的成本太高,我能不能线上进行一些改动?

最后这张图,献给大家,希望大家在对自己系统改动的时候,都能像这哥们一样从容。



人工智能发展到今天,几乎已经无处不在了。从传媒到零售,从教育到金融,从家居到医疗,从安防到物流,人工智能正在一个又一个行业掀起变革!新时代的来临,必将淘汰一批人,同时成就一批人。摆在技术人面前的,是一个巨大的挑战,也是一个难得的机遇,但身为公司技术领导人的你,该向谁学习?——极客邦旗下的高端技术领导者社群EGO,汇聚全国近400位技术大牛,链接技术圈顶级资源,提供丰富的学习交流形式,助力技术领导者开拓视野、提升能力、解决问题、达成合作,精准把握时代脉搏!

9月1日至9月15日,EGO会员招募季正式开启,点击「阅读原文」抓紧报名!

 
EGONetworks 更多文章 2017 年第 36 周 | 每周精华 扒完社交网络关系才明白,《权力的游戏》凭什么是神作 | EGO影视荟 云片 CTO 林佳齐:云通讯稳定性的实践与探索 Mobvista CTO 王平:移动产品全球推广与变现 微软洪小文:AI 还是个小学生,资本请慎重!
猜您喜欢 魔戒普通粉十日炼成 中国雾霾真相及背后惊人的经济困境 使用spring jdbctemplate操作数据库 前端工程师的自我修养 ILSVRC2016目标检测任务回顾(上)--图像目标检测(DET)