数仓学习|几种常见的数据同步方式

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
简介: 笔记

前言


数据仓库的特性之一是集成,即首先把未经过加工处理的、不同来源的、不同形式的数据同步到ODS层,一般情况下,这些ODS层数据包括日志数据和业务DB数据。对于业务DB数据而言(比如存储在MySQL中),将数据采集并导入到数仓中(通常是Hive或者MaxCompute)是非常重要的一个环节。


那么,该如何将业务DB数据高效准确地同步到数仓中呢?


一般企业会使用两种方案:


直连同步

实时增量同步(数据库日志解析)

其中直连同步的基本思路是直连数据库进行SELECT,然后将查询的数据存储到本地文件作为中间存储,最后把文件Load到数仓中。这种方式非常的简单方便,但是随着业务的发展,会遇到一些瓶颈,具体见下文分析。


为了解决这些问题,一般会使用实时增量的方式进行数据同步,其基本原理是CDC (Change Data Capture) + Merge,即实时Binlog采集 + 离线处理Binlog还原业务数据这样一套解决方案。


(1)常见数据同步方式


(1.1)直连同步

直连同步是指通过定义好的规范接口API和基于动态链接库的方式直接连接业务库,比如ODBC/JDBC等规定了统一的标准接口,不同的数据库基于这套标准提供规范的驱动,从而支持完全相同的函数调用和SQL实现。比如经常使用的Sqoop就是采取这种方式进行批量数据同步的。


直连同步的方式配置十分简单,很容易上手操作,比较适合操作型业务系统的数据同步,但是会存在以下问题:


数据同步时间:随着业务规模的增长,数据同步花费的时间会越来越长,无法满足下游数仓生产的时间要求。

性能瓶颈(关键):直连数据库查询数据,对数据库影响非常大,容易造成慢查询,如果业务库没有采取主备策略,则会影响业务线上的正常服务,如果采取了主备策略,虽然可以避免对业务系统的性能影响,但当数据量较大时,性能依然会很差。

60.png


(1.2)实时增量同步(日志解析)

所谓日志解析,即解析数据库的变更日志,比如MySQL的Binlog日志,Oracle的归档日志文件。通过读取这些日志信息,收集变化的数据并将其解析到目标存储中即可完成数据的实时同步。这种读操作是在操作系统层面完成的,不需要通过数据库,因此不会给源数据库带来性能上的瓶颈。


数据库日志解析的同步方式可以实现实时与准实时的同步,延迟可以控制在毫秒级别的,其最大的优势就是性能好、效率高,不会对源数据库造成影响,目前,从业务系统到数据仓库中的实时增量同步,广泛采取这种方式。当然,这种方式也会存在一些问题,比如批量补数时造成大量数据更新,日志解析会处理较慢,造成数据延迟。除此之外,这种方式比较复杂,投入也较大,因为需要一个实时的抽取系统去抽取并解析日志,下文会对此进行详细解释。70.jpg61.png

如上图所示架构,在直连同步基础之上增加了流式同步的链路,经过流式计算引擎把相应的 Binlog 采集到 Kafka,同时会经过一个 Kafka 2Hive 的程序把它导入到原始数据,再经过一层 Merge,产出下游需要的 ODS 数据。


上述的数据集成方式优势是非常明显的,把数据传输的时间放到了 T+0 这一天去做,在第二天的时候只需要去做一次 merge 就可以了。非常节省时间和计算资源。


两种数据同步方式比较:



(2)流式数据集成实现


实现思路

71.png

首先,采用Flink负责把Kafka上的Binlog数据拉取到HDFS上,生成增量表。


然后,对每张ODS表,首先需要一次性制作快照(Snapshot),把MySQL里的全量数据读取到Hive上,这一过程底层采用直连MySQL去Select数据的方式,可以使用Sqoop进行一次性全量导入,生成一张全量表。


最后,对每张ODS表,每天基于全量数据和当天增量产生的Binlog做Merge,从而还原出业务数据。


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


关于Binlog解析部分,可以使用canal工具,采集到Kafka之后,可以使用Flink解析kafka数据并写入到HDFS上,解析kafka的数据可以使用Flink的DataStreamAPI,也可以使用FlinkSQL的canal-json数据源格式进行解析,使用FlinkSQL相对来说是比较简单的。下面是canal-json格式的kafka数据源。

