技术干货|如何利用 ChunJun 实现数据离线同步?

这篇具有很好参考价值的文章主要介绍了技术干货|如何利用 ChunJun 实现数据离线同步?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ChunJun 是⼀款稳定、易⽤、⾼效、批流⼀体的数据集成框架,基于计算引擎 Flink 实现多种异构数据源之间的数据同步与计算。ChunJun 可以把不同来源、格式、特点性质的数据在逻辑上或物理上有机地集中,从⽽为企业提供全⾯的数据共享,目前已在上千家公司部署且稳定运⾏。

在之前,我们曾经为大家介绍过如何利用 ChunJun 实现数据实时同步(点击看正文),本篇将为大家介绍姊妹篇,如何利⽤ ChunJun 实现数据的离线同步。

ChunJun 离线同步案例

离线同步是 ChunJun 的⼀个重要特性,下⾯以最通⽤的 mysql -> hive 的同步任务来介绍离线同步。

配置环境

找⼀个空⽬录,接下来要配置 Flink 和 ChunJun 的环境,下⾯以 /root/chunjun_demo/ 为例⼦。

● 配置 Flink

下载 Flink

wget "http://archive.apache.org/dist/flink/flink-1.12.7/flink-1.12.7-bin-scala_2.12.tgz"
tar -zxvf chunjun-dist.tar.gz

● 配置 ChunJun

#下载 chunjun, 内部依赖 flink 1.12.7
wget https://github.com/DTStack/chunjun/releases/download/v1.12.8/chunjun-dist-1.12-SNAPSHOT.tar.gz
#新创建⼀个⽬录
mkdir chunjun && cd chunjun
#解压到指定⽬录
tar -zxvf chunjun-dist-1.12-SNAPSHOT.tar.gz

解压好的 ChunJun 有如下⽬录:
bin
chunjun-dist
chunjun-examples
lib

● 配置环境变量

#配置 Flink 环境变量
echo "FLINK_HOME=/root/chunjun_demo/flink-1.12.7" >> /etc/profile.d/sh.local
#配置 Chunjun 的环境变量
echo "CHUNJUN_DIST=/root/chunjun_demo/chunjun/chunjun-dist" >> /etc/profile.d/sh.local
#刷新换新变量
. /etc/profile.d/sh.local

● 在 Yarn 上⾯启动 Flink Session

#启动 Flink Session
bash $FLINK_HOME/bin/yarn-session.sh -t $CHUNJUN_DIST -d

输出如下:

echo "stop" | $FLINK_HOME/bin/yarn-session.sh -id application_1683599622970_0270
If this should not be possible, then you can also kill Flink via YARN's web interface or via:
yarn application -kill application_1683599622970_0270

下⾯提交任务会⽤到 Flink Session 这个 Yarn Application Id (application_1683599622970_0270)。

● 其他配置

如果⽤ parquet 格式,需要把 flink-parquet_2.12-1.12.7.jar 放⼊到 flink/lib 下⾯, 在上⾯的例⼦中,需要放到 $FLINK_HOME/lib ⾥⾯。

技术干货|如何利用 ChunJun 实现数据离线同步?

提交任务

● 在 MySQL 准备数据

-- 创建⼀个名为ecommerce_db的数据库,⽤于存储电商⽹站的数据
CREATE DATABASE IF NOT EXISTS chunjun;
USE chunjun;
-- 创建⼀个名为orders的表,⽤于存储订单信息
CREATE TABLE IF NOT EXISTS orders (
 id INT AUTO_INCREMENT PRIMARY KEY, -- ⾃增主键
 order_id VARCHAR(50) NOT NULL, -- 订单编号,不能为空
 user_id INT NOT NULL, -- ⽤户ID,不能为空
 product_id INT NOT NULL, -- 产品ID,不能为空
 quantity INT NOT NULL, -- 订购数量,不能为空
 order_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
-- 订单⽇期,默认值为当前时间戳,不能为空
);
-- 插⼊⼀些测试数据到orders表
INSERT INTO orders (order_id, user_id, product_id, quantity)
VALUES ('ORD123', 1, 101, 2),
       ('ORD124', 2, 102, 1),
       ('ORD125', 3, 103, 3),  
       ('ORD126', 1, 104, 1),
       ('ORD127', 2, 105, 5);
       
select * from chunjun.orders;       

