原文: https://www.cnblogs.com/quchunhui/p/13731825.html
------------------------------------------------------------------------
==背景==
在搭建工業物聯網的數據平台,用來完成設備連接以及數據存儲等,
以支持上層的應用及數據分析等。目前使用的是mq→flink→influxdb的基本套路。
雖然說InfluxDB的性能和功能都非常的棒,特別是連續查詢對性能的支撐,
不過由於influxdb使用的是社區版,存在單點故障的問題,總之不是長久直接。
於是打算嘗試驗證一下陶老師的TDEngine。祝自己一切順利。
==環境==
服務器節點數:3個(VMware虛擬機)
操作系統:Linux Centos8 64位
TDengine版本:2.0.4(2020年10月16日,使用版本換成了2.0.5.1)
JDK:1.8.0_77
JDBC客戶端版本建議:
tdengine:2.0.10.0,jdbc版本:2.0.15
tdengine:2.0.15.0,jdbc版本:2.0.18
==下載==
https://www.taosdata.com/cn/getting-started/
TDengine-server-2.0.4.0-Linux-x64.rpm TDengine-client-2.0.4.0-Linux-x64.tar.gz TDengine-alert-2.0.4.0-Linux-x64.tar.gz
==測試代碼==
所有程序的測試代碼放到了git上,需要的自取。
https://github.com/quchunhui/java-demo/tree/master/tdengine
==集群部署==
參考官網:https://www.taosdata.com/cn/documentation/cluster/
PS:中文文檔是真的很爽,比看英文省心多了。
1、安裝server
上傳到服務器,並復制到各個節點,在各個節點執行rpm安裝命令
命令:rpm -ivh TDengine-server-2.0.4.0-Linux-x64.rpm
【小插曲】
在另一個集群上安裝新的版本(2.0.7.0)的時候,發現如論如何也無法使新增加的節點上線,
后來看了新版本的文檔,上面提示:在增加新的節點時,先不要啟動taosd,安裝時,提示輸入是否要加入一個已經存在的TDengine集群時,第一個物理節點直接回車創建新集群,后續物理節點則輸入該集群任何一個在線的物理節點的FQDN:端口號(默認6030);
2、修改配置
配置文件路徑:/etc/taos/taos.cfg
配置文件說明:TDengine的運營與維護
按照官網的提示,修改了幾個配置:firstEp、secondEp、fqdn、serverPort、logDir、dataDir、replica。
根據官網的說明,我羅列了配置的中文,供參考。沒有寫的是在這個版本的官網上沒有找到的了。
######################################################## # # # TDengine Configuration # # Any questions, please email support@taosdata.com # # # ######################################################## # first fully qualified domain name (FQDN) for TDengine system # taosd啟動時,主動連接的集群中第一個dnode的end point, 默認值為localhost:6030。 firstEp vm1:6030 # second fully qualified domain name (FQDN) for TDengine system, for cluster only # taosd啟動時,如果first連接不上,嘗試連接集群中第二個dnode的end point, 默認值為空。 secondEp vm2:6030 # local fully qualified domain name (FQDN) # 數據節點的FQDN,缺省為操作系統配置的第一個hostname。如果習慣IP地址訪問,可設置為該節點的IP地址。 fqdn vm1 # first port number for the connection (12 continuous UDP/TCP port number are used) # taosd啟動后,對外服務的端口號,默認值為6030。 serverPort 6030 # log file's directory # 日志文件目錄,客戶端和服務器的運行日志文件將寫入該目錄。默認值:/var/log/taos。 logDir /home/radmin/data/tdengine/log # data file's directory # 數據文件目錄,所有的數據文件都將寫入該目錄。默認值:/var/lib/taos。 dataDir /home/radmin/data/tdengine/data # the arbitrator's fully qualified domain name (FQDN) for TDengine system, for cluster only # 系統中裁決器的end point, 缺省值為空。 # arbitrator arbitrator_hostname:6042 # number of threads per CPU core # numOfThreadsPerCore 1.0 # number of management nodes in the system # 系統中管理節點個數。默認值:3。 # numOfMnodes 3 # enable/disable backuping vnode directory when removing dnode # vnodeBak 1 # enable/disable load balancing # 是否啟動負載均衡。0:否,1:是。默認值:1。 # balance 1 # role for dnode. 0 - any, 1 - mnode, 2 - dnode # dnode的可選角色。0-any; 既可作為mnode,也可分配vnode;1-mgmt;只能作為mnode,不能分配vnode;2-dnode;不能作為mnode,只能分配vnode # role 0 # max timer control blocks # maxTmrCtrl 512 # time interval of system monitor, seconds # monitorInterval 30 # number of seconds allowed for a dnode to be offline, for cluster only # dnode離線閾值,超過該時間將導致該dnode從集群中刪除。單位為秒,默認值:86400*10(即10天)。 # offlineThreshold 8640000 # RPC re-try timer, millisecond # rpcTimer 300 # RPC maximum time for ack, seconds. # rpcMaxTime 600 # time interval of dnode status reporting to mnode, seconds, for cluster only # statusInterval 1 # time interval of heart beat from shell to dnode, seconds # shellActivityTimer 3 # time of keeping table meta data in cache, seconds # tableMetaKeepTimer 7200 # minimum sliding window time, milli-second # minSlidingTime 10 # minimum time window, milli-second # minIntervalTime 10 # maximum delay before launching a stream compution, milli-second # maxStreamCompDelay 20000 # maximum delay before launching a stream computation for the first time, milli-second # maxFirstStreamCompDelay 10000 # retry delay when a stream computation fails, milli-second # retryStreamCompDelay 10 # the delayed time for launching a stream computation, from 0.1(default, 10% of whole computing time window) to 0.9 # streamCompDelayRatio 0.1 # max number of vgroups per db, 0 means configured automatically # 每個數據庫中能夠使用的最大vnode個數。 # maxVgroupsPerDb 0 # max number of tables per vnode # 每個vnode中能夠創建的最大表個數。默認值:1000000。 # maxTablesPerVnode 1000000 # step size of increasing table number in a vnode # tableIncStepPerVnode 1000 # cache block size (Mbyte) # cache 16 # number of cache blocks per vnode # blocks 6 # number of days per DB file # 一個數據文件存儲數據的時間跨度,單位為天,默認值:10。 # days 10 # number of days to keep DB file # 數據庫中數據保留的天數,單位為天,默認值:3650。 # keep 3650 # minimum rows of records in file block # 文件塊中記錄的最小條數,單位為條,默認值:100。 # minRows 100 # maximum rows of records in file block # 文件塊中記錄的最大條數,單位為條,默認值:4096。 # maxRows 4096 # enable/disable compression # 文件壓縮標志位,0:關閉,1:一階段壓縮,2:兩階段壓縮。默認值:2。 # comp 2 # write ahead log (WAL) level, 0: no wal; 1: write wal, but no fysnc; 2: write wal, and call fsync # WAL級別。1:寫wal, 但不執行fsync; 2:寫wal, 而且執行fsync。默認值:1。 # walLevel 1 # if walLevel is set to 2, the cycle of fsync being executed, if set to 0, fsync is called right away # 當wal設置為2時,執行fsync的周期。設置為0,表示每次寫入,立即執行fsync。單位為毫秒,默認值:3000。 # fsync 3000 # number of replications, for cluster only # 副本個數,取值范圍:1-3。單位為個,默認值:1 replica 3 # mqtt hostname # mqttHostName test.mosquitto.org # mqtt port # mqttPort 1883 # mqtt topic # mqttTopic /test # the compressed rpc message, option: # -1 (no compression) # 0 (all message compressed), # > 0 (rpc message body which larger than this value will be compressed) # compressMsgSize -1 # max length of an SQL # 單條SQL語句允許最長限制。默認值:65380字節。 maxSQLLength 1048576 # the maximum number of records allowed for super table time sorting # maxNumOfOrderedRes 100000 # system time zone # 默認值:從系統中動態獲取當前的時區設置 # timezone Asia/Shanghai (CST, +0800) # system locale # 默認值:系統中動態獲取,如果自動獲取失敗,需要用戶在配置文件設置或通過API設置 # locale en_US.UTF-8 # default system charset # 默認值:系統中動態獲取,如果自動獲取失敗,需要用戶在配置文件設置或通過API設置 # charset UTF-8 # max number of connections allowed in dnode # maxShellConns 5000 # max numerber of connections allowed in client # maxConnections 5000 # stop writing logs when the disk size of the log folder is less than this value # minimalLogDirGB 0.1 # stop writing temporary files when the disk size of the log folder is less than this value # minimalTmpDirGB 0.1 # stop writing data when the disk size of the log folder is less than this value # minimalDataDirGB 0.1 # enbale/disable http service # http 1 # enable/disable muqq service # mqtt 0 # enable/disable system monitor # monitor 1 # enable/disable recording the SQL statements via restful interface # httpEnableRecordSql 0 # number of threads used to process http requests # httpMaxThreads 2 # maximum number of rows returned by the restful interface # restfulRowLimit 10240 # The following parameter is used to limit the maximum number of lines in log files. # max number of rows per log filters # 單個日志文件允許的最大行數。默認值:10,000,000行。 # numOfLogLines 10000000 # time of keeping log files, days # 日志文件的最長保存時間。大於0時,日志文件會被重命名為taosdlog.xxx,其中xxx為日志文件最后修改的時間戳,單位為秒。默認值:0天。 # logKeepDays 0 # enable/disable async log # asyncLog 1 # The following parameters are used for debug purpose only. # debugFlag 8 bits mask: FILE-SCREEN-UNUSED-HeartBeat-DUMP-TRACE_WARN-ERROR # 131: output warning and error, 135: output debug, warning and error, 143 : output trace, debug, warning and error to log. # 199: output debug, warning and error to both screen and file # 207: output trace, debug, warning and error to both screen and file # debug flag for all log type, take effect when non-zero value # debugFlag 0 # debug flag for meta management messages # mDebugFlag 135 # debug flag for dnode messages # dDebugFlag 135 # debug flag for sync module # sDebugFlag 135 # debug flag for WAL # wDebugFlag 135 # debug flag for SDB # sdbDebugFlag 135 # debug flag for RPC # rpcDebugFlag 131 # debug flag for TAOS TIMER # tmrDebugFlag 131 # debug flag for TDengine client # cDebugFlag 131 # debug flag for JNI # jniDebugflag 131 # debug flag for ODBC # odbcDebugflag 131 # debug flag for storage # uDebugflag 131 # debug flag for http server # httpDebugFlag 131 # debug flag for mqtt # mqttDebugFlag 131 # debug flag for monitor # monitorDebugFlag 131 # debug flag for query # qDebugflag 131 # debug flag for vnode # vDebugflag 131 # debug flag for http server # tsdbDebugFlag 131 # enable/disable recording the SQL in taos client # tscEnableRecordSql 0 # generate core file when service crash # enableCoreFile 1 # maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden # maxBinaryDisplayWidth 30
PS:到此的感受:
總體感覺TDengine的安裝非常容易,配置文件也簡單易懂,到此體驗良好。
==啟動==
1、啟動第1個節點
命令:systemctl start taosd
2、驗證第1個節點是否啟動成功
命令:taos
命令:show dnodes;
3、啟動后續數據節點
先將后兩個節點的服務啟動起來。
在每個節點執行:systemctl start taosd
確認服務狀態:systemctl status taosd
如下圖,第2個節點的服務正常:
第3個節點的服務正常:
【小插曲】
在啟動第2個節點的時候報錯,
[root@vm2 ~]# systemctl status taosd ● taosd.service - TDengine server service Loaded: loaded (/etc/systemd/system/taosd.service; enabled; vendor preset: disabled) Active: failed (Result: start-limit) since Tue 2020-09-29 20:38:20 UTC; 2s ago Process: 5095 ExecStart=/usr/bin/taosd (code=exited, status=1/FAILURE) Main PID: 5095 (code=exited, status=1/FAILURE) Sep 29 20:38:20 vm2 systemd[1]: taosd.service: main process exited, code=exited, status=1/FAILURE Sep 29 20:38:20 vm2 systemd[1]: Unit taosd.service entered failed state. Sep 29 20:38:20 vm2 systemd[1]: taosd.service failed. Sep 29 20:38:20 vm2 systemd[1]: taosd.service holdoff time over, scheduling restart. Sep 29 20:38:20 vm2 systemd[1]: Stopped TDengine server service. Sep 29 20:38:20 vm2 systemd[1]: start request repeated too quickly for taosd.service Sep 29 20:38:20 vm2 systemd[1]: Failed to start TDengine server service. Sep 29 20:38:20 vm2 systemd[1]: Unit taosd.service entered failed state. Sep 29 20:38:20 vm2 systemd[1]: taosd.service failed.
【原因】
沒有創建log和data的文件路徑,在第2個和第3個節點上分別創建兩個路徑
mkdir -p /home/radmin/data/tdengine/log
mkdir -p /home/radmin/data/tdengine/data
4、添加節點
在第一個數據節點,使用CLI程序taos, 登錄進TDengine系統, 執行命令:
CREATE DNODE "vm2:6030"; CREATE DNODE "vm3:6030";
查看新的節點是否加入進來。
【小插曲】
執行show dnodes;之后,發現vm2這個節點處於offline狀態。按照官網提示的方法:
查看日志中提示如下錯誤:
09/29 20:59:55.055274 0x7fcb0aae7700 DND ERROR status rsp is received, error:Cluster cfg inconsistent 09/29 20:59:56.060418 0x7fcb0aae7700 DND ERROR status rsp is received, error:Cluster cfg inconsistent 09/29 20:59:57.065157 0x7fcb0aae7700 DND ERROR status rsp is received, error:Cluster cfg inconsistent
【原因】
經過群里的咨詢,有朋友建議排查一下時區是否一致,經排查第2個節點的時區確實與另外兩個不一致。
修改了一下時區之后,從新啟動第2個節點,發現狀態恢復正常。修改時區命令:
mv /etc/localtime /etc/localtime.bak ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/locaktime
【小插曲2】
解決了上面的小插曲,非常的開心,合上筆記本電腦回家。
回家之后,重新連接上服務器,查看狀態,結果發現第2個節點的狀態又變成offline了,真是開心不過3分鍾啊。
【原因】
發現時間貌似不同步。看來是時候加上NTP時間同步了。按照以下步驟嘗試了一下
1)停掉taos服務
2)配置ntp同步(參考我的另一篇博客:Linux配置ntp時間服務器)
3)重啟taos服務
重啟之后,第2個節點的狀態恢復為ready,開森。
為了以防萬一,將系統放置了一整夜,第2天早上起來查看集群狀態,依然是正常的,這下才算放心。
【感謝道友】
5、數據節點管理命令
添加數據節點:CREATE DNODE "fqdn:port"; 刪除數據節點:DROP DNODE "fqdn:port"; 查看數據節點:SHOW DNODES;
PS:到此的感受
TDengine的集群部署也非常的簡單,比傳統的HBase,MongoDB之類的簡單的多,感受不錯。
唯一比較大的遺憾是,目前的社區版不支持多級存儲,我們實際項目中磁盤是插滿的,
如果要利用磁盤空間,就必須要加上lvm,但是lvm會影響讀寫速度,對已經存在的hdfs也有一些影響。
6、集群卸載
因為是用rpm的格式安裝的,目前用的是yum remove來卸載,不清楚是否為最佳卸載方式。
systemctl stop taosd
rpm -qa | grep TD
yum remove TDengine-2.0.5.0-3.x86_64
2020年11月10日
卸載了2.0.5.0版本,重新安裝了2.0.7.0版本,和上面的步驟一樣
1、停止集群
2、卸載td
3、沖洗安裝
【小插曲】
在這次重新安裝的時候,遇到了下面的問題。在Git上提了issue:https://github.com/taosdata/TDengine/issues/4168
說是需要安裝python環境,可是我又沒有用到python,而且2.0.5.0的時候還沒有這個問題。
所以,tdengine的版本更新是不是太快了,導致一些問題沒能充分測試呢?
error: Failed dependencies: /usr/bin/python is needed by tdengine-2.0.7.0-3.x86_64
解決過程:
按照提示,安裝了3.8.6版本的python,並確認了python安裝沒有問題,嘗試重新安裝tdengine,仍然報了同樣的錯誤,
后來和官方的人員確認過了,應該是官網放的release包有點問題,他們重新更新了一個包之后就可以了,
而且不需要安裝python,不需要安裝python,不需要安裝python。
==TAOS SQL==
官網提供了完整的文檔,官網地址:https://www.taosdata.com/cn/documentation20/taos-sql/
我個人習慣了逐個嘗試驗證一遍,以加深印象,好記性不如爛筆頭。
另外,可以通過官方提供的樣例數據創建一些表供驗證。
命令:taosdemo(注意,需要預留大約2.1GB的存儲空間)
1、數據庫管理
#創建庫:
#COMP參數是指修改數據庫文件壓縮標志位,取值范圍為[0, 2]. 0表示不壓縮,1表示一階段壓縮,2表示兩階段壓縮。
#REPLICA參數是指修改數據庫副本數,取值范圍[1, 3]。在集群中使用,副本數必須小於dnode的數目。
#KEEP參數是指修改數據文件保存的天數,缺省值為3650,取值范圍[days, 365000],必須大於或等於days參數值。
#QUORUM參數是指數據寫入成功所需要的確認數。取值范圍[1, 3]。對於異步復制,quorum設為1,具有master角色的虛擬節點自己確認即可。對於同步復制,需要至少大於等於2。原則上,Quorum >=1 並且 Quorum <= replica(副本數),這個參數在啟動一個同步模塊實例時需要提供。
#BLOCKS參數是每個VNODE (TSDB) 中有多少cache大小的內存塊,因此一個VNODE的用的內存大小粗略為(cache * blocks)。取值范圍[3, 1000]。
#DAYS一個數據文件存儲數據的時間跨度,單位為天,默認值:10。
create database mydb keep 365 days 10 blocks 4; #創建庫(如果不存在): create database if not exists mydb keep 365 days 10 blocks 4; #使用庫: use mydb; #刪除庫: drop database mydb; #刪除庫(如果存在): drop database if exists mydb; #顯示所有數據庫: show databases; #修改數據庫文件壓縮標志位: alter database mydb comp 2; #修改數據庫副本數: alter database mydb replica 2; #修改數據文件保存的天數: alter database mydb keep 365; #修改數據寫入成功所需要的確認數: alter database mydb quorum 2; #修改每個VNODE (TSDB) 中有多少cache大小的內存塊: alter database mydb blocks 100;
2、表管理
#創建表(搞了個包含所有數據類型的表): create table if not exists mytable(time timestamp, intfield int, bigintfield bigint, floatfield float, doublefield double, binaryfield binary(20), smallintfield smallint, tinyintfield tinyint, boolfield bool, ncharfiel d nchar(50)); #刪除數據表 drop table if exists mytable; #顯示當前數據庫下的所有數據表信息 show tables; #顯示當前數據庫下的所有數據表信息 #可在like中使用通配符進行名稱的匹配。通配符匹配:1)’%’ (百分號)匹配0到任意個字符;2)’_’下划線匹配一個字符。 show tables like "%my%"; #獲取表的結構信息 describe mytable; #表增加列 alter table mytable add column addfield int; #表刪除列 alter table mytable drop column addfield;
注意:表名一定不要用數字開頭,官方文檔明確提醒了。
3、超級表管理
#創建超級表 #創建STable, 與創建表的SQL語法相似,但需指定TAGS字段的名稱和類型。說明: #1) TAGS 列的數據類型不能是timestamp類型; #2) TAGS 列名不能與其他列名相同; #3) TAGS 列名不能為預留關鍵字; #4) TAGS 最多允許128個,可以0個,總長度不超過16k個字符 create table if not exists mysupertable (time timestamp, intfield int, bigintfield bigint, floatfield float, doublefield double, binaryfield binary(20), smallintfield smallint, tinyintfield tinyint, boolfield bool, nch arfield nchar(50)) TAGS (product nchar(50), device nchar(100)); #刪除超級表 drop table if exists mysupertable; #顯示當前數據庫下的所有超級表信息 show stables like "%super%"; #獲取超級表的結構信息 describe mysupertable; #超級表增加列 alter table mysupertable add column addfield int; #超級表刪除列 alter table mysupertable drop column addfield; #添加標簽 alter table mysupertable add tag devicetype nchar(60); #刪除標簽 alter table mysupertable drop tag devicetype; #修改標簽名 alter table mysupertable change tag product productKey; #修改子表標簽值 #說明:除了更新標簽的值的操作是針對子表進行,其他所有的標簽操作(添加標簽、刪除標簽等)均只能作用於STable,不能對單個子表操作。對STable添加標簽以后,依托於該STable建立的所有表將自動增加了一個標簽,所有新增標簽的默認值都是NULL。 alter table mysupertable set tag productkey="abc";
【小插曲】
執行了一個下面的創建超級表的語句(通過自己寫的程序生成的),結果報錯
SQL語句:create table if not exists AI_PICK_UDATA ( time timestamp, data double ) tags ( productKey binary(256),deviceName binary(256),pointId binary(256),name binary(256),dataType binary(256),min binary(256),max binary(256),step binary(256),unit binary(256),description binary(256) );
提示錯誤:DB error: invalid SQL: invalid tag name
【問題原因】
創建表的語句中有tdengine的保留字段,如min,max。
但是官方文檔上並沒有對此進行相關介紹,吐槽一下文檔。
4、數據插入
#插入一條數據 insert into mytable values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s"); #插入一條記錄,數據對應到指定的列 insert into mytable(time, intfield, bigintfield, floatfield, doublefield, binaryfield, smallintfield, tinyintfield, boolfield, ncharfield) values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s"); #插入多條記錄 insert into mytable values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s") (now, 2, 3, 4, 5, 6, 7, 8, 0, "t"); #按指定的列插入多條記錄 insert into mytable(time, intfield, bigintfield, floatfield, doublefield, binaryfield, smallintfield, tinyintfield, boolfield, ncharfield) values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s") (now, 2, 3, 4, 5, 6, 7, 8, 0, "t"); #向多個表插入多條記錄(本人沒有驗證此語句) INSERT INTO tb1_name VALUES (field1_value1, ...)(field1_value2, ...) tb2_name VALUES (field1_value1, ...)(field1_value2, ...); #同時向多個表按列插入多條記錄(本人沒有驗證此語句) INSERT INTO tb1_name (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) tb2_name (tb2_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...);
【小插入】
插入多條記錄的時候,語句中寫的是兩條數據,實際上只插入了一條
插入語句:
insert into mytable(time, intfield, bigintfield, floatfield, doublefield, binaryfield, smallintfield, tinyintfield, boolfield, ncharfield) values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s") (now, 2, 3, 4, 5, 6, 7, 8, 0, "t");
【原因】
需要使用不同的時間戳,如果兩條語句都使用now,時間戳一樣,最終只能插入一條。
【感謝道友】
5、數據查詢
查詢語法:
SELECT select_expr [, select_expr ...] FROM {tb_name_list} [WHERE where_condition] [INTERVAL (interval_val [, interval_offset])] [FILL fill_val] [SLIDING fill_val] [GROUP BY col_list] [ORDER BY col_list { DESC | ASC }] [SLIMIT limit_val [, SOFFSET offset_val]] [LIMIT limit_val [, OFFSET offset_val]] [>> export_file]
==查詢語句==
查詢語法:
SELECT select_expr [, select_expr ...] FROM {tb_name_list} [WHERE where_condition] [INTERVAL (interval_val [, interval_offset])] [FILL fill_val] [SLIDING fill_val] [GROUP BY col_list] [ORDER BY col_list { DESC | ASC }] [SLIMIT limit_val [, SOFFSET offset_val]] [LIMIT limit_val [, OFFSET offset_val]] [>> export_file]
常用查詢語句樣例:
#查詢表中的所有字段 select * from t_znsllj001; #按照時間戳查詢表中的所有字段 select * from t_znsllj001 where time > "2020-10-10 22:23:08.728"; #按照時間戳查詢超級表中的所有字段 select * from st_znsllj where time > "2020-10-10 22:23:08.728"; #查詢超級表中的指定字段 select time, forwardintegratedflow, product from st_znsllj; #按照標簽值查詢超級表中的指定字段 select time, forwardintegratedflow, product from st_znsllj where product = "product1"; #查詢結果按照時間倒序排序 select time, forwardintegratedflow, product from st_znsllj where product = "product1" order by time desc; #結果集列名重命名 select time, forwardintegratedflow as ff, product from st_znsllj; #查詢超級表數據並附帶表名(TBNAME: 在超級表查詢中可視為一個特殊的標簽,代表查詢涉及的子表名,不區分大小寫) select tbname, * from st_znsllj; #查詢超級表的表名及第一列 select tbname, _c0 from st_znsllj; #獲取當前所在的數據庫 select database(); #獲取客戶端版本號 select client_version() #獲取服務器版本號 select server_version(); #服務器狀態檢測語句 select server_status() #統計超級表下轄子表數量 select count(tbname) from st_znsllj;
==用戶管理==
#創建用戶,並指定用戶名和密碼,密碼需要用單引號引起來,單引號為英文半角 create user admin pass 'admin123'; #刪除用戶,限root用戶使用 drop user admin; #修改用戶密碼, 為避免被轉換為小寫,密碼需要用單引號引用,單引號為英文半角 alter user admin pass 'admin1234'; #修改用戶權限為:super/write/read。 為避免被轉換為小寫,密碼需要用單引號引用,單引號為英文半角 #語法:ALTER USER <user_name> PRIVILEGE <super|write|read>; alter user admin privilege read;
如果修改了root密碼之后,進入命令行的命令就需要加上密碼的參數了。
可以通過taos --usage查看命令行的參數格式:
如:修改了密碼之后,可以通過以下命令來登錄命令行
taos --user=root -p'RexelRoot!@#'
==Java連接==
官網地址:https://www.taosdata.com/cn/documentation/connector-java/
1、maven配置
<dependency> <groupId>com.taosdata.jdbc</groupId> <artifactId>taos-jdbcdriver</artifactId> <version>2.0.4</version> </dependency>
2、JDBC連接樣例
【TdUtils.java】
單例工具類,實現創建連接等通用方法。
package com.rexel.tdengine.utils; import com.taosdata.jdbc.TSDBDriver; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * @ClassName TdUtils * @Description TDengine共通類 * @Author: chunhui.qu * @Date: 2020/9/30 */ public class TdUtils { private Connection connection = null; /** * 構造函數 */ private TdUtils() { // do nothing } /** * 單例模式 */ private static class SingletonInstance { private static final TdUtils INSTANCE = new TdUtils(); } /** * 獲取對象句柄 */ public static TdUtils getInstance() { return SingletonInstance.INSTANCE; } public Connection getConnection() { if (connection != null) { return connection; } try { Class.forName("com.taosdata.jdbc.TSDBDriver"); String jdbcUrl = "jdbc:TAOS://rexel-ids001:6030/qch_test?user=root&password=taosdata"; Properties connProps = new Properties(); connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "C:\\TDengine\\cfg"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "Asia/Shanghai"); connection = DriverManager.getConnection(jdbcUrl, connProps); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return connection; } }
【CreateDatabase.java】
創建數據的樣例程序。
package com.rexel.tdengine.api; import com.rexel.tdengine.utils.TdUtils; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; /** * @ClassName CreateDatabase * @Description CreateDatabase * @Author: chunhui.qu * @Date: 2020/9/30 */ public class CreateDatabase { public static void main(String[] args) throws SQLException { TdUtils tdUtils = TdUtils.getInstance(); Connection conn = tdUtils.getConnection(); if (conn == null) { return; } System.out.println("get connection"); Statement stmt = conn.createStatement(); if (stmt == null) { return; } stmt.executeUpdate("create database if not exists javatestdb"); System.out.println("create database"); stmt.executeUpdate("use javatestdb"); System.out.println("use database"); stmt.executeUpdate("create table if not exists javatesttable (ts timestamp, temperature int, humidity float)"); System.out.println("create table"); } }
【小插曲1】
寫完了測試代碼,在執行的時候報錯:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no taos in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at com.taosdata.jdbc.TSDBJNIConnector.<clinit>(TSDBJNIConnector.java:25) at com.taosdata.jdbc.TSDBDriver.connect(TSDBDriver.java:133) at java.sql.DriverManager.getConnection(DriverManager.java:664) at java.sql.DriverManager.getConnection(DriverManager.java:208) at com.rexel.tdengine.utils.TdUtils.getConnection(TdUtils.java:54) at com.rexel.tdengine.api.CreateDatabase.main(CreateDatabase.java:17) Disconnected from the target VM, address: '127.0.0.1:54954', transport: 'socket'
【解決過程】
重新看了一下官方文檔,懷疑是沒有安裝Window客戶端,嘗試安裝客戶端程序。
安裝文件:TDengine-client-2.0.4.0-Windows-x64.exe
重新執行程序之后,報了另一個錯誤:
java.sql.SQLException: TDengine Error: Invalid timestamp at com.taosdata.jdbc.TSDBJNIConnector.connect(TSDBJNIConnector.java:100) at com.taosdata.jdbc.TSDBConnection.connect(TSDBConnection.java:64) at com.taosdata.jdbc.TSDBConnection.<init>(TSDBConnection.java:56) at com.taosdata.jdbc.TSDBDriver.connect(TSDBDriver.java:135) at java.sql.DriverManager.getConnection(DriverManager.java:664) at java.sql.DriverManager.getConnection(DriverManager.java:208) at com.rexel.tdengine.utils.TdUtils.getConnection(TdUtils.java:54) at com.rexel.tdengine.api.CreateDatabase.main(CreateDatabase.java:17)
網友說可能是因為客戶端的時間與服務器時間相差比較多的原因,
於是調整了服務器的時間。命令如下,調整之后,重啟了一下服務器
修改系統時間:date --set "09/30/20 14:15" 系統時間向硬件同步:clock --show
重新運行程序,正確執行。感謝網友的幫助。
【感謝道友】
【小插曲2】
本來運行的好好的,debug也都沒有問題,但是下午去酒店再debug測試,就提示“Unable to establish connection”
按照官網的FAQ提示,一頓檢查,沒有發現什么問題,非常迷惑。
后來想到由於服務器用的是阿里雲ECS,需要配置網絡安全組的IP地址白名單,
我配置的時候只配置了TCP,沒有配置UDP,配置上了UCP的權限之后,debug就恢復正常了。
3、插入數據樣例
我這里寫了一個JSON字符串轉換為SQL,並持續插入的樣例。
package com.rexel.tdengine.api; import com.alibaba.fastjson.JSONObject; import com.rexel.tdengine.utils.TdUtils; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; /** * @ClassName CreateDatabase * @Description CreateDatabase * @Author: chunhui.qu * @Date: 2020/10/12 */ public class InsertJson { public static void main(String[] args) throws SQLException { TdUtils tdUtils = TdUtils.getInstance(); Connection conn = tdUtils.getConnection(); if (conn == null) { return; } System.out.println("get connection"); Statement stmt = conn.createStatement(); if (stmt == null) { return; } List<String> aiList = new ArrayList<String>(){{ add("AI_PICK_UDATA"); add("AI_PROD_NPER"); add("AI_PROD_NPICK"); add("AI_PRODUCT_EFF"); add("AI_PRODUCT_QUANTITY"); add("AI_PRODUCT_TIME_MIN"); add("AI_PROD_NPRODING"); }}; List<String> diList = new ArrayList<String>(){{ add("DI_BELOWCLOSTS"); add("DI_BELOWOPNSTS"); add("DI_CANDY_OUTBEELINEA"); add("DI_CANDY_OUTBEELINEB"); add("DI_CANDY_OUTBEELINEC"); add("DI_CHUCKCLOSTS"); add("DI_CHUCKOPNSTS"); add("DI_COVERCLOSTS"); add("DI_COVEROPNSTS"); add("DI_CTNCLO_BSTART"); add("DI_CTNOPN_BSTART"); add("DI_DENSO_BAUTOST"); add("DI_DENSO_BERROR"); add("DI_DENSO_BMOTORONST"); add("DI_DENSO_BREADY"); add("DI_DENSO_BRUNNING"); add("DI_EPSON_BERROR"); add("DI_EPSON_BESTOPON"); add("DI_EPSON_BMOTORONST"); add("DI_EPSON_BREADY"); add("DI_EPSON_BRUNNING"); add("DI_LEFTPUSHCLOSTS"); add("DI_LEFTPUSHOPNSTS"); add("DI_PRINT_BRUNNING"); add("DI_RIGHTCLOSTS"); add("DI_RIGHTOPNSTS"); add("DI_RIGHTPUSHCLOSTS"); add("DI_RIGHTPUSHLOPN"); add("DI_RLCLOSTS"); add("DI_RLOPNSTS"); add("DI_ROBOT1_BLINKSTS"); add("DI_ROBOT1_BSTART"); add("DI_ROBOT2_BLINKSTS"); add("DI_ROBOT2TOSTOR"); add("DI_ROBOT2TOWAI"); add("DI_SYS_BRUNNING"); add("DI_TOPCLOSTS"); add("DI_TOPOPNSTS"); add("DI_UPDOWNCLOSTS"); add("DI_UPDOWNOPNSTS"); add("DI_BBELTSENSOROVT"); add("DI_BCTNCLOCOOPNOVT"); add("DI_BCTNCLORCLOOVT"); add("DI_BCTNCLOROPNOVT"); add("DI_BCTNCLOTCLOOVT"); add("DI_BCTNCLOTOPNOVT"); add("DI_BCTNOVT"); add("DI_BELOWVALCLOOVT"); add("DI_BELOWVALOPNOVT"); add("DI_BROBOT2VALCLOVT"); add("DI_BROBOT2VALOPOVT"); add("DI_BRTSUCKEROVT"); add("DI_BVALCOVERCLOOVT"); add("DI_CHUCJVALCLOOVT"); add("DI_CHUCJVALOPOVT"); add("DI_CHUCKVALOPNOVT"); add("DI_DENSOBERROR"); add("DI_EPSONBERROR"); add("DI_INSENCTNALARM"); add("DI_LEFTNEWVALCLOVT"); add("DI_RLNEWOPVALOPOVT"); add("DI_RLNEWVALCLOOVT"); add("DI_UPDOWNNVALCLOVT"); add("DI_UPDOWNNVALOPOVT"); }}; int count = 0; while(true) { Random intRandom = new Random(); JSONObject demoJson = new JSONObject(); demoJson.put("table", "device_data_up"); demoJson.put("time", System.currentTimeMillis()); JSONObject tagJson = new JSONObject(); tagJson.put("productKey", "a1B6t6ZG6oR"); tagJson.put("deviceName", "QCHTestDevice1"); demoJson.put("tags", tagJson); JSONObject dataJson = new JSONObject(); aiList.forEach(field -> dataJson.put(field, intRandom.nextInt(10000))); diList.forEach(field -> dataJson.put(field, intRandom.nextInt(2))); demoJson.put("datas", dataJson); String sql = jsonToSql(demoJson); stmt.executeUpdate(sql); count ++; System.out.println("executeUpdate. count=" + count + ", sql=" + sql); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } private static String jsonToSql(JSONObject jsonObject) { String sql = "insert into {table} ({fields}) values ({values});"; sql = sql.replace("{table}", getTable(jsonObject)); sql = sql.replace("{fields}", getFields(jsonObject)); return sql.replace("{values}", getValues(jsonObject)); } private static String getTable(JSONObject jsonObject) { return "t_" + jsonObject.getString("table"); } private static String getTime(JSONObject jsonObject) { if (jsonObject.containsKey("time")) { return timeLongToStr(jsonObject.getLong("time")); } else { return timeLongToStr(System.currentTimeMillis()); } } private static String getFields(JSONObject jsonObject) { JSONObject dataJson = jsonObject.getJSONObject("datas"); StringBuilder sb = new StringBuilder(); sb.append("time").append(","); dataJson.forEach((key, value) -> sb.append(key).append(",")); return sb.substring(0, sb.length() - 1); } private static String getValues(JSONObject jsonObject) { JSONObject dataJson = jsonObject.getJSONObject("datas"); StringBuilder sb = new StringBuilder(); sb.append("\"").append(getTime(jsonObject)).append("\"").append(","); dataJson.forEach((key, value) -> sb.append(value).append(",")); return sb.substring(0, sb.length() - 1); } private static String timeLongToStr(long time) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); return sdf.format(new Date(time)); } }
【小插曲】
測試過程中,發現了一個問題,詳細請參考issue:https://github.com/taosdata/TDengine/issues/3818
==數據模型==
官網地址:https://www.taosdata.com/cn/documentation/architecture/#%E6%95%B0%E6%8D%AE%E6%A8%A1%E5%9E%8B
官網上面寫了TD的數據模型,不過沒有圖例進行直觀的說明,所以介紹的多少有些抽象。希望文檔上可以提升一下逼格。
【物理量】
也叫“測點”、“點位””。就像做心電圖時,粘在身上的幾個吸盤。一吸盤就是一個測點,也就是一個物理量。
我這里以智能水流量計為例,包括以下測點。
【數據采集點】
每個數據采集點可以采集多個物理量。
我覺得實際場景中的PLC應該算是一個數據采集點了。
【表】
一個數據采集點一張表。
【超級表】
同一類型數據采集點的集合。
我這里做了一寫想到哪里就試到哪里的嘗試。
1、先創建一個超級表
create table if not exists znsllj (time timestamp, ForwardIntegratedFlow double, BackwardIntegratedFlow double, InstantaneousFlow double, Velocity double, Density double, Temperature double, Pressure double, Error bool) tags(product nchar(256), device nchar(256));
2、基於超級表創建表
create table znsllj001 using znsllj tags("product1", "device1");
3、向表中插入一條數據
insert into znsllj001(time, ForwardIntegratedFlow, BackwardIntegratedFlow, InstantaneousFlow, Velocity, Density, Temperature, Pressure, Error) values(now, 10, 11, 12, 13, 14, 15, 16, 0);
4、如果修改表結構可以嗎?
alter table znsllj001 add column AddField double;
發現直接修改表的結構是失敗的,提示只能修改超級表
5、嘗試修改超級表結構
alter table znsllj add column AddField double;
發現修改成功,並且表的結構也跟着變化了。
6、分別查看一下表和超級表的結構
describe znsllj001;
describe znsllj;
7、刪除超級表中一個列(有數據的列)
alter table znsllj drop column ForwardIntegratedFlow;
看到的是可以成功刪除,同時表結構也發生了改變。
8、此時如果刪除超級表會如何?
drop table if exists znsllj;
看到可以正常刪除超級表,而且表也被連帶着一起刪掉了。
9、重新創建超級表、表及插入一條數據(修改了一下超級表和表的的前綴,便於區分)
create table if not exists st_znsllj (time timestamp, ForwardIntegratedFlow double, BackwardIntegratedFlow double, InstantaneousFlow double, Velocity double, Density double, Temperature double, Pressure double, Error bool) tags (product nchar(256), device nchar(256));
create table t_znsllj001 using st_znsllj tags("product1", "device1");
insert into t_znsllj001(time, ForwardIntegratedFlow, BackwardIntegratedFlow, InstantaneousFlow, Velocity, Density, Temperature, Pressure, Error) values(now, 10, 11, 12, 13, 14, 15, 16, 0);
10、繼續創建幾個表(同一個超級表)
兩個標簽值重復:create table t_znsllj002 using st_znsllj tags("product1", "device1");
標簽值都不重復:create table t_znsllj003 using st_znsllj tags("product3", "device3");
少一個標簽:create table t_znsllj004 using st_znsllj tags("product4");
無標簽:create table t_znsllj005 using st_znsllj;
多一個標簽:create table t_znsllj006 using st_znsllj tags("product6", "device6", "type6");
一個標簽值重復:create table t_znsllj007 using st_znsllj tags("product1", "device7");
結論如下:
表的標簽數量必須與超級表一致。
表的標簽值可以重復。
11、分別向幾個成功的表中插入一條數據
insert into t_znsllj001(time, ForwardIntegratedFlow, BackwardIntegratedFlow, InstantaneousFlow, Velocity, Density, Temperature, Pressure, Error) values(now, 10, 11, 12, 13, 14, 15, 16, 0);
insert into t_znsllj002(time, ForwardIntegratedFlow, BackwardIntegratedFlow, InstantaneousFlow, Velocity, Density, Temperature, Pressure, Error) values(now, 20, 21, 22, 23, 24, 25, 26, 0);
insert into t_znsllj003(time, ForwardIntegratedFlow, BackwardIntegratedFlow, InstantaneousFlow, Velocity, Density, Temperature, Pressure, Error) values(now, 30, 31, 32, 33, 34, 35, 36, 0);
insert into t_znsllj007(time, ForwardIntegratedFlow, BackwardIntegratedFlow, InstantaneousFlow, Velocity, Density, Temperature, Pressure, Error) values(now, 70, 71, 72, 73, 74, 75, 76, 0);
12、查看一下幾個表的數據(僅時間戳,正向累計流量)
select time, forwardintegratedflow from t_znsllj001 order by time;
select time, forwardintegratedflow from t_znsllj002 order by time;
select time, forwardintegratedflow from t_znsllj003 order by time;
select time, forwardintegratedflow from t_znsllj007 order by time;
13、檢索超級表的所有數據(時間戳,一個物理量(正向累計流量)、兩個TAG(產品、設備))
select time, forwardintegratedflow, product, device from st_znsllj order by time;
可以看到,通過超級表的結果會帶有標簽,普通表是么有標簽的。另外超級表只看標簽值,結果集中看不到具體是從哪個表中數據。
==聚合語句==
根據官方文檔進行了一堆驗證,感覺這些函數還不錯。但是在大量數據的情況下,結果是否正確沒有驗證過。僅進行了功能上的驗證,基本可以代替InfluxDB。
另外,對於“適用於”這一列,實際上與官方文檔有出入。至少在這個版本,我的驗證結果如下。
Excel版本的驗證結果,我共享到百度網盤了,有需要的自提。
鏈接:https://pan.baidu.com/s/1AOgDeGCqoOsvhGWu27Vrtg
提取碼:vxpb
==滾動升級測試==
目前版本的td尚屬於更新迭代很快的階段,所以難免會有一些bug發生,所以在實際使用中,會頻繁的進行版本升級。
這一點也會影響td是否能夠順利落地,以及長久使用的一個考量指標。我按照以下的方式進行了一次嘗試。
【驗證思路】
因為目前集群版release的就這一個版本,所以沒有辦法測試版本升級,只能測試卸載之后,在重新安裝。
【驗證結論】
卸載並重新安裝之后,集群可以正常使用。
【驗證過程】
1、先備份配置文件
分別將3個節點的配置文件下載並備份。
2、停止td集群
在3個節點分別執行命令:systemctl stop taosd
3、卸載tdengine
在3個節點分別執行命令:
#查看tdengine rpm -qa | grep TDengine #卸載tdengine yum remove TDengine-2.0.4.0-3.x86_64
4、查看卸載后的狀態
配置文件保留,沒有被刪除。
數據文件保留,沒有被刪除。
5、重新安裝集群
在3個節點分別執行:rpm -ivh /home/radmin/soft/TDengine-server-2.0.4.0-Linux-x64.rpm
6、觀察配置文件
配置文件沒有被覆蓋,保留了卸載之前的配置,這樣挺好的,省着重新配置了。
7、啟動集群
在3個節點分別執行命令:systemctl start taosd
8、進入命令行
在任意節點運行taos,確認可以進入命令行。
9、查看集群狀態
show dnodes;
查看數據庫show databases;
切換數據庫,並查看超級表
查詢任意表
2020年10月12日 13:38 追記
看到官方剛剛發布了2.0.5.0版本,按照下面的順序重新嘗試了一遍,結果一樣,順利升級成功。
2020年10月12日 14:00 追記
集群使用了一會之后,發現第2個節點宕掉了,
沒有辦法,由於着急測試,將tdengine卸載,然后刪除數據目錄,重新安裝之后才得以解決。
2020年10月12日 19:37 追記
服務器版本升級到2.0.5.0之后,taos-jdbcdriver的版本需要使用2.0.8,使用2.0.5的時候會報錯。感謝網友
2020年12月21日 9:24 追記
服務器從2.0.8.0升級到2.0.10.0,出現了一個問題。升級之后,通過shell查詢數據提示錯誤:DB error: Invalid message
在群里咨詢之后,最終問題得到了解決,不過不敢保證是以下哪個方式解決的,猜測是第1個原因
1、在升級taosd的時候,taos進程一直沒有關閉,升級之后也是用的2.0.8.0版本的taos shell檢索的。所以報錯
2、java客戶端版本不正確,java客戶端版本從2.0.12升級到2.0.15之后,重新執行程序確實解決了。
另外,從群里咨詢得到了一下幾個結論,后續升級需要注意:
濤思的版本升級規則是,前三位一致是版本兼容的,如不一致需要同步升級客戶端和服務端
==連續查詢==
在InfluxDB中有連續查詢的功能,可以按照一定的時間頻率對原始數據進行聚合,並將聚合結果放入到新的數據庫中,
具體可以參考我InfluxDB連續查詢的另一篇博客:使用InfluxDB的連續查詢解決聚合性能問題
同樣,在TDengine中也提供了連續查詢的功能,我這里需要驗證一下TDengine的連續查詢與InfluxDB的區別,
用來評估替換InfluxDB之后,對應用端的代碼改動的影響大小。
【語法嘗試】
1、創建連續查詢
create table avg_velocity as select avg(velocity) from st_znsllj interval(1m) sliding(30s);
在定義連續查詢的時候需要指定時間窗口大小(time window, 參數interval)和每次前向增量時間(forward sliding times, 參數sliding)。
2、查看連續查詢
show streams;
3、殺掉指定連續查詢
kill stream 3:1;
【小插曲】
在超級表的查詢語句中加上sliding之后,提示Redirect錯誤。Issue為:https://github.com/taosdata/TDengine/issues/3801
官方上是說在連續查詢上不建議使用sliding
4、嘗試將連續查詢的結果放入另一個庫
需要在查詢的表以及目標表上加上數據的名字即可。
create table qch_cq.device_data_up_sum as select sum(AI_PICK_UDATA) from qch_test.st_device_data_up interval(1m) sliding(30s) order by time desc;
【小插曲】
配置上連續查詢,並且程序段在一直的寫入數據,發現了幾個奇怪的現象
現象1:streamId會一直變化
==寫入性能測試==
我寫了一個單列模式的測試樣例,
1、測試服務器:3個節點(阿里雲ECS服務器,8核16G內存)
2、單client
3、單列模式
4、自動建表
5、分別測試5千,10萬,100萬測點,按照不同粒度批量寫入(每批100、1000、5000等共10個粒度)
6、1個超級表
在本地運行環境中跑,由於服務器在阿里雲上,受網絡的影響,速度時非常的慢的,
10萬點的數據,一共跑了3次,每次都差不多要1個小時才能跑完(一共3個小時)
如果把程序打成jar包,扔到阿里雲ECS服務器上跑,就快了太多太多了,
一樣的程序,每次10萬,一共3次,每次差多也就2分鍾就可以插入完成。
但是,感覺還是有一些慢,等找到一些優化的方法,在繼續更新。。。。
2020年11月10日追記:
嘗試了批量寫入的方式,比如每次寫入500條(由於是單列模式,相當於每次向500個表同時寫入數據)
從結果上看,速度確實要快了很多很多,是一個好的結果。
【小插曲】
由於是單列模式的批量插入,所以sql語句會非常的長,大概是下面的這種感覺,
當sql超過一定長度的時候,程序就報錯TDengine Error: Invalid SQL statement。
嘗試調整maxSQLLength參數,將限制放大到10倍,也就是654800,問題解決。
注意:
maxSQLLength是客戶端參數,是調用JDBC Connector的應用程序所在機器上的配置文件,
Linux OS 上默認值 /etc/taos/taos.cfg ,Windows OS 上默認值 C://TDengine/cfg/taos.cfg。
【測試結論】
測試結論:
1、單client,單列模式,自動建表模式,每秒寫入性能約每秒2萬條。
2、按照我目前的機器配置,批量寫入的時候,建議每批500條。
下圖是測試的統計圖。
==可靠性測試==
==數據備份==
==聚合性能驗證==
==實際落地姿勢==
筆記:2021年1月19日
目前在一個項目中,准備上TDengine,但是考慮到TDengine的一些實際情況
1、TD在快速的版本迭代過程中,難免會有一些問題不能第一時間解決(需要提Issue)
2、社區版的解決速度也會比預期的要慢一些 (實際上還是比較不錯的了)
3、TD本身是用C語言開發的,能獨立解決TD問題的人不多(年輕人,會C的人不是很多)
綜合考慮之后,沒有獨立的使用TDengine來支撐項目,而是采用了以下方案
1、使用InfluxDB(社區版)來支撐實時業務,數據存儲時間不超過3個月。並使用連續查詢來支撐實時聚合。
2、使用TDengine(社區版)來支撐分析業務,數據存儲時間為默認的10年。使用單列模式,來支撐測點的增減場景。
這樣的好處是,可以充分使用InfluxDB的穩定,來確保實時類業務的可靠性。
同時有可以引入TDengine的新物種,帶來聚合性能的提升,給業務帶來一些成長因素。
筆記:2021年4月7日 20:30
我們在InfluxDB和TDengine之外包裝了一層SDK,對應用層暴露SDK,這樣應用層就不需要關心到底用的哪個存儲技術了。
在SDK中需要解決以下問題:
1、檢查InfluxDB及TDengine的連接狀態,如果其中一個宕了,使用另一個。
2、判斷查詢數據的起始時間,如果在時間范圍內則查詢InfluxDB,如果超過一定時間則使用TDengine。
3、翻譯應用端的查詢語句以及查詢的數據結果。統一到InfluxDB的數據格式。
實際場景中的數據備份方案還沒有最終確定,后續更新。
--END--