CREATE TABLE region (
  id BIGINT,
  region_name STRING
) WITH (
 'connector' = 'kafka',
 'topic' = 'mydw.base_region',
 'properties.bootstrap.servers' = 'kms-3:9092',
 'properties.group.id' = 'testGroup',
 'format' = 'canal-json' ,
 'scan.startup.mode' = 'earliest-offset' 
);

数据解析完成之后,下面的就是合并还原完整数据的过程,关于合并还原数据,一种比较常见的方式就是全外连接(FULL OUTER JOIN)。具体如下:

生成增量表与全量表的Merge任务,当天的增量数据与昨天的全量数据进行全外连接,该Merge任务的基本逻辑是:

INSERT OVERWRITE TABLE user_order PARTITION(ds='20211012')
SELECT  CASE    WHEN n.id IS NULL THEN o.id 
                ELSE n.id 
        END
        ,CASE    WHEN n.id IS NULL THEN o.create_time 
                 ELSE n.create_time 
         END
        ,CASE    WHEN n.id IS NULL THEN o.modified_time
                 ELSE n.modified_time 
         END
        ,CASE    WHEN n.id IS NULL THEN o.user_id 
                 ELSE n.user_id 
         END
        ,CASE    WHEN n.id IS NULL THEN o.sku_code 
                 ELSE n.sku_code 
         END
        ,CASE    WHEN n.id IS NULL THEN o.pay_fee
                 ELSE n.pay_fee 
         END
FROM    (
            SELECT  *
            FROM    user_order_delta
            WHERE   ds = '20211012'
            AND     id IS NOT NULL
            AND     user_id IS NOT NULL
        ) n
FULL OUTER JOIN (-- 全外连接进行数据merge
                    SELECT  *
                    FROM    user_order
                    WHERE   ds = '20211011'
                    AND     id IS NOT NULL
                    AND     user_id IS NOT NULL
                ) o
ON      o.id = n.id
AND     o.user_id = n.user_id
;

经过上述步骤,即可将数据还原完整。


相关实践学习
AnalyticDB MySQL海量数据秒级分析体验
快速上手AnalyticDB MySQL,玩转SQL开发等功能!本教程介绍如何在AnalyticDB MySQL中,一键加载内置数据集,并基于自动生成的查询脚本,运行复杂查询语句,秒级生成查询结果。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
相关文章
|
3月前
|
SQL HIVE
数仓学习-----named_struct和collect_set函数
数仓学习-----named_struct和collect_set函数
|
2月前
|
消息中间件 SQL Kafka
离线数仓(四)【数仓数据同步策略】(1)
离线数仓(四)【数仓数据同步策略】
|
2月前
|
消息中间件 关系型数据库 Kafka
深入理解数仓开发(二)数据技术篇之数据同步
深入理解数仓开发(二)数据技术篇之数据同步
|
2月前
|
消息中间件 JSON 分布式计算
离线数仓(四)【数仓数据同步策略】(3)
离线数仓(四)【数仓数据同步策略】
|
2月前
|
消息中间件 JSON Java
离线数仓(四)【数仓数据同步策略】(4)
离线数仓(四)【数仓数据同步策略】
|
2月前
|
canal 关系型数据库 MySQL
离线数仓(四)【数仓数据同步策略】(2)
离线数仓(四)【数仓数据同步策略】
|
3月前
|
存储 JSON 数据处理
数仓学习---数仓开发之DWD层
数仓学习---数仓开发之DWD
283 6
数仓学习---数仓开发之DWD层
|
3月前
|
存储 NoSQL 数据处理
Apache Paimon流式湖仓学习交流群成立
Apache Paimon流式湖仓学习交流群成立
335 59
|
3月前
|
数据挖掘 数据库
数仓学习---数仓开发之DIM层
数仓学习---数仓开发之DIM层 维度建模、维度表介绍、
315 1
|
3月前
|
数据格式
数仓学习---数仓开发之ODS层
数仓学习---数仓开发之ODS层
649 2

热门文章

最新文章