目錄
一、設計思路與方案
1、思路
我的需求:從MySQL 按時間增量同步到 SQLServer,MySQL中的數據會源源不斷的寫入,不會刪除數據, SQLServer根據 MySQL表中的 modifytime 做增量同步就好,三臺阿里雲機器做數據的接入、計算、同步。
下面是網友的設計思路:
假定在源數據表中有一個字段會記錄數據的新增或修改時間(modifytime),可以通過它對數據在時間維度上進行排序。通過中間表記錄每次更新的時間戳,在下一個同步週期時,通過這個時間戳同步該時間戳以後的增量數據。這是時間戳增量同步。
但是時間戳增量同步不能對源數據庫中歷史數據的刪除操作進行同步,我們可以通過在每次同步時,把時間戳往前回滾一段時間,從而同步一定時間段內的刪除操作。這就是時間戳增量回滾同步,這個名字是我自己給取得,意會即可,就是在時間戳增量同步的同時回滾一定的時間段(參考的https://blog.csdn.net/dora_310/article/details/80511793 )。
說明:
- 源數據表 需要被同步的數據表
- 目標數據表 同步至的數據表
- 中間表 存儲時間戳的表
2、方案
1、剛開始接觸到這個需求,我就抱着學習的態度,因爲kettle沒怎麼用過,覺得應該不難,解決方案的話就是如下的操作,別人的:
2、後面的話我參考了同事的一種設計方式
下面這種方式是 源數據庫 與目標數據庫 保持一致,有源數據庫表記錄刪除,這個是整張表數據的同步,兩張表的數據是一致的。
3、從需求的實際出發,我選擇博客上網友的設計,但是我沒有刪除時間戳及其以後的數據,意會我的設計即可
說明:Kettle根據時間戳增量同步兩張表的數據從MySQL到SQLServer,時間戳表 etl_last_jobtime 字段last_timestamp記錄每次作業開始時的當前時間(數據同步) ,作業完成後根據ID 更新相應表的 last_timestamp 字段,增量獲取數據時 modifytime字段 大於等於上次記錄的 last_timestamp 字段, 作業開始記錄當前時間防止 作業執行的時間長而丟失數據。
3、總體流程
- 開始組建
- 設置config_path
- 建時間戳表
- 獲取中間表的時間戳,並設置爲全局變量
- 數據的插入或更新
- 更新時間戳
其實,這裏的設計和上面網友的設計基本思路是一樣的, 區別有兩點:
- 我的臨時表 時間戳沒有把表中的 modifyTime字段 排序 取最新值,因爲排序取值性能這塊不好,我們的需求也不需要這樣做,因爲源數據表中的數據是不斷寫入的,記錄當前時間就可以(now()),然後 表中數據的 modifytime 又會不斷的更新,下次取數據的時候,我只需要 (modifytime >= last_timestamp) ,我的設計如此,數據重複與丟失考慮的不是很多。
- 考慮到作業的執行也需要時間,這個 當前時間(now()),在作業一開始就給了,作業執行完後,更新這個 last_timestamp ,設計可能存在問題,時間戳回滾也考慮過,但是沒想好回滾多長時間合適,數據丟失或重複的可能也存在,數據不能丟失就好,項目搭建測試中
二、實現步驟
2.1、創建作業和DB連接
打開Spoon工具(java環境),新建作業,然後在左側主對象樹DB連接中新建DB連接。創建連接並測試通過後可以在左側DB連接下右鍵共享出來。因爲在單個作業或者轉換中新建的DB連接都是局域數據源,在其他轉換和作業中是不能使用的,即使屬於同一個作業下的不同轉換,所以需要把他們共享,這樣DB連接就會成爲全局數據源,不用多次編輯,提醒添加相應數據庫的驅動。
2.2、創建時間戳表
這張表的話,一開始就是建好的,這個表一定存在的,沒有使用 SQL 腳本在作業中創建 ,考慮到 SQLServer 不熟,我將中間表建在 源數據庫中 etl_last_jobtime,不同的表根據 ID 取時間戳,爲了表信息易維護增加了 table_info字段。
CREATE TABLE IF NOT EXISTS
etl_last_jobtime(
id int(11) NOT NULL PRIMARY KEY,
table_info varchar(32) NOT NULL,
last_timestamp TIMESTAMP NOT NULL comment '最近一次同步數據時間'
);
-- 插入初始的時間
INSERT IGNORE etl_last_jobtime(id ,table_info,last_timestamp) VALUES(1,'表1信息', '1998-07-02 15:30:00');
INSERT IGNORE etl_last_jobtime(id ,table_info,last_timestamp) VALUES(2,'表2信息', '1998-07-02 15:30:00');
2.3、獲取時間戳並設爲變量
這一步使用到了 表輸入和 設置標量, nowTime 就是作業剛開始運行的時間,估計存在偏差還在測試中,想法是這樣的,因爲作業的執行需要時間,每次數據同步的時間可能不等,所以作業開始執行或者沒有開始執行時就獲取 這個時間戳,然後作業開始執行,這就好比是回滾時間,只不過是根據每次同步作業的執行時間決定的,這塊考慮到這塊數據一定不能丟失,所以使用了 大於等於 取數據。
2.4、插入更新
這一步是真正的同步增量同步,完成數據的更新和插入
2.5、更新時間戳
將 etl_last_jobtime 中 last_timestamp 字段的更新放在最後一步。
update etl_last_jobtime set last_timestamp='${NOWTIME}' where id=1;
id =1 的時候更新 last_timestamp 等於 前面作業開始是 獲取的 nowTime
2.6、配置數據源加載外部文件
具體可以參考Kettle配置數據源時加載外部properties配置文件:https://www.jianshu.com/p/ac7c0566d782
1、配置config.properties 文件,設置變量
2、作業空表處雙擊,設置作業參數,設置變量就是爲了將 配置的命名參數獲取到,從而獲取到 配置文件 config.properties
config.properties文件配置
3、使用配置文件連接數據庫
4、linux 中運行 作業的腳本
這裏我們使用真實環境的測試運行,使用腳本執行作業,後面也可以定時調度。
#!/bin/bash
###############################
#
#
#
#
###############################
set -x
date=`date +%Y-%m-%d`
jobPath=`cd $(dirname $0);pwd`
cd /hadoop/software/kettle/data-integration/
./kitchen.sh -file=${jobPath}/data_sync.kjb -param:"config_path=${jobPath}/config.properties"
說明:作業沒有運行,configPath 的配置信息是沒有加載進內存的,在左側 DB 連接 測試數據庫連接是會報錯的,可以先運行作業,作業執行完 start->設置configPath 後會將配置信息加載進內存中,這樣配置文件的信息就可以獲取到了。
C:\Users\yangxu\.kettle\shared.xml.backup 這塊可以看到配置的數據庫信息。
將以上的作業、數據庫配置文件、作業運行的腳本在本地測試沒問題後打包(zip unzip)上傳到 linux 測試機,運行腳本即可。
以上就是數據同步的個人記錄,後期測試結果,會繼續分享。
最後說一下:儘量將轉換抽離,不要放在一個轉換中,尤其是有多個 SQL腳本需要執行的轉換 執行的順序 可能不是串行,可以參考:https://mp.csdn.net/console/editor/html/106633806,這樣做也方便測試。
kettle轉換裏面sql腳本的執行順序:https://blog.csdn.net/u012848709/article/details/65626634
參考博客:使用Kettle實現數據實時增量同步https://blog.csdn.net/dora_310/article/details/80511793
kettle轉換裏面sql腳本的執行順序:https://blog.csdn.net/u012848709/article/details/65626634
kettle的轉換裏面sql腳本執行順序以執行次數:https://blog.csdn.net/u012848709/article/details/67679366