ChunJun は、安定した、使いやすい、高効率のバッチフロー統合データ統合フレームワークであり、コンピューティング エンジン Flink に基づいて、複数の異種データ ソース間のデータ同期とコンピューティングを実現します。ChunJun は、さまざまなソース、形式、特性からのデータを論理的または物理的に一元化し、企業に包括的なデータ共有を提供することができ、数千の企業に導入され、安定して稼働しています。
以前、 ChunJun を使用してリアルタイムのデータ同期を実現する方法(クリックすると本文が表示されます) を紹介しましたが、この記事では関連記事、ChunJun を使用してオフライン データ同期を実現する方法を紹介します。
ChunJunオフライン同期事例
オフライン同期は ChunJun の重要な機能です。以下では、最も一般的な mysql -> hive 同期タスクを使用して、オフライン同期を導入しています。
構成環境
空のディレクトリを見つけて、Flink と ChunJun の環境を設定します (例として /root/chunjun_demo/ を使用します)。
● フリンクの設定
フリンクをダウンロード
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 セッションを開始する
#启动 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 セッションの Yarn アプリケーション ID (application_1683599622970_0270) は、以下のタスクを送信するために使用されます。
●その他の構成
Parquet 形式を使用する場合は、flink-parquet_2.12-1.12.7.jar を flink/lib に配置する必要があります (上記の例では $FLINK_HOME/lib に配置する必要があります)。
タスクを送信する
● 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 にデータを直接同期できるため、ライターは 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\"}
● タスクの表示
タスクの同期が完了すると、HDFS 上のデータを確認できるようになります。
Hive テーブルのデータを見てください。
パーティション分割された Hive テーブルの場合は、MSCK コマンドを使用して Hive メタデータを手動で更新する必要があることに注意してください。(MSCK は、テーブル内のパーティションをチェックし、それらを Hive メタデータに追加する Hive のコマンドです)
MSCK REPAIR TABLE my_table;
ChunJun オフライン同期原理の分析
HDFS ファイル同期原理
· ファイル システムの場合、同期時にファイルはパス + [ファイル名] ディレクトリにある .data ファイルに書き込まれます。タスクが失敗した場合、.data 内のファイルは生成されません。
· TaskManager 上のすべてのタスクが完了すると、FinalizeOnMaster の FinalizeGlobal メソッドが JobManager 上で実行され、最後に moveAllTmpDataFileToDir が呼び出され、.data 内のファイルが .data の上位レベルに削除されます。
パブリック インターフェイス 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);
}
}
増分同期
増分同期は主に、挿入操作のみを行う特定のテーブルに対して行われます。ビジネスが成長するにつれて、テーブル内のデータは増加します。テーブル全体が毎回同期されると、より多くの時間とリソースが消費されます。したがって、インクリメンタル同期機能が必要となり、毎回データの増加部分のみが読み取られます。
●実施原則
実際の実装の原理は、クエリの SQL ステートメント内のフィルター条件を、where id > ? などのインクリメント キーと結合して、以前に読み取られたデータをフィルターで除外することです。
増分同期は、2 つ以上の同期ジョブを対象とします。初めて増分同期を実行するジョブでは、実際にはテーブル全体が同期されます。他のジョブと異なるのは、増分同期ジョブはジョブの実行後に endLocation インジケーターを記録し、このインジケーターを prometheus にアップロードしてさらに実行することです。その後の使用のために。
最初のジョブを除き、後続のすべての増分同期ジョブは、前のジョブの endLocation をこのジョブのフィルター基準 (startLocation) として使用します。たとえば、最初のジョブが実行され、endLocation が 10 になった後、次のジョブは、増分読み取りの目的を達成するために、id > 10 のテーブルから SELECT id,name,age などの SQL ステートメントを構築します。
●使用制限について
・RDB Readerプラグインのみ使用可能
SQL フィルター ステートメントを構築することによって実装されるため、RDB プラグインにのみ使用できます
· 増分同期は書き込みではなく読み取りのみを考慮するため、Reader プラグインにのみ関連します
· 増分フィールドには数値型と時間型のみを使用できます
· インジケーターは prometheus にアップロードする必要があります。prometheus は文字列型をサポートしていないため、データ型と時刻型のみがサポートされます。時刻型はタイムスタンプに変換されてアップロードされます。
· インクリメントキー値は繰り返すことができますが、インクリメントする必要があります
· 「>」を使用しているため、必須フィールドをインクリメントする必要があります
http
ブレークポイント レジュームはオフライン同期用です。1 日以上の長時間にわたる同期タスクの場合、同期プロセス中に何らかの理由でタスクが失敗した場合、最初から開始すると非常にコストがかかります。そのため、ブレークポイント レジュームは渡された関数は、タスクが失敗したところから続行されます。
●実施原則
· Flink のチェックポイントに基づいて、ソース側の最後のデータの特定のフィールド値がチェックポイント中に保存され、シンク側プラグインがトランザクションの送信を実行します。
· タスクが失敗し、その後チェックポイントを通じて再実行されると、ソース側は、最後の障害点から回復するために、select ステートメントの生成時にデータをフィルターするための条件として状態の値を使用します。
· jdbcInputFormat が SQL を結合して読み取るときに、チェックポイントから復元された状態が空でなく、restoreColumn も空でない場合は、チェックポイントの状態がデータの読み取りを開始する開始点として使用されます。
● 適用可能なシナリオ
上記の原理により、ブレークポイント再開を実現するために select ステートメントを where 条件で結合することによってデータ フィルタリングが実現されるため、ソース エンドが RDB タイプのプラグインである必要があることがわかります。フィルタ条件としてフィールドを指定する必要があり、このフィールドの要件は増分です。
· タスクはチェックポイントを有効にする必要があります
リーダーはすべての RDB プラグインでサポートされるプラグインであり、ライターはトランザクション (rdb ファイルシステムなど) をサポートします。ダウンストリームが冪等である場合、ライター プラグインはトランザクションをサポートする必要はありません
· フィルター条件が > であるため、ブレークポイントとして再開されるフィールドのソース テーブル内のデータは増分です。
「Dutstack 製品ホワイトペーパー」: https://www.dtstack.com/resources/1004?src=szsm
「データ ガバナンス業界実践ホワイト ペーパー」ダウンロード アドレス: https://www.dtstack.com/resources/1001?src=szsm Kangaroo Cloud のビッグデータ製品、業界ソリューション、顧客事例について詳しく知りたい、相談したい場合は、 Kangaroo Cloud 公式 Web サイトにアクセスしてください: https://www.dtstack.com/?src=szkyzg
同時に、ビッグデータのオープンソース プロジェクトに興味のある学生は、最新のオープンソース テクノロジー情報を交換するために「Kangaroo Cloud Open Source Framework DingTalk Technology qun」に参加することを歓迎します。qun 番号: 30537511、プロジェクト アドレス: https: // github.com/DTStack