背景
MySQL
數(shù)據(jù)庫中,設(shè)備歷史數(shù)據(jù)單表過億,如何快速、低成本地遷移到 TDengine3.x
中?
從標(biāo)題可以看出,我們使用的數(shù)據(jù)遷移/同步工具是 DataX
,數(shù)據(jù)源( Source
)為傳統(tǒng)的關(guān)系型數(shù)據(jù)庫 MySQL
,目標(biāo)庫( Sink
)為新型的具有場景特色的時序數(shù)據(jù)庫 TDengine
。
DataX:是阿里云DataWorks數(shù)據(jù)集成的開源版本,在阿里巴巴集團(tuán)內(nèi)被廣泛使用的離線數(shù)據(jù)同步工具/平臺。 DataX
實(shí)現(xiàn)了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS, databend 等各種異構(gòu)數(shù)據(jù)源之間高效的數(shù)據(jù)同步功能。
MySQL:略。。
TDengine:是一款開源、高性能、云原生的時序數(shù)據(jù)庫 (Time-Series Database, TSDB)。 TDengine
能被廣泛運(yùn)用于物聯(lián)網(wǎng)、工業(yè)互聯(lián)網(wǎng)、車聯(lián)網(wǎng)、 IT
運(yùn)維、金融等領(lǐng)域。除核心的時序數(shù)據(jù)庫功能外, TDengine
還提供緩存、數(shù)據(jù)訂閱、流式計(jì)算等功能,是一極簡的時序數(shù)據(jù)處理平臺,最大程度的減小系統(tǒng)設(shè)計(jì)的復(fù)雜度,降低研發(fā)和運(yùn)營成本。
從 MySQL
到 TDengine3.x
進(jìn)行數(shù)據(jù)遷移,即面臨異構(gòu)數(shù)據(jù)的遷移。首先要了解下 MySQL
與 TDengine
的數(shù)據(jù)模型方面的區(qū)別,具體可參考濤思數(shù)據(jù)官方提供的一個關(guān)于電表數(shù)據(jù)的模型對比:寫給MySQL開發(fā)者的 TDengine入門指南。
數(shù)據(jù)模型
以水庫水位監(jiān)測的案例說明,在 MySQL
中我們會有1張?jiān)O(shè)備信息表(設(shè)備編號、廠家、型號等信息)和1張?jiān)O(shè)備數(shù)據(jù)表(傳感器采集的時序數(shù)據(jù))。
針對 MySQL
中的2張表,以 TDengine
的設(shè)計(jì)思想來建模:在遷移到 TDengine
后會變成1張超級表+N(設(shè)備的數(shù)量)張子表,且每張子表的名稱對應(yīng) MySQL
設(shè)備信息表中的每個設(shè)備編碼。具體地來說, TDengine
中的數(shù)據(jù)模型如下:
create database if not exists sensor;
create stable if not exists sensor.water(ts timestamp, level float, status int) tags(district_code nchar(6), unit_id nchar(36), sensor_code int);
這里僅創(chuàng)建了1張超級表,具體的子表會在進(jìn)行數(shù)據(jù)遷移時,根據(jù) MySQL
設(shè)備信息表中的設(shè)備編碼自動創(chuàng)建。
準(zhǔn)備遷移工具
一開始我直接從https://github.com/taosdata/DataX的README中的:Download DataX下載地址下載的,但是后來才發(fā)現(xiàn)沒有 TDengine3.x
版本的writer;然后直接下載https://github.com/taosdata/DataX的源碼,本地編譯生成了 jar
包,放到了 DataX
的 plugin
目錄中。
Note:本地源碼 mvn clean package -Dmaven.test.skip=true
構(gòu)建生成 tdengine30writer-0.0.1-SNAPSHOT.jar
后,在 \datax\plugin\writer
下復(fù)制 tdenginewriter
目錄,重命名為 tdengine30writer
,對應(yīng)修改了其中的 plugin.json
和 plugin_job_template.json
,以及 libs
目錄下的 taos-jdbcdriver-3.0.2.jar
。
至此,工具就準(zhǔn)備好了,剩下的就是編寫數(shù)據(jù)遷移的配置腳本了。
遷移設(shè)備信息表
job-water.json
:遷移配置腳本分兩部分:一個是數(shù)據(jù)源,一個是目標(biāo)庫。遷移設(shè)備信息表這一步的結(jié)果就是創(chuàng)建了所有的子表:一個設(shè)備一張表。
- 數(shù)據(jù)源
“name”: “mysqlreader”, 遷移設(shè)備信息表時,對設(shè)備編碼起別名為tbname
,TDengine
自動會將其作為子表的名稱進(jìn)行創(chuàng)建。
Note:這里在設(shè)備編碼前加了一個字母d,因?yàn)樵?TDengine
中表名不可以為數(shù)字。
- 目標(biāo)庫
“name”: “tdengine30writer”, 在 column
部分羅列出數(shù)據(jù)源中查詢出的列名,與 MySQL
數(shù)據(jù)源中的順序和名稱一一對應(yīng),表名 table
處直接寫超級表的名稱。
{
"job": {
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "your-password",
"connection": [
{
"jdbcUrl": [
"jdbc:mysql://your-ip:3306/iotdata?useSSL=false&serverTimezone=Asia/Shanghai"
],
"querySql": [
"select concat('d', code) as tbname, create_time as ts, sensor_code, district_code, unit_id from b_device WHERE sensor_code=2;"
]
}
]
}
},
"writer": {
"name": "tdengine30writer",
"parameter": {
"username": "root",
"password": "taosdata",
"column": [
"tbname",
"ts",
"sensor_code",
"district_code",
"unit_id"
],
"connection": [
{
"table": [
"water"
],
"jdbcUrl": "jdbc:TAOS-RS://192.168.44.158:6041/sensor"
}
],
"batchSize": 1000,
"ignoreTagsUnmatched": true
}
}
}
],
"setting": {
"speed": {
"channel": 1
}
}
}
}
- 執(zhí)行遷移/同步腳本
D:\datax\bin>datax.py ../job/job-water.json
遷移設(shè)備數(shù)據(jù)表
job-water-data.json
:遷移配置腳本分兩部分:一個是數(shù)據(jù)源,一個是目標(biāo)庫。遷移設(shè)備數(shù)據(jù)表這一步的結(jié)果便會將傳感器數(shù)據(jù)根據(jù)設(shè)備編號寫入對應(yīng)的子表中。
- 數(shù)據(jù)源
遷移設(shè)備數(shù)據(jù)表時,查詢傳感器采集的字段,同樣對設(shè)備編碼起別名為 tbname
, TDengine
自動會將數(shù)據(jù)寫入對應(yīng)的子表。
- 目標(biāo)庫
在 column
部分羅列出數(shù)據(jù)源中查詢出的列名,與 MySQL
數(shù)據(jù)源中的順序和名稱一一對應(yīng),配置設(shè)備數(shù)據(jù)表時,需要注意,表名 table
處要寫所有子表的名稱。
{
"job": {
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "your-password",
"connection": [
{
"jdbcUrl": [
"jdbc:mysql://your-ip:3306/iotdata?useSSL=false&serverTimezone=Asia/Shanghai&net_write_timeout=600"
],
"querySql": [
"select concat('d', code) as tbname, create_time as ts, value as level, status from sensor_water;"
]
}
]
}
},
"writer": {
"name": "tdengine30writer",
"parameter": {
"username": "root",
"password": "taosdata",
"column": [
"tbname",
"ts",
"level",
"status"
],
"connection": [
{
"table": [
"d66057408201830",
"d66057408063030",
"d66057408027630",
"d66057408208130",
"d66057408009630",
"d66057408000530",
"d66057408067330",
"d66057408025430"
],
"jdbcUrl": "jdbc:TAOS-RS://192.168.44.158:6041/sensor"
}
],
"encoding": "UTF-8",
"batchSize": 1000,
"ignoreTagsUnmatched": true
}
}
}
],
"setting": {
"speed": {
"channel": 1
}
}
}
}
- 執(zhí)行遷移/同步腳本
D:\datax\bin>datax.py ../job/job-water-data.json
使用DataX可能遇到的問題
DataX中文亂碼
執(zhí)行 D:\datax\bin>datax.py ../job/job.json
后,控制臺上的中文輸出亂碼。
- Solution:直接輸入
CHCP 65001
回車,直到打開新窗口出現(xiàn)Active code page: 65001,再次執(zhí)行job命令,中文正常顯示。
插件加載失敗, 未完成指定插件加載:[mysqlreader, tdengine20writer]
- Solution:使用的插件名稱要寫正確
com.alibaba.datax.common.exception. DataXException: Code:[TDengineWriter-00], Description:[parameter value is missing]. - The parameter [username] is not set.
- Solution:TDengine2.0和3.0的配置項(xiàng)不一樣,因?yàn)槲乙婚_始是采用的TDengine2.0的配置來遷移的,根據(jù)3.0的文檔修改參數(shù)即可。
java.lang. ClassCastException: java.lang. String cannot be cast to java.util. List
- Solution:mysql的reader讀取部分的jdbcUrl和querySql的值需要使用“[]”括起來,是
jdbc
固定的模板。
com.alibaba.datax.common.exception. DataXException: Code:[TDengineWriter-02], Description:[runtime exception]. - No suitable driver found for [“jdbc: TAOS-RS://192.168.44.158:6041/sensor”]
- Solution:writer這邊的"jdbcUrl": “jdbc: TAOS-RS://192.168.44.158:6041/sensor”,使用字符串而不是數(shù)組。
空指針錯誤:ERROR WriterRunner - Writer Runner Received Exceptions:
java.lang.NullPointerException: null
at com.taosdata.jdbc.rs.RestfulDriver.connect(RestfulDriver.java:111) ~[taos-jdbcdriver-2.0.37.jar:na]
at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.8.0_311]
at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.8.0_311]
at com.alibaba.datax.plugin.writer.tdenginewriter.DefaultDataHandler.handle(DefaultDataHandler.java:75) ~[tdenginewriter-0.0.1-SNAPSHOT.jar:na]
- Solution:看到taos-jdbcdriver用的是2.0的jar包,下載DataX源碼,編譯生成tdengine30writer-0.0.1-SNAPSHOT.jar,并拷貝tdenginewriter文件夾為tdengine30writer,將tdengine30writer-0.0.1-SNAPSHOT.jar放到tdengine30writer中,刪除tdenginewriter\libs其中taos-jdbcdriver-2.0.37.jar,添加taos-jdbcdriver-3.0.2.jar。
com.alibaba.datax.common.exception. DataXException: Code:[TDengineWriter-02], Description:[運(yùn)行時異常]. - TDengine ERROR (2600): sql: describe 66057408201830, desc: syntax error near “66057408201830”
- Solution:表名不可以為數(shù)字,我在編號前加了個字母d。
com.mysql.jdbc.exceptions.jdbc4. CommunicationsException: Application was streaming results when the connection failed. Consider raising value of ‘net_write_timeout’ on the server.
- Solution:在數(shù)據(jù)源
URL
的連接上增加該參數(shù),net_write_timeout/net_read_timeout
設(shè)置稍微大一些,默認(rèn)60s。
例如:jdbc:mysql://your-ip:3306/iotdata?useSSL=false&serverTimezone=Asia/Shanghai&net_write_timeout=600
在 MySQL
中查看變量值: SHOW VARIABLES LIKE "net%"
。
小總結(jié)
以上便是基于 DataX
完成從 MySQL
到 TDengine3.x
的時序數(shù)據(jù)遷移實(shí)戰(zhàn)記錄,借助 DataX
工具,通過配置文件驅(qū)動的方式完成了海量時序數(shù)據(jù)的快速遷移。
實(shí)際的遷移測試結(jié)果是,3000+個水庫水位傳感設(shè)備,歷史數(shù)據(jù)單表1億+,半天時間遷移了5000萬+。
Reference
- https://github.com/taosdata/DataX
- MysqlReader插件文檔
- DataX TDengineWriter插件文檔
- https://developer.aliyun.com/ask/430332
- 基于 DataX 的 TDengine 2.* 版本數(shù)據(jù)遷移工具
If you have any questions or any bugs are found, please feel free to contact me.文章來源:http://www.zghlxwxcb.cn/news/detail-462378.html
Your comments and suggestions are welcome!文章來源地址http://www.zghlxwxcb.cn/news/detail-462378.html
到了這里,關(guān)于基于DataX的海量時序數(shù)據(jù)遷移實(shí)戰(zhàn):從MySQL到TDengine3.x的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!