如果没有 MySQL 的话,可以⽤ docker 快速创建⼀个。

docker pull mysql:8.0.12
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.12

● 创建 Hive 表

CREATE DATABASE IF NOT EXISTS chunjun;
USE chunjun;
-- 创建⼀个名为orders的表,⽤于存储订单信息
CREATE TABLE IF NOT EXISTS chunjun.orders (
 id INT,
 order_id VARCHAR(50),
 user_id INT,
 product_id INT,
 quantity INT,
 order_date TIMESTAMP
)
 STORED AS PARQUET;
-- 查看 hive 表,底层的 HDFS ⽂件位置,下⾯的 SQL 结果⾥⾯ Location 字段,就是 HDFS ⽂件的位置。
desc formatted chunjun.orders;
-- Location: hdfs://ns1/dtInsight/hive/warehouse/chunjun.db/orders
-- ⼀会配置同步任务的时候会⽤到 hdfs://ns1/dtInsight/hive/warehouse/chunjun.db/orders

● 在当前⽬录( /root/chunjun_demo/ ) 配置⼀个任务 mysql_hdfs.json

vim mysql_hdfs.json 输⼊如下内容:

{
"job": {
"content": [
 {
"reader": {
"parameter": {
"connection": [
 {
"schema": "chunjun",
"jdbcUrl": [ "jdbc:mysql://172.16.85.200:3306/chunjun" ],
"table": [ "orders" ]
 }
 ],
"username": "root",
"password": "123456",
"column": [
 { "name": "id", "type": "INT" },
 { "name": "order_id", "type": "VARCHAR" },
 { "name": "user_id", "type": "INT" },
 { "name": "product_id", "type": "INT" },
 { "name": "quantity", "type": "INT" },
 { "name": "order_date", "type": "TIMESTAMP" }
 ]
 },
"name": "mysqlreader"
 },
"writer": {
"parameter": {
"path": "hdfs://ns1/dtInsight/hive/warehouse/chunjun.db/orders",
"defaultFS": "hdfs://ns1",
"hadoopConfig": {
"dfs.nameservices": "ns1",
"dfs.ha.namenodes.ns1": "nn1,nn2",
"dfs.namenode.rpc-address.ns1.nn1": "172.16.85.194:9000",
"dfs.namenode.rpc-address.ns1.nn2": "172.16.85.200:9000",
"dfs.client.failover.proxy.provider.ns1":
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"
 },
"column": [
 { "name": "id", "type": "INT" },
 { "name": "order_id", "type": "VARCHAR" },
 { "name": "user_id", "type": "INT" },
 { "name": "product_id", "type": "INT" },
 { "name": "quantity", "type": "INT" },
 { "name": "order_date", "type": "TIMESTAMP" }
 ],
"writeMode": "overwrite",
"encoding": "utf-8",
"fileType": "parquet",
"fullColumnName":
 [ "id", "order_id", "user_id", "product_id", "quantity", "order_date"],
"fullColumnType":
 [ "INT", "VARCHAR", "INT", "INT", "INT", "TIMESTAMP" ]
 },
"name": "hdfswriter"
 }
 }
 ],
"setting": {
"errorLimit": {
"record": 0
 },
"speed": {
"bytes": 0,
"channel": 1
 }
 }
 }
}

因为我们要将 MySQL 同步到 Hive ⾥⾯,但是如果直接同步 Hive 的话,内部会⽤ jdbc,⽽ jdbc 的效率不⾼,因此我们可以直接把数据同步到 Hive 底层的 HDFS 上⾯,所以 writer ⽤到了 hdfswriter。脚本解析如下:

