数据同步到数仓解决方案

一、概述

在数据仓库建模中,未经任何加工处理的原始业务层数据,称之为ODS(Operational Data Store)数据。在互联网企业中,常见的ODS数据有业务日志数据(Log)和业务DB数据(DB)两类。对于业务DB数据来说,从MySQL等关系型数据库的业务数据进行采集,然后导入到数据仓库。

一般常用的解决方案是批量取数并Load:直连MySQL去Select表中的数据,然后存到本地文件作为中间存储,最后把文件Load到数据仓库的表中。

这种方案的优点是实现简单,但是随着业务的发展,缺点也逐渐暴露出来:

  • 直接从MySQL中Select大量数据,对MySQL的影响非常大,容易造成慢查询,影响业务线上的正常服务
  • 性能瓶颈:随着业务规模的增长,Select From MySQL -> Save to Localfile -> Load to Hive这种数据流花费的时间越来越长,无法满足下游数仓生产的时间要求。

为了彻底解决这些问题,我们逐步转向CDC (Change Data Capture) + Merge的技术方案,即实时Binlog采集 + 离线处理Binlog还原业务数据这样一套解决方案。(Binlog是MySQL的二进制日志,记录了MySQL中发生的所有数据变更,MySQL集群自身的主从同步就是基于Binlog做的)

二、整体架构

数据仓库问题 数据仓库解决方案_big data

在Binlog实时采集方面,我们采用了阿里巴巴的开源项目Canal,负责从MySQL实时拉取Binlog并完成适当解析。Binlog采集后会暂存到Kafka上供下游消费。整体实时采集部分如图中红色箭头所示。离线处理Binlog的部分,如图中黑色箭头所示。

优点:

  • 第一Binlog是流式产生的,通过对Binlog的实时采集,把部分数据处理需求由每天一次的批处理分摊到实时流上。无论从性能上还是对MySQL的访问压力上,都会有明显地改善。
  • 第二,Binlog本身记录了数据变更的类型(Insert/Update/Delete),通过一些语义方面的处理,完全能够做到精准的数据还原。

三、Merge

Binlog成功入仓后,下一步要做的就是基于Binlog对MySQL数据进行还原。Merge流程做了两件事,首先把当天生成的Binlog数据存放到Delta表中,然后和已有的存量数据做一个基于主键的Merge。Delta表中的数据是当天的最新数据,当一条数据在一天内发生多次变更时,Delta表中只存储最后一次变更后的数据。

把Delta数据和存量数据进行Merge的过程中,需要有唯一键来判定是否是同一条数据。如果同一条数据既出现在存量表中,又出现在Delta表中,说明这一条数据发生了更新,则选取Delta表的数据作为最终结果;否则说明没有发生任何变动,保留原来存量表中的数据作为最终结果。Merge的结果数据会Insert Overwrite到原表中,即图中的origindb.table。

数据仓库问题 数据仓库解决方案_数据库_02

四、总结

随着业务规模的扩大,MySQL的分库分表情况越来越多,很多业务的分表数目都在几千个这样的量级。因此,我们需要在ODS层就完成分表的聚合。首先,在Binlog实时采集时,我们支持把不同DB的Binlog写入到同一个Kafka Topic。第二,Merge任务的配置支持正则匹配。通过配置符合业务分表命名规则的正则表达式,Merge任务就能了解自己需要聚合哪些MySQL表的Binlog,从而选取相应分区的数据来执行。