高途数据平台迁移与成本治理实践
导读: 随着国家在教育领域推行了"双减"政策,互联网在线教育巨头高途遇到降本增效的挑战,其中在大数据平台方面也面临成本巨大、人员变动等问题,所以数据平台集群上云迫在眉睫。从 2021 年 9 月开始,历时 3 个月,高途完成了底层集群从阿里云的自建平台迁移到腾讯 EMR,以及众多数据引擎迁移上云的工作。
今天对高途数据平台上云迁移的实践的介绍会围绕以下四个方面展开:
-
高途上云迁移数据平台背景
-
迁移面临的困难与挑战
-
迁移具体实施方案及心得总结
-
高途成本管控现状及未来规划
分享嘉宾|李明庆 (前)高途 技术专家
编辑整理|Henry hypers
出品社区|DataFun
01/高途上云迁移数据平台背景
1. 自建数据平台的架构与潜在问题
上图中可以看到,这是迁移之前的集群状态。当时是为了支持业务的快速增长,但隐患也是暗藏其中。
● 第一是成本问题:在线教育火热的阶段,招聘和花钱都不限制,存储和算力不够都可以用"买买买"来解决,完全没时间精力考虑资源浪费的问题;
● 第二是技术泛滥:从架构图中可以看到,仅实时框架就包含了 Storm,Spark Streaming,Flink 这老中青三代;数据引擎更多,有 HBase,ES,Clickhouse, Impala,Kudu,Presto,Kylin 等,技术众多无形增加了运维的成本;
● 第三是中台工具缺失:比如当时用户想把数据从 Hive 离线的拷贝到 Kudu;按照大厂常规做法,我们应该提供一个 Web 页面,用户在页面上只需要做源端和目的端的配置,提供两个表名就可以完成整个操作;但因为当时业务发展太快,技术跟不上业务,导致我们没有时间去开发这种基础能力,用户只能写脚本来完成;
● 第四是历史问题沉积:在线教育行业风起云涌,瞬息万变,经常是刚上线一两个月的东西就要重构,而废弃链路并没有及时的销毁,这也就形成了一系列的历史遗留问题。
2021 年 7 月 24 日国家为减轻义务教育阶段学生过重作业负担和校外培训负担发布了"双减"政策,政策发布后,高途迅速积极响应,根据政策要求在第一时间展开行动,进行了针对性的业务调整,企业内部也进行降本增效。其中大数据平台出于计算、存储成本和人员维护的考虑,选择了大数据平台上云方案。
2. 分期上云方案
经过组里讨论,我们设立了三步走的规划:第一步是短期内是把原来自建的集群迁到云上;第二是启用云端可用的 Paas 产品,替换掉现有系统;第三个长期规划是在我们没有用过的技术能力和前沿科技,通过新的应用把我们的竞争力提升上去。设定规划后,下一步我们就开始讨论迁移面临的困难。
--
02/迁移面临的困难与挑战
当企业选择从自建平台往云上迁移的时候,往往会面临很多挑战。首先,积累多年的历史遗留问题,都会在迁移中都暴露出来。另外,迁移时用户还在使用服务和系统可能受影响,所以既要照顾用户的使用,还要解决迁移中一些不兼容的问题。
1. 云产品众多带来选择困难症
**首先要面对选型的问题。**已经确定选云以后,各个厂家纷至沓来,介绍其产品。但是直到做决策的时候,才发现是非常难的。因为我们心里想解决的问题很多,既想降成本少花钱,又想有优质服务,还想迁移能轻松一些,并且以后迭代能更顺畅。一旦考虑太多,总想着"既要又要也要还要",那决策就十分难做了。
2. 迁移面临的问题
下一步迁移时具体面临的问题,情况更为复杂和具有挑战性。
● 实际问题:比如说大批量数据拷贝、结果比对;再比如说迁移任务需要业务方的支持,特别还需要说服他们支持和给于一定的容错的空间;
● 互斥性问题:比如迁移的速度和质量往往就存在天然的矛盾;再比如有一些表没人认领,不知道是否还在使用,如果一直跑就会占用计算资源和存储资源,如果停了又可能会出事。
问题和矛盾无法避免,迁移的工作还是得干,所以接下来就是**制定迁移的流程。**高途从 2021 年 9 月开始,一共用时三个月基本完成迁移。除少数长尾工作以外,大多数业务都已经在云上跑通,下面将分享其间的一些心得。
--
03/迁移具体实施方案及心得总结
1. 云产品选型:取舍五边形
选定厂家产品的过程中,我们总结归纳了上图所示的一个五边形:
● 经济成本和售后服务:对于上层领导来说,最关心经济成本和售后服务,因为这两个都是直接跟经济收益相关的;
● 迁移复杂度:对于执行迁移工作的团队来说最看重这点,要保证最终的可行性;
● 前沿科技:这也是我们考量的一个标准,会影响到长期目标,架构调整和架构升级;
● 团队稳定性:最后厂商的团队稳定性也是需要考量的,大家都不希望厂商三天两头换对接人,从这一点来说大厂可能更有优势一些。
对于成熟的数据平台,像高途已经运营了两三年,有很多自身烙印了,已经没有任何一家云产品可以无缝衔接,所以只能针对功能做选择筛分。
2. 高途的最终选择
高途最终选择了腾讯云,此处并非对其它厂商存在否定之意,只是综合考量 ,在当时场景下,这是最贴合我们需求的一个选项。具体到模块,能替换原有服务的都尽量做到物为我用。
● 实时框架 :腾讯云产品 Oceanus 是一个实时平台,与我们原来自研的实时系统是很接近的,直接替换自研的调度平台;
● 离线系统 :腾讯的离线系统,和我们自己的有很大差距,所以我们就沿用原来自研的数据管理系统,而只使用他们的 EMR;
● 其它引擎:例如 HBase、Kudu、ClickHouse 等,云厂商的运维能力更强,成本也更低,都做相应的切换。
3. 迁移的原则
① C 端业务绝对不能受影响,所有迁移工作都要在夜间低谷执行;
② B 端业务也尽量在低谷期操作,但可接受短期(默认1小时)的不可用,并保证最终可用;
③ 无人认领的任务,可做暂停处理并等待反馈,同时要保证在一段时间(默认3个月)内可随时恢复;
④ 离线链路全部双跑,非重要链路行数一致即放行,重要链路除对比行数外还要比对关键指标,极重要链路延长比对周期;
⑤ 实时链路可不双跑,迁移前做好数据同步(一般为快照同步)准备,并确保新集群与消息队列和输出引擎间的网络可通;
⑥ 老集群任务和表下线采用自顶向下模式,随时做好任务回滚准备(离线任务做重跑,实时任务重置偏移量消费),表可禁用的引擎(如 HBase)做禁用,其它的做停写处理,观察用户反馈;
⑦ 事事留后招,不做一锤子买卖。
迁移工作中,我们总结了 7 点原则。提出这些原则是由于,我们人数不足而且精力有限,不可能一次性完全做到位,所以我们只能把事情拆分出来,哪些重要的提高优先级,花费精力做好迁移,哪些不重要的可以做一些让步。
原则的 4~6 项主要是对于安全性方面的支持不详细展开了,简单解释一下前三点:
● C 端业务:比如说用户有学生在高途平台上面买课,结果一提交订单时发现账户余额都没了,这就是大失误,是完全不能接受的;C 端的业务是绝对不能受影响的,所有迁移都在夜间低谷进行;
● B 端业务:反过来说对于 B 端业务,因为用户都是自己人,可能相对更宽容一些,所以能接受短期的不可用,我们当时默认设置是一小时,但以实际情况来说有时还可以适当的放宽;
● 无人认领的任务:不论任务还是表,找不到负责人了怎么办?我的想法是暂停维护,但同时要满足一点,如果有人找上来的话,让它随时处于一个可以恢复的状态;保留时间设为了三个月,三个月以后如果还没人找,任务和表会彻底删除;
最后提醒一点:事事留后招,不做一锤子买卖。做迁移这种大事,一定要杜绝"不成功便成仁"的想法。
4. 数据迁移--元数据和数据组合迁移
接下来介绍迁移工作中的一些具体事项。
首先是数据迁移 。在迁移数据以前我们查了一些资料和大厂迁移的规范,发现大家普遍的精力都是放在了数据迁移上,而很少提到数据和元数据的搭配迁移 ;数据迁移过以后,如果没有元数据辅佐的话,它只是一堆不可读的文件,所以我们当时设立了一整套的组合迁移(上图是组合迁移的流程)。
● 标记无用的表并清理:第一步是瘦身,旧系统先根据自身情况,把一些无用的、不用迁移的数据提前干掉,这样在后边迁移的时候能节约很多带宽;
● Metastore 全量快照:第二步"设定时间点",以这个点为中心,把元数据全量的 dump 到新集群的 metastore,这时两边的表包括 ID 都是一致的,旧数仓的 partition 在分区新的集群里也有,但此时新集群的分区中查不到数据,因为数据还没导入进来;
● Data 全量快照:第三步是历史全量数据的拷贝,这需要相当长的时间,用时跟数据量正相关,我们当初完成拷贝用时超过一个月;拷贝完成后,"设定时间点"之前的数据就是既可读又可用了;
● Data 增量快照 :拷贝历史数据过程中,旧集群还在不断产生新数据,所以在历史层面的一次全面拷贝之外,还有数次的轮巡增量拷贝;增量拷贝 的逻辑跟全量是相反的,全量是先拷贝元数据再拷贝数据,增量是直接拷贝数据,然后利用 Hive MSCK Repair 功能把元数据给补齐,这对应的主要是分区增加的情况;还有一种情况是,因为旧集群还在提供服务,所以可能还在产生新表,而此时新集群可能也会产生新表,这样如果未来拷贝元数据时,很可能会造成 tbls 表里边的 ID 有冲突;解决方案是临时调整旧集群元数据 tbls 表 increment 的方式,手动进行主键规避。
5. 数据迁移--方案示例
图中是一些当时云厂商给我们的迁移数据方案,包括离线的,以及如 Kudu、HBase、ClickHouse 等各种引擎的,每一个都代表了当时一系列的重复性劳动。
6. 任务迁移--四象限评估链路
数据迁移说完谈谈任务迁移。任务迁移也是讲主次分明,要把有限精力都放在刀刃上,重点还是说不会影响 C 端用户,不会影响"不接受任何停顿和不可用状态"的这种服务;然后根据修复难易度做四象限的拆分,确认哪些应该投入更多精力,哪些简单处理就可以了,原则还是抓大放小。
7. 任务迁移--重要链路的迁移流程
重要链路迁移流程,如图所示大致分为了三个阶段。
实际迁移的重点,首先是单次任务的迁移和比对,每到发现问题的时候,立刻要检查,可以根据整个链路从底向上检查,如果底层最后一个环节多次比对数据都一致的话,则认为这个链路是可靠的,可以通过了,如果最后一个环节不行就逐层往上走,看是哪一层出了问题。
对于不重要的链路,对数相对简单,比如如果连续几天新旧环境行数是一致的,那么就可以认为通过了;重要链路可能就要麻烦一些,需要核对指标,比如某个列的 sum 值,average 值,然后再去更长周期比对,确保一致才可以放心。
8. 业务部门的协作
与业务人员的合作中遇到过很多麻烦,业务方可能基于各种原因不配合迁移工作,**原因无外乎两个,一是没有时间,二是担心风险。**如果能解决这两个问题,那么用户积极性自然就上来了。
我们的做法是:第一,针对用户繁忙 ,我们把力所能及的事都处理掉,比如拷贝数据,重置偏移量,搭建测试环境等,到业务侧就只需要做简单的修改配置、重启进程、重启服务,这样就解决了时间不足的问题;第二,针对风险担忧 ,推功揽过,排除其后顾之忧;另外,还是要主次分明,有一些很琐碎问题,比如是否有人在外部直连我们的主服务,迁移是否有影响等等,只要抱着"做大放小、主次分明"的态度,问题就会迎刃而解。
--
04/高途成本管控现状及未来规划
下面分享下成本管控的现状和未来规划。
高途刚迁移完成时,在腾讯云上的成本相比平台自建时期降低了 40%。但随着业务重点发力成人与职业教育、素质教育,大数据计算和存储资源的使用量又开始快速增长,所以大数据平台需要进一步进行成本治理和资源利用率治理。
1. 成本管控的最终目的
成本管控的最终目的是什么?
很多人可能第一感觉就是省钱,降低支出,其实不然。我们的投入是要求产出的,如果花了 50 赚回 100,那么这 50 就花的值;我花了 20 结果都打水漂了,那 20 花的就不值。所以仅看投入支出,不看产出,实际上是一个错误的想法。
因此我们要提高利用率。那怎么提高利用率呢?
如果集群 CPU 利用率是 20%,现在提到 80%了,那么就做到成本管控了?这里有悖论,假如只写一个死循环,然后在后边一直刷单,那么 CPU 利用率肯定高涨,这其实是一个自欺欺人的伪命题,并没有真的做到成本管控。所以我们最终目的是提高有效利用率,既能把利用率提上去,还要减少浪费,这才是成本管控的最终目的。
那么如何提高利用率呢?
有两方面,一是存储资源,二是计算资源 。途径还是开源 和节流。
有 1 个必须维护的任务,以前可能花 10 个单位的成本,因为运用新技术后可能 5 个单位就解决了,这是开源 。原来任务得花 5 个单位的成本去维护,但是发现这个任务无人使用,后把它给将其下线,这就是节流。
2. 成本管控前的存储资源状态
先说一下存储资源当时的状态和问题,存储资源的浪费无外乎以下三点:
● 表空跑:表没人访问,还每天都在跑,还在生成新的数据;
● 分区膨胀 :有一些业务线的表是小时级,这样分区就过度膨胀,分区数量可能达到几千上万个;而且大家也感受到当分区数量过多的时候,重启hiveserver2,就会有相当长的时间一直在加载元数据,无法正常服务;
● 碎文件:主要来自 ods 层,因为我们是用 waterdrop 导入数据,该工具天然的存在一些碎文件问题,这样不仅给文件系统(不管是 hdfs namenode,还是我们现在使用的 cos)的中心进程带来巨大压力;当查表的时候,如果表里同样是 1GB 的数据,数据分散在 10 个文件里边和分散在 1 万个文件里边,效果也是不一样的,在1万个文件里边的话,可能 hive2 还没有把这个任务提交到 yarn,就因为内存不足任务先崩溃了。
以上就是存储资源实现成本管控要解决的三座大山。
3. 成本管控前的计算资源状态
上图是计算资源的状态。每天夜间会有大批量调度去执行,资源使用率飙到很高,接近100%;但是在白天的时候却显得风平浪静,仅在小时级任务执行时有轻微的波动,说明在白天存在极其严重的浪费,这些钱是白花的。
4. 表访问监控
对于表访问控制是怎么解决的?
● 传统监测方式:熟悉 metastore 人都了解可能见过,在关于表的元表 tbls 里边有一个列 LAST_ACCESS_TIME,这个列默认是不更新的,一直是 0;通过在 hive 配置中添加 PREHOOK,就能接收到 MapReduce 这种引擎的表访问记录,可以把时间戳更新;其缺点是只能记录 mapreduce 的访问,但我们还有其他数据引擎,比如 spark、impala、presto 的查询是记录不到的,所以它对我们监控表的访问有借鉴意义但覆盖得不够全面;
● 高途的改进:不论什么引擎来查表都要经过 metastore,所以我们在 metastore 里改写了 preEventListener ,metastore 监听到表被查询时,就去修改 tbls 表的 LAST_ACCESS_TIME 字段把时间记录下来;经过这个改进以后,所有来源的查询行为都真真切切的被记录到元数据里边了。
● 静默率:这时候我们引出了静默的概念,定义是一个表如果连续 30 天没有任何访问,它就是"静默"的;当时迁移上线以后发现我们的数仓里高达 80% 以上的表都处于静默状态,这也是一个很严重的浪费,需要进行管控。
监控了所有表的访问并统计了静默率后,前文提到的表的浪费和分区的浪费问题就可以解决了。
5. ODS表导入改造
下一个要解决的是碎文件问题。碎文件基本都来源于 ods 导入,不管是用传统的 Apache Sqoop、阿里 dataX,或者我们现在用的 waterdrop,天然都存在碎文件问题,原因如下:
● 碎文件产生原理:当拉数的时候,waterdrop 总是去算你取得切分键的最小值和最大值,然后根据两个极值及提交的并发度去算 span,即每一个 worker 的上下限额。比如要查的部分数据,最小的 ID=1 最大 ID=1,000,000,000(10亿),并发度设置是 10,000;所以要求就是每个 worker 查最多 10 万条记录,此时 worker1 条件就是 where ID>=1 and ID<100,001,worker2 条件是 where ID>=100,001 and ID<200,001,以此类推;但是数据的实际情况有可能是第一条记录 ID=1,第二条记录 ID 就已经是5亿多了,因为第一条数据奇异歧义的分布导致了整个任务分布向左拉伸,结果是很多任务的空跑,第一个 worker 可能产生 1 条数据的文件,中间这些都会产生行数为 0 的空文件,最后一个 worker 任务干了绝大部分的活但执行还慢,然后会产生很大的文件,甚至出现很多小文件或者碎文件,这是拉数时存在的问题;
高途的改进是,拉取数据的时候去扫描库里的切分键链,当然一般选主键,所以它的速度顺序还可以,然后根据我自己提供的 span 去拉数。
比如说我看的第一条数据 ID=1,并且要求每个 worker 就查 10 万条,然后第 100,001 条可能是 ID=a,那么 worker1 的查询条件就是 where ID>=1 and ID<a;第二十万条数据可能是 id=b;worker2 条件就是 where>=a and ID<b;这样的结果就是每一个 worker 拉取的行数都是一样的(但是最后一个 worker 除外,作为一个边界点,可能数据会比较少,其他 worker 行数完全一样),而且大家工作压力也是基本上均摊,所以执行速度提升上来了,而且小文件问题也解决掉了。
6. 表清理机制
解决了表静默、分区膨胀和静默,以及碎文件这三座大山,下一步就要提出制度 来实现我们的目的,存储成本管控,所以我们制定并执行了表清理机制。
● 静默表处理:首先针对相当时间内无人访问的表,特别是占用空间、分区数和文件数较大的表,优先处理 ,处理采用先通告再冷藏最后删除的方式;
● 开发规范:对开发环节的逻辑规范增加了要求,比如要建临时的任务里用的表,那么要加上关键词 temporary,这样会话结束以后,表名就消失掉了,别人不会看到,也会把数仓里一些垃圾清除掉;
● 机制执行效果:现在存储管控已经持续了一段时间,静默率从 80% 降到 40%,存储空间下降 5%,还在持续优化中。
7. 计算资源成本治理
和存储管控相比,高途现在计算资源管控才刚刚起步,目前很多地方还没有很直观的进展,预计可能 Q4 才能看到成效了。
我们规划了六步优化实现计算任务的成本治理,这里重点介绍两点,潮汐资源管理 和任务监控。
8. 调度资源潮汐式管理
潮汐资源管理是属于使用云原生的技术能力,依赖集群的容量调度的标签工具,在每天夜晚把资源扩容,保证能扛住夜间的调度高峰;然后到白天比如早上 8 点的时候,我们知道白天时间段可能不再用这么多资源,就把夜晚的扩容部分缩掉;假如按刚才说到的白天常规 30% 的资源使用率,就将这些作为常规储备,另外 70% 作为夜间的潮汐性扩容进来的资源(假定扩容资源每天只用 8 小时),这样计算成本也就是 30%,再加上 70% 乘以 1/3,也就只剩 51% 的综合成本了。
9. 任务消耗资源监控
任务的监控,依赖于 yarn rest API 周期性的收集平台跑的任务,要针对设定的阈值,比如这个任务占用 core 的核数超过了一定数量或超过了一个比例,或者资源超过了一定数量比例,而且持续时间达到了确定分钟数的话,就在企业内部 im 上给负责人发出报警,强制其整改,这样也能间接的把资源浪费问题解决掉。
10. 规划的技术替换
最后介绍一下未来规划:
● Paas 工具应用:可能有一些 Paas 工具可以较好地取代我们现有的某些系统,这样可以减轻我们自己的运维压力;
● 新技术应用:应用新技术,会对业务水平和输入能力有很大提高;
● 历史问题的处理:一些问题,比如 kudu/impala 这一板块运维能力差,会想办法迁走。
● 计划 Q4 验收:我们计划把整个成本再降低20%,实现有效管控。
--
05/问答环节
Q1:先迁移任务,再每日核对,再同步历史任务,会有读很久历史分区数据的任务,这样整条链路的数据都是不准确的,然后不能把所有的读取很久的历史分区数据的任务单独都捞取出来,所以说有什么好的办法?
A1:这种情况是说,如果你的上游不稳定的话,那么尽量把上一层数据都原样拷贝,从旧集群同步到新集群;每次只是检查当前这一块任务的一个准备性,验证条件是说我输入是确定的情况下,我的任务是不是准,而不是说连带的去校验我输入是否都正确,这是上一环节它考虑的事情。
Q2:对于选型,像腾讯云、阿里云、华为云等,从业务的角度来考虑的话,都会对比哪些?
A2:初期考虑的主要几项,一是经济成本 ,二是运维能力 ,还有很重要的是运维的责任心;当时来看我们选择的厂商它折扣还是很大的,对我们当前的状态是有很大帮助。
第二点是当时我们人员变动,运维的能力不够,当下的人力是不可能把这个迁移完全搞起来的,而那个时候腾讯云不仅有很多专家可以远程支持,甚至还派了一些人到我们现场驻扎来协助迁移环节,这些都是让我们很能接受的一个方面。
长期来说还是前边总结的五边形,我选用你们厂家,那么你们以后在技术方面打造的策略什么?你是固步自封一直还用当前这点一亩三分地,还是说以后如果是业内有新的技术方案,你就能相对及时的把它引进来?
还有迁移的是否容易,因为像刚才所说,每家的自研系统都带了自己的烙印,其实这是云厂商云产品所不能支持的,所以是我来兼容你还是你来兼容我,这些都是看出这个厂商是否可选的一点。
最后要强调稳定性,毋庸多言。
Q3:需要迁移的历史数据太多了,每天又不断写入,有的还不断刷新历史数据,这样写集群的数据的问题如何解决?
A3:这个问题确实存在着,当时我们以那个时间卡点,卡住以后,旧的集群还是会有一些数据重刷,所以这块确实也是一种比较 low 的方式。先看这个数据更新时间是晚于这个时间,然后在下一期增量更新的时候,可能问一下负责人他是需要你从旧集群里面拷贝到新的,还是在新集群里边去跑出来这部分数据。如果是他能接受新集群里边跑的话,这是简单的。如果他还要拷的话,那么只能我们费点劲给他拉过去,这确实没有太好办法,但是苦一阵子比苦一辈子要强吧。
今天的分享就到这里,谢谢大家。