{
"job": {
"content": [
 {
"reader": {
"parameter": {
"connectionComment": "数据库链接, 数据库, 表, 账号, 密码",
"connection": [
 {
"schema": "chunjun",
"jdbcUrl": [ "jdbc:mysql://172.16.85.200:3306/chunjun" ],
"table": [ "orders" ]
 }
 ],
"username": "root",
"password": "123456",
"columnComment": "要同步的列选择, 可以选择部分列",
"column": [
 { "name": "id", "type": "INT" },
 { "name": "order_id", "type": "VARCHAR" },
 { "name": "user_id", "type": "INT" },
 { "name": "product_id", "type": "INT" },
 { "name": "quantity", "type": "INT" },
 { "name": "order_date", "type": "TIMESTAMP" }
 ]
 },
"nameComment" : "source 是 mysql",
"name": "mysqlreader"
 },
"writer": {
"parameter": {
"pathComment": "HDFS 上⾯的路径, 通过 hive 语句的 desc formatted 查看",
"path": "hdfs://ns1/dtInsight/hive/warehouse/chunjun.db/orders",
"defaultFS": "hdfs://ns1",
"hadoopConfigComment": "是 hdfs ⾼可⽤最基本的配置, 在 Hadoop 配置⽂件 hdfs-site.xml 可以找到",
"hadoopConfig": {
"dfs.nameservices": "ns1",
"dfs.ha.namenodes.ns1": "nn1,nn2",
"dfs.namenode.rpc-address.ns1.nn1": "172.16.85.194:9000",
"dfs.namenode.rpc-address.ns1.nn2": "172.16.85.200:9000",
"dfs.client.failover.proxy.provider.ns1":
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"
 },
"columnComment": "要同步的列选择, 可以选择部分列",
"column": [
 { "name": "id", "type": "INT" },
 { "name": "order_id", "type": "VARCHAR" },
 { "name": "user_id", "type": "INT" },
 { "name": "product_id", "type": "INT" },
 { "name": "quantity", "type": "INT" },
 { "name": "order_date", "type": "TIMESTAMP" }
 ],
"writeModeComment": "覆盖写⼊到 hdfs 上⾯的⽂件, 可选 overwrite, append(默认模式)",
"writeMode": "overwrite",
"encoding": "utf-8",
"fileTypeComment": "可选 orc, parquet, text",
"fileType": "parquet",
"fullColumnNameComment": "全部字段,有时候 column ⾥⾯同步部分字段,但是⼜需要有全部字段的格式,例如 fileType : text ",
"fullColumnName": [ "id", "order_id", "user_id", "product_id", "quantity", "order_date"], 
"fullColumnTypeComment": "全部字段的类型",
"fullColumnType": [ "INT", "VARCHAR", "INT", "INT", "INT", "TIMESTAMP" ]
 },
"nameComment" : "sink 是 hdfs",
"name": "hdfswriter"
 }
 }
 ],
"setting": {
"errorLimit": {
"record": 0
 },
"speed": {
"bytes": 0,
"channel": 1
 }
 }
 }
}

● 提交任务

bash chunjun/bin/chunjun-yarn-session.sh -job mysql_hdfs.json -confProp
{\"yarn.application.id\":\"application_1683599622970_0270\"}

● 查看任务

技术干货|如何利用 ChunJun 实现数据离线同步?
技术干货|如何利用 ChunJun 实现数据离线同步?

任务同步完成, 可以看⼀下 HDFS 上⾯的数据。

技术干货|如何利用 ChunJun 实现数据离线同步?

查看⼀下 Hive 表的数据。

技术干货|如何利用 ChunJun 实现数据离线同步?

注意, 如果是分区的 Hive 表,需要⼿动刷新⼀下 Hive 的元数据, 使⽤ MSCK 命令。(MSCK 是 Hive 中的⼀个命令,⽤于检查表中的分区,并将其添加到 Hive 元数据中)

MSCK REPAIR TABLE my_table;

ChunJun 离线同步原理解析

HDFS 文件同步原理

· 对于⽂件系统,同步的时候会先把⽂件写⼊到 path + [filename] ⽬录⾥⾯的 .data 的⽂件⾥⾯,如果任务失败,那么 .data ⾥⾯的⽂件不会⽣效。

· 在 TaskManager 上⾯所有 task 任务结束的时候,会在 JobManager 执⾏ FinalizeOnMaster 的 finalizeGlobal ⽅法, 最终会调⽤到 moveAllTmpDataFileToDir , 把 .data ⾥⾯的⽂件移除到 .data 的上⼀层。

public interface FinalizeOnMaster {

/**
The method is invoked on the master (JobManager) after all (parallel) instances of an OutputFormat finished.
Params:parallelism – The parallelism with which the format or functions was run.
Throws:IOException – The finalization may throw exceptions, which may cause the job to abort.
*/
void finalizeGlobal(int parallelism) throws IOException; 
}
// 在 JobManager 执⾏
@Override
protected void moveAllTmpDataFileToDir() {
if (fs == null) {
openSource();
 }
String currentFilePath = "";
try {
Path dir = new Path(outputFilePath);
Path tmpDir = new Path(tmpPath);

FileStatus[] dataFiles = fs.listStatus(tmpDir);
for (FileStatus dataFile : dataFiles) {
currentFilePath = dataFile.getPath().getName();
fs.rename(dataFile.getPath(), dir);
LOG.info("move temp file:{} to dir:{}", dataFile.getPath(), dir);
 }
fs.delete(tmpDir, true);
 } catch (IOException e) {
throw new ChunJunRuntimeException(
String.format(
"can't move file:[%s] to dir:[%s]", currentFilePath, outputFilePath),
e);
 }
}

增量同步

增量同步主要针对某些只有 Insert 操作的表,随着业务增⻓,表内数据越来越多。如果每次都同步整表的话,消耗的时间和资源会⽐较多。因此需要⼀个增量同步的功能,每次只读取增加部分的数据。

● 实现原理

其实现原理实际上就是配合增量键在查询的 sql 语句中拼接过滤条件,⽐如 where id > ? ,将之前已经读取过的数据过滤出去。

增量同步是针对于两个及以上的同步作业来说的。对于初次执⾏增量同步的作业⽽⾔,实际上是整表同步,不同于其他作业的在于增量同步作业会在作业执⾏完成后记录⼀个 endLocation 指标,并将这个指标上传到 prometheus 以供后续使⽤。

除第⼀次作业外,后续的所有增量同步作业都会取上⼀次作业的 endLocation 做为本次作业的过滤依据(startLocation)。⽐如第⼀次作业执⾏完后,endLocation 为10,那么下⼀个作业就会构建出例如 SELECT id,name,age from table where id > 10 的 SQL 语句,达到增量读取的⽬的。

● 使用限制

· 只有 RDB 的 Reader 插件可以使⽤

· 通过构建SQL过滤语句实现,因此只能⽤于RDB插件

· 增量同步只关⼼读,不关⼼写,因此只与Reader插件有关

· 增量字段只能为数值类型和时间类型

· 指标需要上传到 prometheus,⽽ prometheus 不⽀持字符串类型,因此只⽀持数据类型和时间类型,时间类型会转换成时间戳后上传

· 增量键的值可以重复,但必须递增

· 由于使⽤ '>' 的缘故,要求字段必须递增

断点续传

断点续传是为了在离线同步的时候,针对⻓时间同步任务如超过1天,如果在同步过程中由于某些原因导致任务失败,从头再来的话成本⾮常⼤,因此需要⼀个断点续传的功能从任务失败的地⽅继续。

● 实现原理

· 基于 Flink 的 checkpoint,在 checkpoint 的时候 会存储 source 端最后⼀条数据的某个字段值,sink 端插件执⾏事务提交。

· 在任务失败,后续通过 checkpoint 重新运⾏时,source 端在⽣成 select 语句的时候将 state ⾥的值作为条件拼接进⾏数据的过滤,达到从上次失败位点进⾏恢复。

技术干货|如何利用 ChunJun 实现数据离线同步?
· jdbcInputFormat 在拼接读取 SQL 时,如果从 checkpoint 恢复的 state 不为空且 restoreColumn 不为空,则此时会将 checkpoint ⾥的 state 作为起点开始读取数据。

● 适用场景

通过上述原理我们可以知道 source 端必须是 RDB 类型插件,因为是通过 select 语句拼接 where 条件进⾏数据过滤达到断点续传的,同时断点续传需要指定⼀个字段作为过滤条件,且此字段要求是递增的。

· 任务需要开启 checkpoint

· reader 为 RDB 的插件均⽀持且 writer ⽀持事务的插件(如 rdb filesystem 等),如果下游是幂等性则 writer 插件也不需要⽀持事务

· 作为断点续传的字段在源表⾥的数据是递增的,因为过滤条件是 >

《数栈产品白皮书》:https://www.dtstack.com/resources/1004?src=szsm

《数据治理行业实践白皮书》下载地址:https://www.dtstack.com/resources/1001?src=szsm

想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=szbky

同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术qun」,交流最新开源技术信息,qun号码:30537511,项目地址:https://github.com/DTStack文章来源地址https://www.toymoban.com/news/detail-450193.html

到了这里,关于技术干货|如何利用 ChunJun 实现数据离线同步?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【大数据进阶第三阶段之Datax学习笔记】使用阿里云开源离线同步工具DataX 实现数据同步

    【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述  【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax快速入门   【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图 【大数据进阶第三阶段之Datax学习笔记】使

    2024年01月24日
    浏览(42)
  • 揭秘 ChunJun:如何实现 e2e&session 日志隔离

    本文将从 e2e 的基本介绍,e2e 的使用与扩展,session 日志隔离三个维度为大家带来 ChunJun e2e session 日志隔离的分享。 大量具体代码和演示请看视频教程⬇️ 视频课程: https://www.bilibili.com/video/BV1ru411P7oZ/?spm_id_from=333.999.0.0 课件获取: https://www.dtstack.com/resources/1052?src=szsm ChunJu

    2024年02月08日
    浏览(32)
  • 利用MQ实现mysql与elasticsearch数据同步

    1.声明exchange、queue、RoutingKey 2. 在hotel-admin中进行增删改(SQL),完成消息发送 3. 在hotel-demo中完成消息监听,并更新elasticsearch数据 4. 测试同步 我这里的mq是挂在了docker上,虚拟机地址是192.168.116.128。到时候这个根据自己的项目改就行 在hotel-demo中,定义配置类,声明队列、交

    2024年02月09日
    浏览(25)
  • 十万字图文详解mysql、redis、kafka、elasticsearch(ES)多源异构不同种类数据库集成、数据共享、数据同步、不同中间件技术实现与方案,如何构建数据仓库、数据湖、数仓一体化?

    数据库大数据量、高并发、高可用解决方案,十万字图文详解mysql、redis、kafka、elasticsearch(ES)多源异构不同种类数据库集成、数据共享、数据同步、不同中间件技术实现与方案,如何构建数据仓库、数据湖、数仓一体化?Delta Lake、Apache Hudi和Apache Iceberg数仓一体化技术架构

    2024年02月07日
    浏览(38)
  • 离线数仓同步数据1

    com.atguigu.gmall.flume.interceptor.TimestampInterceptor$Builder

    2024年02月10日
    浏览(27)
  • 如何利用纯前端技术,实现一个网页版视频编辑器?

    介绍:本篇文章打算利用纯前端的技术,来实现一个网页版的视频编辑器。为什么突然想做一个这么项目来呢,主要是最近一直在利用手机剪映来剪辑一些照片或者视频之类的,在剪辑的过程中,突然想到,有没有一种纯网页版的视频剪辑网站呢?于是搜了下,大多为 sass 成

    2024年04月27日
    浏览(32)
  • docker环境安装mysql、canal、elasticsearch,基于binlog利用canal实现mysql的数据同步到elasticsearch中

    🚀 本文提供的指令完全可以按顺序逐一执行,已进行了多次测试。因此如果你是直接按照我本文写的指令一条条执行的,而非自定义修改过,执行应当是没有任何问题的。 🚀 本文讲述:使用docker环境安装mysql、canal、elasticsearch,基于binlog利用canal实现mysql的数据同步到elas

    2024年02月02日
    浏览(38)
  • 【技术干货】如何快速创建商用照明 OEM APP?

    本文介绍了如何在涂鸦 IoT 平台的 App 工作台上创建一款体验版商照 App、正式版 OEM App、上架 App、以及完成通用配置。 创建 App 登录 涂鸦 IoT 平台的 App 页面。 单击  创建APP ,选择  商照 APP  进行创建。 在提示框里,完善 App 信息,然后仔细阅读并勾选《OEM APP 服务及软件使

    2024年02月07日
    浏览(25)
  • Kafka 集群如何实现数据同步?

    哈喽大家好,我是咸鱼 最近这段时间比较忙,将近一周没更新文章,再不更新我那为数不多的粉丝量就要库库往下掉了 T﹏T 刚好最近在学 Kafka,于是决定写篇跟 Kafka 相关的文章(文中有不对的地方欢迎大家指出) 考虑到有些小伙伴可能是第一次接触 Kafka ,所以先简单介绍

    2024年02月05日
    浏览(31)
  • 深入数仓离线数据同步:问题分析与优化措施

    在数据仓库领域,离线数仓和实时数仓是常见的两种架构类型。离线数仓一般通过定时任务在特定时间点(通常是凌晨)将业务数据同步到数据仓库中。这种方式适用于对数据实时性要求不高,更侧重于历史数据分析和报告生成的场景。 然而,采用离线同步方式可能会引发业

    2024年01月23日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包