TDengine 使用最佳实践

简介

阅读本文档需要具备的基础知识:

  • Linux系统的基础知识,及基本命令
  • 网络基础知识:TCP/UDP、http、RESTful、域名解析、FQDN/hostname、hosts、防火墙、四层/七层负载均衡

本文档的阅读对象有:架构师、研发工程师,及DBA、运维工程师

写在前面

TDengine是一时序大数据平台,核心是时序数据库(TSDB: Time Series DataBase)。虽然其CLI/API支持类SQL的语法来进行数据写入查询、数据库维护,但其本质上不是RDBMS(如MySQL、Oracle)。采用SQL语法的目的仅仅是为了减少用户的学习成本,切记!

与大多数数据库产品不同的是,TDengine客户端与服务端的连接方式。对于一般数据库来说,客户端发起的连接是至集群某一节点的TCP长连接,需要访问数据库服务时建立,使用完了即关闭。

TDengine设计思想是全分布式的:以taosc连接方式为例,客户端除首次获取集群的meta-data时需要连接到指定节点(firseEP/secondEP) 外,一旦获取到了meta-data,客户端驱动会将其缓存下来,后续客户端与服务端的交互由驱动根据需要建立一(客户端)对多(节点)的TCP/UDP连接。获得meta-data后,与指定节点firstEP的连接即刻释放。

应用通过taosc创建的taos_connect连接是虚拟连接,作为应用访问集群的接口。最佳实践是:在应用生命周期内,该连接永远有效,不建议频繁建立、关闭taos_connect连接。仅当应用关闭前,释放连接即可。

这样设计的优点是:

  • 不存在单点故障:firstEP/secondEP提供了客户端获取meta-data的备份功能;集群有多副本支持
  • 不存在单点瓶颈:获取meta-data的时间短,一旦成功获取后客户端无需频繁访问firstEP
  • 水平扩展简单便捷:增加新节点后,meta-data发生改变,客户端会按需动态刷新

TDengine的重要特性

  • 超级表:带上静态属性标签(tags)的表结构描述,超级表本身不存数据。超级表用来作为模板创建子表/普通表,创建子表时指定对应的标签值即可。
  • 首列必须为时间戳且为表的主键,一个表最少要有两列:第一列时间戳,另一列数据列。
  • 索引:仅首列时间戳及第一个标签列带索引(建表时自动建立),其他列无论是普通列还是标签列,均无索引,也无法建索引。标签均为全内存存储,以提升效率。
  • group by:对标签列、表名(tbname)有效,普通列(整型、binary类型)仅当该列不重复值(distinct)小于100万可用于group by。
  • 写入数据:按时间戳顺序批量写入可以达到最佳写入速度,常用的方案有:单表单条拼多表,单表多条拼多表。三种接口的写入速度排序为:taosc-stmt > taosc > RESTful。

RESTful: 通过RESTful协议,传入sql语句解析实现,不依赖客户端驱动**【推荐使用】**

taosc: taosc写入接口,通过传入sql语句解析实现,依赖客户端驱动

taosc-stmt: 为taosc的特殊实现,通过参数绑定API实现快速写入,避免了字符串解析。目前仅支持单表单条写入、批量提交,依赖客户端驱动

  1. 时序数据库仅保留指定时间段的数据,写入时如报时间戳越界错误,意味着写入数据的时间戳太旧(超过保留期限),或太新(写入的是未来的时间)。
  2. 乱序写入需要认真评估。TDengine允许少量的乱序写入,但如果写入的数据存在大量乱序,将严重影响写入速度。如数据是从消息队列(如kafka)消费入库,需确保每个采集量进入消息队列是按顺序进入指定的partition。详见 这里

多列宽表写入时,建议以全列方式写入,不建议采用指定列的方式,以获得最佳写入性能,无数据的列填NULL即可。

  • 三种接口:客户端可通过taosc、taosc-stmt、RESTful三种接口访问服务端。其中taosc和RESTful均通过sql语句交互,taosc-stmt通过参数绑定API传入参数,写入性能较优。

RESTful接口写入性能与taosc相比,性能约下降30%,可以满足绝大部分应用场景,推荐使用

  • 排序:默认支持的排序结果集为10万条记录,最大支持100万,可通过maxNumOfOrderedRes选项配置。
  • 返回结果集:RESTful默认返回结果集上限为10240条,最大支持1000万,可通过restfulRowLimit选项配置。
  • Update:数据库创建时,可以设置update开关,默认为关。打开时,如insert数据之时间戳已经存在,后面的数据将覆盖已存在的记录。如关闭,则丢弃后面写入的数据。
  • 不支持手动删除指定记录,数据在超过保留天数后自动删除。但支持删除库、表的操作。
  • 时钟:客户端与服务端需保持时钟同步。

一、安装部署篇

1.1 安装基本流程

目前TDengine服务端仅支持Linux X64系统,推荐CentOS 7.9 和 Ubuntu 18.04。硬件平台支持X64和arm64。

客户端支持Windows X64、Linux X64。

mac版在开发中,将提供有限功能,用于开发环境。

安装服务端之前,需做好以下准备:

a) 准备好至少一台Linux X64服务器,可用磁盘空间足够

b) 配置好hostname

c) 网络环境正常,网络内TCP/UDP可正常通信

d) 防火墙已关闭

1.1.1 服务端安装步骤
  1. 从官网上下载tar.gz的安装包 https://www.taosdata.com/cn/getting-started/
  2. 上传至服务器指定目录,解压缩 sudo tar xzvf TDengine-server-2.1.3.2-Linux-x64.tar.gz
  3. 进入解压后的子目录,安装 cd TDengine-server-2.1.3.2 && sudo ./install
  4. 编辑 /etc/taos/taos.cfg,将firstEP和fqdn修改为本机的hostname【后续节点如需加入集群,需修改fqdn为该节点的hostname】
  5. 编辑/etc/hosts,将集群所有节点的域名解析添加进去(如已部署DNS server,则无需编辑)
  6. 启动taosd服务 sudo systemctl start taosd
  7. 进入taos CLI查看数据节点 taos > show dnodes;
常用命令
复制代码
$ sudo systemctl start taosd		//启动taosd服务
$ sudo systemctl stop taosd			//停止taosd服务
$ sudo systemctl status taosd		//查看taosd状态
$ sudo rmtaos										//卸载TDengine服务端、客户端,数据文件、配置文件将保留

> SHOW DNODES;									//查看数据节点dnode信息
> SHOW MNODES;									//查看管理节点mnode信息
> SHOW VARIABLES;								//查看当前集群运行参数
> USE dbname;										//打开数据库dbname
> SHOW VGROUPS;									//显示当前数据库虚拟节点组信息

配置文件 taos.cfg

典型的服务端配置文件

Apache 复制代码
firstEp                   node1:6030   //集群第一个节点
 fqdn                      node1	//本机hostname
 numOfMnodes               1            //管理节点数量,默认1,上限3且小于等于节点数
# arbitrator               arbi:6042	//双副本时需配置arbitrator,独立机器
 logDir			   /var/log/taos	//日志文件夹
 dataDir		   /var/lib/taos	//数据文件夹
 numOfThreadsPerCore       2.0		//客户端RPC的收发线程比例因子
 ratioOfQueryCores         2.0		//查询线程比例
 numOfCommitThreads        4.0		//落盘线程数
 minTablesPerVnode         1000		//每vnode创建表数初始值
 tableIncStepPerVnode      1000		//每vnode新增表数步长值
 maxVgroupsPerDb           32           //每Db最大Vgroups数量,0为不限制(不建议)
 minRows		   100		//每张表最小落盘记录数
 keepColumnName            1		//保留原列名
 balance                   0		//关闭自动负载均衡
 blocks                    6		//每vnode写入缓存块数
 maxSQLLength              1048576	//最大SQL长度
 maxNumOfOrderedRes        100000	//超级表排序结果集最大记录数,上限1亿
 maxNumOfDistinctRes       10000000     //返回不重复值结果集最大记录数,上限1亿
 maxWildCardsLength        100          //通配符前字符串最大长度,上限16384
 update                    2		//允许部分列更新,创建数据库时生效
 cachelast                 1		//打开cachelast,创建数据库时生效
 timezone                  UTC-8
 locale                    en_US.UTF-8
 charset                   UTF-8
 maxShellConns             50000
 maxConnections            50000
 monitor                   1		//打开内部log监控数据库
 logKeepDays               -1		//压缩保存一天日志
 debugflag                 131		//设置131日志开关,仅打印最小日志信息
 slaveQuery                0            //vgroup查询发送到slave节点开关,默认关闭
 rpcForceTcp               1            //强制打开TCP通信
 offlineInterval           15           //检测判断dnode offline的时间间隔
 tcpConnTimeout            100          //检测vnode在线状态的超时值
1.1.2 客户端安装与配置

如已安装服务端,则该服务器已包含客户端驱动,无需安装。【如果在某台服务器上安装了TDengine服务端,用其客户端连接另外的taosd集群,请检查该客户端与被连服务端版本是否一致】

客户端安装步骤与服务端基本相同,解压缩后运行安装脚本即可完成。

编辑/etc/hosts,将集群所有节点的域名解析添加进去(如已部署DNS server,则无需编辑)。确保客户端通过网络可以访问到服务端,如不能ping通服务端节点的fqdn,请联系贵司网络管理员。

客户端安装成功后,需配置/etc/taos/taos.cfg才能访问TDengine服务:firstEP/secondEP。

典型的客户端配置文件

Apache 复制代码
firstEp                   node1:6030		//集群第一个节点
 secondEp                  node2:6030		//集群第二个节点
 logDir			   /var/log/taos        //日志文件夹
 numOfThreadsPerCore       2.0
 maxSQLLength              1048576
 maxNumOfOrderedRes        100000	//超级表排序结果集最大记录数,上限100万
 maxNumOfDistinctRes       10000000     //返回不重复值结果集最大记录数,上限1亿
 maxWildCardsLength        100          //通配符前字符串最大长度,上限16384
 timezone                  UTC-8
 locale                    en_US.UTF-8
 charset                   UTF-8
 maxConnections            50000
 logKeepDays               -1
 debugflag                 131
 rpcForceTcp               1

时区一般默认注释掉,将获取操作系统的当前时区作为taosd的时区。但某些情况下,需要手工指定时区时,可尝试指定为特定时区。【不是所有的操作系统均支持指定时区,建议事先确认后再实施】

客户端建议配置logDir并确保运行应用的账号拥有该文件夹访问权限,否则日志将无法生成。

一般情况下,建议安装TDengine客户端驱动。客户也可以不安装客户端,仅导入动态链接库也可实现完整的客户端驱动功能,只是缺少相关工具如taos CLI、taosdemo。默认taos.cfg路径为/etc/taos。

Linux系统的方法如下:

  1. 拷贝动态链接库至/usr/local/taos/drivers sudo cp libtaos.so.2.1.3.2 /usr/local/taos/drivers
  2. 建立符号链接
Shell 复制代码
sudo ln -s /usr/local/taos/drivers/libtaos.so.2.1.3.2 /lib/libtaos.so.1
sudo ln -s /lib/libtaos.so.1 /lib/libtaos.so

Windows系统同样支持,可将dll拷贝到c:\Windows\System32,默认taos.cfg路径为c:\TDengine\cfg

1.2 集群部署:扩容、缩容、迁移vnode

1.2.1 扩容 - 增加节点
  1. 第一个节点部署完成后,在后续节点依次安装TDengine服务端,编辑/etc/hosts,将集群所有节点的域名解析添加进去(如已部署DNS server,则无需编辑)
  2. 将第一节点taos.cfg拷贝至当前节点,配置taos.cfg,修改fqdn为本机hostname
  3. 启动本机taosd sudo systemctl start taosd
  4. 运行taos CLI,将本节点添加至集群 > create dnode 'node2:6030';
  5. 查看数据节点列表 > show dnodes;

节点正常加入集群后,数据节点列表中会显示该节点处于ready状态。

如该节点为offline状态,请检查:

a) 该节点taosd是否已启动、防火墙是否关闭、数据文件夹是否清空;

b) 所有节点/etc/hosts域名解析是否完整(内含所有节点的解析,包括arbitrator)、正确;

c) 该节点firstEP、fqdn是否正确配置。

1.2.2 缩容 - 减少节点

缩容只能通过drop dnode来实现,直接停止taosd进程只能将该节点下线,不能完成缩容。切记!

  1. 运行taos CLI登入集群,查看集群节点信息 > show dnodes;
  2. 从当前集群中删除指定节点 > drop dnode 'node2:6030';
  3. 查看集群节点信息,确认待删除节点已从列表中剔除 > show dnodes;

集群在完成drop dnode操作之前,须将该dnode的数据迁移走。

数据迁走需要一定时间,时间长短取决于该节点上的须迁出的数据量大小,以及网络带宽、磁盘IO。在节点从列表中剔除之前,万不能停止该节点taosd服务

一个节点被drop之后,不能立即重新加入集群。加入任何集群之前,需要将节点重新部署(清空数据文件夹、配置taos.cfg、重启taosd、将节点添加至集群)。

1.2.3 迁移vnode

当一个数据库的某个vnode数据过热时,可手动迁移该vnode至指定的数据节点。

该操作仅在自动负载均衡选项关闭(balance=0)时方可执行。

  1. 运行taos CLI登入集群,查看集群节点信息 > show dnodes;
  2. 查看待数据库(mydb)虚拟节点组信息 > show mydb.vgroups;
  3. 将当前节点(source-dnodeId)的vnode(vgId),迁移至指定节点(dest-dnofeId) > ALTER DNODE <source-dnodeId> BALANCE "VNODE:<vgId>-DNODE:<dest-dnodeId>";

1.3 Arbitrator

当集群中数据库配置为双副本(replica=2)时,需部署arbitrator以防止集群某节点下线时,有关的虚拟节点组重新选主遇到"脑裂"的问题。

arbitrator须部署在一台独立的机器上,因占用资源很少,可以与其他服务公用一台机器。如需单独部署,1C2G的配置即可。

1.4 taosAdapter

在2.4版本中,httpd从taosd分离出来,成为独立的服务进程:taosadapter。taosAdapter 是一个 TDengine 的配套工具,是 TDengine 集群和应用程序之间的桥梁和适配器。它提供了一种易 于使用和高效的方式来直接从数据收集代理软件(如 Telegraf、StatsD、collectd 等)摄取数据。它还提供了 InfluxDB/OpenTSDB 兼容的数据摄取接口,允许 InfluxDB/OpenTSDB 应用程序无缝移植到 TDengine。

taosAdapter提供以下功能: (具体使用可以参考官网文档或 GitHub )

  • RESTful 接口,端口默认还是6041,可以使用任何支持 http 协议的客户端通过访问 RESTful 接口地址 "https://:6041/" 来写入数据到 TDengine 或从 TDengine 中查询数据
  • 兼容 InfluxDB v1写接口
  • 兼容 OpenTSDB JSON 和 telnet 格式写入 - 无缝连接到 Telegraf
  • 无缝连接到 collectd
  • 无缝连接到 StatsD
1.4.1 注意事项

taosAdapter的配置文件为 /etc/taos/taosadapter.toml。需要说明的是,日志路径path需要单独配置。默认/var/log/taos路径需要注意操作系统的 / 目录空间大小,如果不进行修改,很可能会把 / 目录空间占用完。

taosAdapter启停,需要通过systemd。默认情况下,taosAdapter没有设置开机自动启动。

如需restful服务,需手动启动taosAdapter服务:systemctl start taosadapter,并设置开启自动启动:systemctl enable taosadapter。

企业Web shell需依赖RESTful,如需使用Web shell则需启动taosAdapter。

1.4.2 taosAdapter参数配置

taosAdapter 支持通过命令行参数、环境变量和配置文件来进行配置。 可以通过taosadapter --help查看具体参数介绍。

命令行参数优先于环境变量优先于配置文件,命令行用法是arg=val,如 taosadapter -p=30000 --debug=true

taosadapter.toml示例配置文件参⻅ https://github.com/taosdata/taosadapter/blob/develop/example/config/taosadapter.toml ,修改完taosadapter.toml后,需要重启服务生效:systemctl restart taosadapter

关键参数配置:

Bash 复制代码
port = 6041               //默认端口号
logLevel = "info"         //日志级别,如需调试则改为debug
restfulRowLimit = 10240   //限制查询返回最大记录条数。针对/rest/sql /rest/sqlt /rest/sqlutc

[log]
path = "/var/log/taos"    //建议修改为自定义路径
rotationCount = 30        //日志保留个数
rotationTime = "24h"      //日志保留时间
rotationSize = "1GB"      //单个日志文件大小

1.5 时间同步:客户端/服务器

集群内所有服务器,以及客户端机器均需保持时钟同步。

生产环境中,无论是否能连接互联网,建议部署本地ntp服务器,采用ntpdate与ntpd结合的方式实现各机器之间的时钟同步。

复制代码
ntpdate -u cn.pool.ntp.org
hwclock --systohc
ntpd start

1.6 中文字符

TDengine默认字符集为UTF-8。

在Windows系统中,大多采用GBK/GB18030存储中文字符,TDengine的客户端驱动会将其统一转为UTF-8编码,发送至服务端存储。应用开发时,在调用接口时正确配置当前的中文字符集即可。

在TDengine中,中文字符或其他大字符集字符需用nchar类型存储,不能用binary进行存储,否则在用taosdump工具导出导入时将出现乱码,导致不可修复的异常。

【v2.2.1.5以后版本】建议在Windows 10环境下,在taos.cfg中设置

Apache 复制代码
locale C
charset UTF-8

运行Windows版taos命令行工具,可正常输入、显示中文。

1.7 mac版本环境搭建与使用

mac版本目前尚未正式发布,仅用于开发研究使用。

mac os X的版本要求:Catalina 或 Big Sur

安装步骤:

  1. 建议先安装XCode command line tool、git、brew,再通过brew安装cmake、tmux

  2. pull TDengine最新develop分支代码 git pull

  3. 编译步骤:

    mkdir debug && cd debug
    cmake .. && cmake --build .

  4. 快速启动taosd并运行taos CLI(建议启动tmux,开两个窗口)

    build/bin/taosd -c test/cfg //第一个tmux窗口
    build/bin/taos -c test/cfg //第二个tmux窗口

mac作为客户端开发环境使用taosc连接服务端时,需用到动态链接库。该库位于:

复制代码
./build/lib/libtaos.2.1.3.2.dylib

同时该目录下有两个符号链接,最终均指向该文件

复制代码
./build/lib/libtaos.1.dylib
./build/lib/libtaos.dylib

1.8 多级存储

TDengine 2.0 仅企业版支持多级存储。

多级存储支持三级:0级、1级、2级。每级支持16个挂载点。

最热的数据放在0级,最冷的数据放在2级。

如需在某一级存储需部署多块硬盘,部署方案建议采用:LVM 或 LVM+RAID5

1.9 taos.cfg重要参数说明

taos.cfg里面配置的参数在启动taosd时,作为默认参数载入运行实例。主要的参数有:

numOfThreadsPerCore​ ​客户端RPC的收发线程比例因子

【全局参数】客户端RPC收发线程数 = CPU核的数量 * NumOfThreadsPerCore (默认是1) / 2.0

ratioOfQueryCores 每CPU核查询线程比例

【全局参数】设置每个CPU核启动的查询线程与核数的比例

numOfCommitThreads 落盘线程数

【全局参数】设置每个vnode落盘线程数,建议与挂载的硬盘数量一致

minTablesPerVnode 每vnode创建表数初始值

【全局参数】每个vnode首次创建普通表的上限,默认为1000。如系统表数小于5000,须修改本参数。假设共500张表,集群CPU有24核,则建议设置round(500/24)=20

tableIncStepPerVnode 每vnode新增表数步长值

【全局参数】每个vnode后续新增表的步长值,默认为1000。可与minTablesPerVnode保持一致

minRows 每张表最小落盘记录数

【数据库参数】每张表最终落盘的最小记录数,默认为100。当vnode写入缓存达到满1/3触发落盘时,该参数将决定数据写往永久存储.data文件(该表待落盘记录数大于minRows时),还是写入临时存储.last文件(该表待落盘记录数小于minRows时)

keepColumnName 保留原列名

【全局参数】当select语句带有函数时,默认返回结果列名为函数+列名。如需保留原列名,需打开本选项

balance 自动负载均衡

【全局参数】默认关闭自动负载均衡

blocks 每vnode写入缓存块数

【数据库参数】每个vnode配置的写入缓存计算公式为cache*blocks。cache默认为16MB,blocks=6,建议cache保持不变,通过修改blocks来调整写入缓存大小。该参数在创建数据库时生效。

该参数大小将影响每张表落盘的平均记录数,如希望达成更好的写入、查询性能,需设置尽可能大的blocks,但这也需要服务器配置更大的内存。

该参数与数据库的超级表数量、超级表的平均行长度、子表数、副本数、虚拟节点组数相关。

maxSQLLength 最大SQL长度

【全局参数】设置一条SQL语句最大的长度。默认65480,最大1048576。设置为较大值,将允许一条SQL语句拼接尽可能多组记录,或多个表的记录,以实现更快的写入速度。

maxNumOfDistinctRes 不重复值结果集最大记录数

【全局参数】设置distinct函数返回的不重复值结果集最大记录数,默认1000万,最大1亿。

update 更新

【数据库参数】每个数据库可设置是否允许覆写已存在的记录,创建数据库时生效。打开本选项,写入相同时间戳的记录时,将覆写已存在的记录,反之,则丢弃后面写入的记录。

cachelast 内存中缓存最后一条数据

【数据库参数】每个数据库可设置是否允许在内存中缓存每张表的最后一条数据,创建数据库时生效。

monitor 内部监控数据库

【全局参数】打开本选项,会创建log库,用于内部监控,默认打开。建议打开。

logKeepDays 保存日志

【全局参数】设置日志文件保存时长。0 - 仅保留两个日志文件;正数 - 保留天数,不压缩;负数 - 保留天数,压缩。

debugflag 日志级别开关

【全局参数】设置日志级别,默认131。131 - 仅打印最小日志信息;135 - 打印详细日志信息;143 - 打印全量日志。

rpcForceTcp 强制使用TCP通信​**【v2.0.20.19以后版本支持】**

【全局参数】该选项打开后,所有从本节点发出的消息均通过TCP发出。默认关闭

关闭时,小于15KB走UDP,超过的走TCP。

offlineInterval 检测数据节点dnode在线状态的时间间隔【v2.4.0.1以后版本支持】

【全局参数】设置检测dnode离线状态的时间间隔。mnode在超过该设定值的时间内没有收到dnode回应,将其状态置为offline。单位:秒,默认:3

tcpConnTimeout 检测vnode在线状态的超时值【v2.4.0.16以后版本支持】

【全局参数】设置检测vnode在线状态的超时值,单位:ms。默认值:1000

1.10 如何定位、排除故障

taosd服务不能启动、SQL写入异常等情况发生时,都需要定位问题原因,才能解决问题。

TDengine提供了日志用于问题定位和分析,分为:taosd服务端日志taosdlog & taosinfo,客户端日志taoslog。

日志存放位置由配置文件taos.cfg中的logDir指定,默认路径是:

Linux /var/log/taos

Windows C:/Windows/log

日志文件最大长度由numOfLogLines(默认10,000,000)来进行配置,一个taosd/taosc实例默认保留两个文件(当logKeepDays = 0时)。

日志开关debugflag

日志开关debugflag是日志的总控制开关,分三级:131、135、143.

131 - 仅打印最小日志信息

135 - 打印详细日志信息

143 - 打印全量日志

系统默认为131,如需定位问题,建议打开135后,重启taosd或应用,以让新的debugflag设置生效。建议在停止服务时,删除已有的日志文件,便于问题定位。

【提示:问题定位分析结束后,记得将debugflag改回131。切记!】

在线修改debugflag

taosd可能因某种原因不能重启,也可能无法响应taos的连接请求,下面的方法可以在不重启taosd的情况下,快速设置日志开关。

方法一:在taos CLI里面在线修改日志开关

复制代码
> ALTER DNODE nn DEBUGFLAG 131|135|143;			//修改节点nn的debugflag
> ALTER DNODE nn RESETLOG;									//重置节点nn的taosd日志文件

方法二:在OS命令行在线修改日志开关

复制代码
$ kill -SIGUSR1 <PID of taosd>							//将PID的taosd的debugflag设为143
$ kill -SIGUSR2 <PID of taosd>							//重置PID的taosd的日志文件

1.11 安装常见问题

安装完成,连接TDengine时报错Unable to resolve FQDN

A TDengine的服务器节点必须配置FQDN(fully qualified domain name,完全限定域名)才能实现节点之间的通信。

简单来说,FQDN可以等同于服务器主机的hostname,通过hostname -f查询获得。配置TDengine服务端的FQDN时,直接将hostname -f获得的该服务器主机名,填入本机taos.cfg的FQDN即可。

需要注意:

  1. FQDN依赖于hostname的域名解析,才能实现节点间通信。所有服务器节点、客户端的域名解析(hosts文件或DNS服务),**必须配置所有服务器节点(包括arbitrator)**的域名解析
  2. 不建议使用localhost或者IP地址作为FQDN,除非本机作为开发环境仅供本机客户端连接
  3. firstEP/secondEP是集群某个节点的FQDN:serverPort (serverPort默认为6030)
  4. hosts文件位置。Linux: /etc/hosts Windows: C:/Windows/System32/drivers/etc/hosts

部署了单机版TDengine,可以升级为集群吗?

A 单机版就是一个节点的集群,请参看集群扩容章节进行扩容

部署了两个单机版TDengine,可以合并为一个集群吗?

A 不能。两个单机版是两个独立的集群,无法合并。只能将其中一台taosd停下后,清空数据文件夹,重新加入另一台的集群

之前部署的时候把FQDN配置成了localhost,想更换FQDN如何操作?

A 这是一个危险的操作,建议操作前建议做好数据目录的备份。

首先,停止taosd服务;在/etc/hosts中配置新的fqdn对应的host的域名解析;修改taos.cfg,修改firstEP和FQDN;

然后,修改$dataDir/dnode/dnodeEps.json,将dnodeFqdn为localhost的值改为期望值;

最后,重启taosd。

TDengine已成功安装,也启动了,但taos CLI登录报错Unable to establish connection是怎么回事?

A taosd服务没有正常启动,可能的原因有:

a) taosd是否已启动、防火墙是否关闭、数据文件夹是否清空

b) 所有节点/etc/hosts域名解析是否完整、正确

c) 各节点firstEP、fqdn是否正确配置

另外,可以通过以下步骤来查看客户端与服务端通信是否正常:

a) 停止taosd服务后,在服务端运行 taos -n server

b) 在客户端运行 taos -n client -h <server>

c) 查看哪些通信端口工作异常,再找网络管理员逐一排查

如何读日志文件?

A 服务端日志有taosinfo和taosdlog,客户端日志taoslog。

用户无需读懂TDengine系统日志,在发生错误时,grep日志里面的ERROR信息,发送给涛思技术支持团队一般可判定大部分问题。

某些情况,需要将ERROR发生的前20万行后5万行发给涛思进行分析定位。

为何客户端连接服务端失败,报taos connect failed, reason: Invalid app version

A 客户端与服务端版本不一致所致。

TDengine版本号分为四段,客户端与服务端需保证前三段相同,才能正常工作。例如2.1.3.0的服务端可以和2.1.3.2的客户端通信,反之亦然。但不能与2.1.2.x/2.0.20.xx ... 通信。

域名解析如何配置?

A 域名解析可通过配置hosts或DNS服务来实现。以hosts文件为例,Linux域名解析可通过/etc/hosts,Windows的域名解析通过C:/Windows/System32/drivers/etc/hosts来实现,用户可以编辑该文件实现本地的域名解析。

Windows下面打开终端运行taos ​CLI查询中文却显示乱码?

A 在Windows环境中,须将终端字符集修改为65001 UTF-8代码页(chcp 65001),即可正确显示中文等字符集。

二、数据建模

本文提到的数据模型是指数据库中对数据的组织、描述方式,具体来讲就是表结构的设计。TDengine要求写入数据前提前创建表,但创新性地提出"一个采集点一张表"的表设计思路,相较关系型数据库有很大的创新。以下是使用TDengine处理时序数据前最重要的一些数据建模原则。

2.1 基本概念

2.1.1 一个采集点一张表

首先要明确,TDengine只处理时序、结构化的数据。这类数据有清晰的采集点(数据源)和其产生的时间序列数据(时间线),并且对于采集点往往有一些不随时间变化的静态属性(标签)。

以物联网场景智能电表举例:一个实时采集电流、电压状态数据的智能电表,就是一个数据源,而它按照时间顺序采集的电流、电压数据构成一簇时间线,电表本身的设备ID、部署的城市、城区等信息是不随时间变化的标签。

TDengine定义的采集点,在同一时刻只可能采集一条数据记录,因此对单个采集点而言,数据的采集时间是严格单调递增的。TDengine的建表原则是,对每一个采集点(数据源)创建一张表去存储其产生时间序列数据。表采用关系型数据库的行列结构(注意:TDengine不是关系型数据库,并不支持所有SQL语句语法),但表中的第一列必须是主键、且要求必须是timestamp类型,用于存储数据记录的采集时间;从第二列开始,存储该采集点每条记录中上报的多个固定采集指标,比如智能电表采集的电流、电压。

2.1.2 超级表

由于一个数据采集点一张表,导致表的数量巨增,难以管理,而且应用经常需要做多个采集点之间的聚合操作,如果应用层代码要操作的表数目过多,则聚合的操作会变得非常复杂。为解决这个问题,TDengine引入超级表(Super Table,简称为STable)的概念。超级表是对某一类型的数据采集点的描述,它既用来定义这类采集点的表结构,同时又作为所有这类采集点数据的查询入口,简化应用层的查询复杂度。

同一类型的数据采集点,其表的结构是完全一样的,但每个表(数据采集点)的静态属性(标签,如设备编号等)是不一样的。描述一个超级表(某一特定类型的数据采集点的结合),除需要定义采集量的表结构之外,还需要定义其标签的表结构schema,标签的数据类型可以是整数、浮点数、字符串,标签可以有多个,可以事后增加、删除或修改。 如果整个系统有N个不同类型的数据采集点,就需要建立N个超级表。

在TDengine的设计里,表用来代表一个具体的数据采集点,超级表用来代表一组相同类型的数据采集点集合 。当为某个具体数据采集点创建表时,用户使用超级表的定义做模板,同时指定该具体采集点(表)的标签值。与传统的关系型数据库相比,表(一个数据采集点)是带有静态标签的,而且这些标签可以事后增加、删除、修改。一张超级表包含有多张表,这些表具有相同的时序数据表结构schema,但带有不同的标签值

建超级表示例
复制代码
> CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (deviceid binary(20), city binary(20), district binary(20), type int);

【提示:超级表的第一个tag上有主键索引(上面示例为deviceid),一旦创建无法删除,须特别留意;标签列为静态属性列,频繁变动的列不建议作为标签列】

以超级表为模板创建子表示例
复制代码
> CREATE TABLE d1001 USING meters TAGS ("d1001","Beijing","chaoyang",2);

【提示:创建子表时,需使用超级表做模板,同时指定标签的具体值,标签值可事后修改;一个超级表可包含若干子表,子表数量没有限制;不同子表标签值允许相同,例如若干电表(d1001/d1002...)都属于某个城市(city)】

2.2 建表思路及原则

不同于OpenTSDB、Promtheus等时序库,TDengine允许一个表有多个列(即每条记录中,多个采集量共用一个时间戳的存储方式),提供了建表时更大的灵活性。

智能电表是个典型的可以按照设备建表,多列存储时序数据的例子。但在实际使用过程中,情况可能会更复杂,一定要结合本身数据的情况来灵活设计表结构。

2.2.1 按照设备建表的标准情形

上文中的智能电表例子就是一个设备一张表的标准情形。这种标准情形有以下特点:

(1) 相同类型的设备,采集指标完全相同。(比如上文例子中的智能电表,只采集电流、电压、相位三个指标)

(2) 同一个设备而言,各采集指标同时采集,采集时间戳相同。

(3) 同一个设备而言,各采集指标每次采集的数据最好是在同一个消息中上报到TDengine,而非分别上报。

这种情况的处理最简单:

  1. 采用多列模式,即为给类型的设备创建一张多列超级表。
  2. 为该类型的每个设备创建一张子表。
  3. 子表从第二列起,每一列均为一个采集指标。
2.2.2 按照设备建表,但同类型设备的采集指标不完全相同

实际生产中,同类型的设备有时候采集指标也不完全相同,这种情况下有以下特点:

(1) 相同类型的设备,采集指标大体相同,但每个设备可能有少量个性化的指标。(前提:所有个性化指标总数加上共有指标总数不超过1024个)

(2) 同一个设备而言,各采集指标同时采集,采集时间戳相同。

(3) 同一个设备而言,各采集指标每次采集的数据在同一个消息中上报到TDengine,而非分别上报。

这种情况类似于2.1,但区别是每个设备可能有个性化的采集指标。这种情形处理思路常称为"大宽表":

  1. 创建一个多列超级表,包含所有不同的采集指标列,为所有采集指标的全集。
  2. 为每个设备创建一张子表。
  3. 子表从第二列起,每一列均为一个采集指标。
  4. 数据写入时,对于该设备不具备的采集指标填入null值。
2.2.3 按照采集指标建表

更复杂的场景中,设备的固定表结构很难抽象出来,或者表结构经常改变,无法固定,此时需要有更灵活的处理思路。以下任一个特点满足时,需考虑按指标建表的思路:

(1) 相同类型的设备,采集指标无法固定,或者每个设备有大量个性化的指标。(所有个性化指标总数加上共有指标总数超过1024)

(2) 同一个设备而言,各采集指标有各自的采集时间戳。(即同一个设备的不同采集指标的采集时间、采集周期等无法保证相同)

(3) 同一个设备而言,各采集指标每次采集的数据分多个消息上报到TDengine,且时间延迟无法确定。

这种情形要求更高的灵活性。一般处理思路如下:

  1. 创建单列的超级表,即时间戳+采集值,而在标签项中增加采集指标ID这一标签。
  2. 每个设备的每个采集指标单独创建一张表,在标签项中增加具体的采集指标ID。
  3. 不同数据类型的采集指标要划归不同超级表,比如数值型、布尔型和字符串型的数据应该分别归入三类对应的超级表。

三、数据读写

写在前面

TDengine支持多种接口写入数据,目前支持三种接口:taosc-stmt、taosc、RESTful。三种接口的写入性能排序为:taosc-stmt > taosc > RESTful。

应用开发支持多种开发语言,包括C/C++, C#, Java, Go, Rust, Python, node.js,通过相应的接口来写入或查询数据。用户还可以通过TAOS Shell,手动输入SQL Insert语句来写入,或通过导入csv文件来批量导入。

不同开发语言连接器支持三种接口的列表:

taosc-stmt taosc RESTful other
C/C++
C#
Java JDBC RESTful
Go
Rust
Python
node.js
写入最佳实践

TDengine支持单条数据写入,及批量多条数据写入。批量写入时(taosc-stmt目前仅支持单条数据写入),支持一条SQL语句写入一个数据采集点/表的多组数据,也支持一条SQL语句写入多个数据采集点/表的数据。

支持多线程写入,支持时间乱序数据写入(乱序数据建议控制在10%以内),也支持历史数据插入。

要提高写入效率,按时间戳顺序批量写入可以达到最佳写入速度。一条SQL语句一批写入的记录条数越多,写入效率就越高。但一条SQL语句长度不能超过1048576Byte (由参数maxSQLLength控制)。

全列写入速度会远快于指定列,因此建议尽可能采用全列写入方式,此时空列可以填入NULL。

写入的数据的时间戳,必须大于当前时间减去数据库配置参数keep的时间。如果keep配置为3650天,那么无法写入比3650天还老的数据。写入数据的时间戳也不能大于服务端当前时间days天数以后数据,即不允许写入未来超过days以远的数据。

对同一张表,如果新插入记录的时间戳已经存在,默认情况下(数据库选项 UPDATE 0时)新记录将被直接抛弃。如果在创建数据库时使用 UPDATE 1 选项,插入相同时间戳的新记录将覆盖原有记录。

写入数据时,时间戳可以填写now,代表taosc所在计算机的当前时间。如采用taosc或taosc-stmt接口连接TDengine,now取的是客户端计算机的时间;如采用RESTful接口,now取的是提供httpd服务的计算机的时间。

目前,TDengine不支持删除表中指定数据,可以删除整个表。

乱序写入需要严谨评估。TDengine允许少量乱序数据写入比如小于10%,且乱序时间戳范围不建议超过写入缓存存储的平均时长,这样写入速率受到的影响很小。但如果写入数据存在大量的乱序,将严重影响写入速度。

如何减少乱序?一般情形下,物联网数据都是顺序产生的。发生乱序大多出现在传输、消息队列缓存环节中,而且以消息队列较为严重。如果数据是从消息队列(如kafka)消费入库,减少乱序的最佳实践需确保每个采集量进入消息队列是按顺序进入指定的partition。详见这里

TDengine从企业版2.6.0.0开始支持delete语句,可删除指定的超级表、子表、普通表指定时间段的记录。

TDengine不支持truncate、update/upsert(只能设置数据库update参数)语句。

3.1 一条SQL语句拼接多表数据【在taos-sql接口中,建议使用insert语句,而非import语句来写入数据】
  • 向多个表插入单条记录【重要典型场景】

典型场景

SQL 复制代码
INSERT INTO 
d1001 VALUES ('2018-10-03 14:38:09.500', 10.3, 219, 0.31) 
d1002 VALUES ('2018-10-03 14:39:02.500', 12.3, 221, 0.31);

向多个表插入多条记录

典型场景

Plain%20Text 复制代码
INSERT INTO 
d1001 VALUES ('2018-10-03 14:38:09.500', 10.3, 219, 0.31) ('2018-10-03 14:39:01.500', 12.6, 218, 0.33) 
d1002 VALUES ('2018-10-03 14:39:02.500', 12.3, 221, 0.31) ('2018-10-03 14:39:03.500', 12.3, 221, 0.31) ;

同时向表d1001和d1002中分别插入多条记录。

3.2 自动建表同时插入
  • 同时向多个表按列插入多条记录,自动建表
Plain%20Text 复制代码
INSERT INTO 
tb1_name (tb1_field1_name, ...) [USING stb1_name TAGS (tag_value1, ...)] 
VALUES (field1_value1, ...) (field1_value2, ...) ...            
tb2_name (tb2_field1_name, ...) [USING stb2_name TAGS (tag_value2, ...)] 
VALUES (field1_value1, ...) (field1_value2, ...) ...;

以自动建表的方式,同时向表tb1_name和tb2_name中按列分别插入多条记录。

3.3 历史数据写入

使用INSERT命令,来写入历史数据,或从指定csv文件导入。

SQL 复制代码
INSERT INTO table_name USING stable_name TAGS(tag_value1, ...) VALUES(values1,...); 
INSERT INTO table_name FILE 'filename.csv';

【提示:不支持自动建表同时导入csv】

3.4 数据查询
查询语法
Plain%20Text 复制代码
SELECT select_expr [, select_expr ...]
        FROM {tb_name_list}
        [WHERE where_condition]
        [SESSION(ts_col, tol_val)]
        [STATE_WINDOW(col)]
        [INTERVAL(interval_val [, interval_offset]) [SLIDING sliding_val]]
        [FILL(fill_mod_and_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];
查询示例
Plain%20Text 复制代码
taos> SELECT d1001.* FROM d1001,d1003 WHERE d1001.ts = d1003.ts;
               ts            |       current        |   voltage   |        phase         |
======================================================================================
     2018-10-03 14:38:05.000 |             10.30000 |         219 |              0.31000 |
Query OK, 1 row(s) in set (0.020443s)

更多查询语法使用、查询技巧、查询函数,详见https://www.taosdata.com/cn/documentation/taos-sql#insert

关联查询
超级表关联查询 子表关联查询 普通表关联查询
连接条件必须包含时间戳列 (timestamp join condition missing) 可以在同一个超级表下关联,也可以跨超级表进行关联查询 只能使用timestamp进行关联,不能使用普通列关联(not support ordinary column join)
连接条件不能使用普通列 (not support ordinary column join) 只能使用timestamp作为关联条件 (not support ordinary column join) 可以最多进行10个表关联
如果超级表下面有多张子表的tag完全一样,不能使用关联查询(Duplicated join key) 可以最多进行10个表关联
每个超级表只支持一个tag用于连接(only support one join tag for each table)
可以最多进行10个表关联
边界限制
  • 各类名称命名规则

合法字符:英文字符、数字和下划线

允许英文字符或下划线开头,不允许以数字开头

不区分大小写

  • 数据库名最大长度为 32
  • 表名最大长度为 192,每行数据最大长度 16k 个字符(注意:数据行内每个 BINARY/NCHAR 类型的列还会额外占用 2 个字节的存储位置)
  • 列名最大长度为 64,最多允许 1024 列,最少需要 2 列,第一列必须是时间戳
  • 标签名最大长度为 64,最多允许 128 个,可以 1 个,一个表中标签值的总长度不超过 16k 个字符
  • SQL 语句最大长度 65480 个字符,但可通过系统配置参数 maxSQLLength 修改,最长可配置为 1M
  • SELECT 语句的查询结果,最多允许返回 1024 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错。
  • 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制
  • 支持对标签、TBNAME进行GROUP BY操作,也支持普通列进行GROUP BY,前提是:仅限一列且该列的唯一值小于10万个。
  • IS NOT NULL支持所有类型的列。不为空的表达式为 <>"",仅对非数值类型的列适用。
3.6 Java写入方式

taos-jdbcdriver 的实现包括 3 种形式: JDBC-JNI/taosc-stmt, JDBC-JNI/taosc 和 JDBC-RESTful(taos-jdbcdriver-2.0.18 开始支持 JDBC-RESTful)

taosc-stmt,参数绑定API,以二进制方式写入,通过免除SQL语法解析消耗而大幅提升了写入性能。taosc-stmt仅支持C/C++、Java连接器,其他语言暂不支持。

JDBC-JNI 通过调用客户端 libtaos.so(或 taos.dll )的本地方法实现。

JDBC-RESTful 则在内部封装了 RESTful 接口实现。

对比项 JDBC-JNI JDBC-restful
支持的操作系统 linux、windows 全平台
是否需要安装client 需要 不需要
server升级后是否需要升级client 需要 不需要
写入性能 JDBC-restful是JDBC-JNI的50%~90%
查询性能 JDBC-restful与JDBC-JNI没有差别
3.7 Java应用程序框架对比

JDBC已经能满足大部分用户最基本的需求,但是在使用JDBC时,必须自己来管理数据库资源如:获取PreparedStatement,设置SQL语句参数,关闭连接等步骤。

JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。

JdbcTemplate处理了资源的建立和释放。它帮助我们避免一些常见的错误。比如忘了总要关闭连接。它运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。

  • ORM普遍会拖慢Java写入TDengine性能
  • 高性能写入时,建议放弃ORM,直接调用JDBC实现TDengine的写入
  • ORM写入效率:JDBC Template 优于 Mybatis
3.8 Java连接池配置
  • 建议maxLifeTime设为0(TDengine连接器连接时长无限制,永久有效)
  • connectionTestQuery建议采用:select server_status()
  • 可设置固定大小的连接池,即最小、最大连接数相等
  • HikariCP配置示例:
Shell 复制代码
maximumPoolSize=100 (可调整)
minimumIdle=100 (可调整)
connectionTimeOut=30000
maxLifetime=0
idleTimeout=0
3.9 TDengine与jdbcdriver版本对应表

TDengine企业版与社区版均遵循以下对应关系:

客户端版本需要与服务端版本保持一致。

TDengine版本号分为四段,客户端与服务端需保证前三段相同,才能正常工作。例如2.1.3.0的服务端可以和2.1.3.2的客户端通信,但不能与2.1.2.0通信

四、性能调优

【提示:为方便区分,文中大写CACHE专指操作系统内存缓存区】

在性能调优前,需要理解TDengine与操作系统运行的基本原理:

  • TDengine对CPU的利用非常高,很可能在任务繁忙时短时占用所有CPU资源;
  • TDengine内存使用:目前可通过设置cache和blocks参数调整写入缓存区大小,不能限制读/查询缓存区大小;
  • TDengine调用操作系统函数进行数据写入,其性能很大程度依赖于操作系统的参数设置以及硬盘写入性能;
  • TDengine写入磁盘的内容主要包括两部分:WAL日志和压缩后的时序数据;
  • TDengine采用分布式架构实现高可用和水平扩展。数据写入时,首先写入vgroup的master节点,同时同步到slave;数据查询时,在各vnode查询得到一级聚合的数据集,最后汇聚到taosc所在节点;
  • 操作系统使用CACHE进行延迟写入,进而优化写入速度,写入的数据会先写入CACHE,然后由操作系统定期写入磁盘。

数据写入流程

  1. 数据进入到TDengine后首先会调用write()函数写入WAL日志(此时并非写入磁盘,只是写入操作系统CACHE),然后将数据放入TDengine中的写入缓存区中。当TDengine写入缓存区存储的数据超过总容量的1/3时,会触发fsync()进行落盘,同时生成新的WAL日志,数据完成落盘后,删除对应的WAL日志。
  • write()函数会将数据写入操作系统的CACHE中,不会马上落盘,只有当满足操作系统的条件【1】 后才会写入磁盘。
  • TDengine中的写入缓存区由参数cahce和blocks共同决定,写入缓存区cacheSize=cache*blocks,注意这部分内存仅用于数据写入,查询使用单独缓存区
  • fsync()函数会确保数据写入磁盘。
  • 当写入缓存中的数据小于minRows时,TDengine会将数据放入last文件,与下次的数据一起合并写入。
  • 当写入缓存中的数据大于maxRows时,TDengine会将数据进行分割存储。

与传统关系型数据库不同TDengine采用列式存储来保证压缩率和存储速度。因此数据在磁盘的存储结构为col1{row1,row2...rowN},col2{row1,row2...rowN}...colN{row1,row2...rowN}。

在TDengine集群中进行查询数据时,会先访问mnode获取表的基础信息,然后将分布在不同节点的数据在当前节点汇总后发送给客户端,当前节点会在内存中缓存所有查询数据。因此在进行规划时,需要将查询所占的内存也计算在内。

4.1.磁盘最慢写入速度 vs 模型校核

4.1.1.最慢写入速度

磁盘在大数据块连续写入时速度最快,小数据块随机写入时速度最慢。

对于TDengine而言,写入磁盘的数据中WAL日志占绝大部分(时序数据具有很高的压缩率),而WAL日志是通过write()进行写入的,操作系统CACHE大小、磁盘写入速度、操作系统参数直接影响其写入速度。

使用以下命令可对磁盘进行测试,测得随机写的速度。在进行性能估算时,建议以此速度为基准。

Shell 复制代码
fio -ioengine=sync -direct=0 -thread -rw=randwrite -filename=/taos/test -runtime=600 -numjobs=1 -filesize=20g -bsrange=4k-500k -loop 1000 -name="Test"
Shell 复制代码
-ioengine=sync fio存储引擎,sync为系统默认落盘模式。TDengine直接调用write()和fsync()函数进行落盘,不会使用其他引擎。
-direct=0 是否直接写入磁盘。1 直接写入,0 不直接写,使用OS_buffer。TDengine使用的落盘函数均使用OS buffer。
-rw=randwrite 使用随机写模式。TDengine落盘是会写WAL日志、data、last等多个文件,因此采用随机写更符合TDengine的实际写入。
-numjobs=1 并行进程数。在不使用异步io时,多进程不会对写入速度产生影响。
-filesize=20g 测试文件大小,如果设置了runtime,则在到期前反复写入。该值应接近待测磁盘可用存储空间大小,至少要远大于内存大小。
-bsrange=4k-500k 单次IO块大小,IO块大小随机在4k-500k内选择。
-runtime=600 测试时间单位秒(s)。测试时间越长越接近于真实环境,要求不低于10分钟。
-loop 1000 单次写入完成后循环1000次,受runtime控制。
-name="Test" 测试名称
4.1.2.模型校核

TDengine落盘的文件包括WAL日志和时序数据,由于TDengine进行压缩,TDengine的落盘时序数据文件会远小于WAL日志文件。

WAL日志由操作系统定时写入磁盘,写入的数据是连续的。TDengine时序数据落盘时会对数据进行拼接,在数据文件尾部进行追加,对于单个数据文件属于连续写入。

但实际部署中,一台服务器会存在多个vnode,对应多组数据文件。当数据文件较多时,写入行为呈现随机写入。在上一小节我们获得了随机写的速度,由此估算TDengine的数据落盘速度:

Shell 复制代码
rowSpeed=DiskIO/[rowSize*(1+comP)]
Shell 复制代码
rowSpeed #每秒写入记录数
DiskIO #上一小节获得的磁盘写入速度
rowSize #单条记录平均行长度
comP #数据压缩率

4.2.平衡写入缓存区大小与碎片化与OOM

4.2.1.写入缓存区

TDengine中的写入缓存区主要用于缓存要写入的数据,缓存区大小=cache x blocks,默认cache大小为16MB,不建议修改。在本章开头中提到如果落盘时写入缓存区中数据不足minRows时,数据会放入last文件中,在下次写入时进行合并。因此每次时序数据落盘时都会读取last文件,如果last文件中内容过多,必然会影响写入的性能。因此需要合理设置写入缓存区,尽量减少写入到last文件的数据。

写入缓存区大小的基本估算原则为:tableNums x minRows x 3,这只是一个最基础的大小,写入缓存区中还会存储表的元数据,因此在计算写入缓存区时需要再上浮一些。

那么写入缓存区是否越大越好呢?也不尽然,当写入缓存区中存储了大量数据,而系统突然掉电,这部分数据就会损失掉。因此设置写入缓存区时还要兼顾数据安全。

写入缓存区设置需要遵循以下两个基本原则:

  • 写入缓存区的最小值需要能包含所有表的minRows,太小会造成last文件过大影响写入效率;
  • 写入缓存区的最大值不能超过操作系统内存的40%,太大会造成系统内存不足引发OOM。
4.2.2.碎片化

碎片化是指数据存储在磁盘上时不连续、不规律、块过小等。造成碎片化的原因有多种,包括但不限于以下情况:

  • 同一个vnode中表的结构(行长度)相差悬殊、采集间隔差若干倍
  • 写入缓存大小受限,导致每表落盘记录数徘徊在minRows附近
  • 大量历史数据与实时数据同时写入
  • 频繁更新记录
  • 表删除

碎片化的危害:

  • 数据文件占用空间变大
  • 查询效率低下

如何处理

  • 将数据导出后重新导入
  • 碎片重整 compact
4.2.3.碎片重整 compact 【2.1.3.2以后版本支持该特性】

compact基本原理:数据库引擎根据用户要求,compact指定vgroup里面vnode的数据。它每次会读取一组数据文件,遍历所有块,将碎块合并到一起,写入一组新的数据文件,合并后每个块的记录数将大于3200条。

正常情况下,合并会比较快,会消耗一定的磁盘IO。但如果碎片化很严重,会拖慢写入的性能,极端情况会阻塞写入。

compact语法

Plain%20Text 复制代码
COMPACT VNODES IN (vgid1, vgid2, ...)

compact根据用户提供的vgroup列表,对所属的vnode进行重整。

建议先查看dnode/vgroups分布、数据文件大小,查看表、超级表的碎片化程度,规划重整策略:

  • 查询、写入请求低谷期实施
  • 从单一vgroup开始
  • 同一批处理的vnodes尽可能分布在不同的dnode上
  • 小文件优先处理

首次进行碎片重整耗时较长,之后再进行重整操作仅处理增量部分,时间会相应缩短。

4.2.4.OOM

OOM是操作系统的保护机制,当操作系统内存(包括SWAP)不足时,会杀掉某些进程,从而保证操作系统的稳定运行。

内存不足判断依据

通常内存不足包含两方面,一是剩余内存小于vm.min_free_kbytes;二是程序请求的内存大于剩余内存。还有一种情况是程序占用了特殊的内存地址。

OOM​ kill 进程顺序

先杀引起oom的,然后杀oom分数高的。影响评分的因素包括占用内存大小和程序优先级【2】。

预防OOM措施

造成OOM的原因不只是某个程序内存占用过多,还有部分责任是操作系统的过度分配(over-commit memory),由以下参数控制:

Shell 复制代码
vm.overcommit_memory = 0
vm.overcommit_ratio = 50

但是不建议修改以上参数。

要防止OOM,需要在项目建设之初合理规划内存,并合理设置SWAP【3】。

4.3.如何查看碎片化程度 _block_dist【2.0.20.7以后版本支持该特性】

语法:

SQL 复制代码
SELECT _BLOCK_DIST() FROM stable_name \G;

输出结果:

Shell 复制代码
block_dist: summary: 
//数据块中存储数据分布
5th=[216], 10th=[216], 20th=[216], 30th=[216], 40th=[232], 50th=[232] 60th=[232], 70th=[232], 80th=[248], 90th=[248], 95th=[248], 99th=[248]
//数据块中存储数据条数汇总
Min=[210(Rows)] Max=[250(Rows)] Avg=[231(Rows)] Stddev=[11.58]  
//总数据条数
Rows=[16211], 
//总数据块数
Blocks=[70], 
//总数据大小
Size=[1441.520(Kb)] 
//压缩率
Comp=[0.83] 
//驻留内存中的数据条数
RowsInMem=[0]

解释:5th=[216] 表示5%的blocks的记录数小于216条,Blocks=[70] 表示总数据块有70个,Comp=[0.83] 表示压缩落盘的数据大小/原始数据大小的比率

数据块中条数分布的越均匀,查询效率越高。


【1】.操作系统CACHE中数据写入磁盘受以及几个参数控制

Shell 复制代码
vm.dirty_background_ratio = 10  ##CACHE数据超过该值会启动异步写磁盘,此时CACHE仍可写入数据。
vm.dirty_ratio = 40   ##CACHE数据超过该值会触发同步写磁盘,写入CACHE被阻塞
vm.dirty_expire_centisecs = 3000   ##CAHCE中数据过期时间 30s
vm.dirty_writeback_centisecs = 500  ##每隔5s将CACHE中过期数据异步写入磁盘

【2】.OOM启动后会首先杀掉内存暴增的程序,然后杀掉oom分数高的。oom分数查看

Shell 复制代码
/proc/PID/oom_score

为防止程序被oom杀掉,可以手动调整oom评分,omm_adj取值范围为【-17,15】,默认0,值越小优先级越高。当设置为-17时,在该程序上oom失效。

Shell 复制代码
/proc/PID/oom_adj

【3】.Redhat官方给出SWAP设置建议:对于物理内存大于8GB的环境,SWAP建议至少4GB。操作系统会将物理内存中数据转储到SWAP,从而延缓OOM。

五、Grafana

TDengine提供了Grafana的数据源插件和仪表盘插件,支持 7 以上版本,为保证更好的兼容效果,推荐使用 Grafana 7.5.x 版本。

【TDengine 2.1.5.0以后版本支持数字运算和时间对齐(Timeshift)】

5.1.DataSource

TDengine的DataSource支持Grafana 7 以上的版本。DataSource使用RESTful接口查询,因此需要添加RESTful地址,默认端口6041。

DataSource插件安装

a.复制DataSource插件到Grafana插件目录:

Shell 复制代码
cp -rf /usr/local/taos/connector/grafanaplugin /var/lib/grafana/plugins/tdengine

b.重启Grafana

Shell 复制代码
systemctl restart grafana-server

c.在Grafana数据源配置界面搜索TDengine,进行添加。

d.注意事项

  • Grafana 7.x /8.x 添加时会提示 Unsigned external plugin,请忽略。
  • Grafana 8.x 需要在grafana.ini 添加 allow_loading_unsigned_plugins = taosdata-tdengine-datasource 以支持外部插件。

5.2.DashBoard

DashBoard插件提供了TDenging相关指标的综合展示图表,支持Grafana 7 以上版本。

DashBoard插件安装

插件所在位置:

Shell 复制代码
/usr/local/taos/connector/grafanaplugin/dashboard/tdengine-grafana.json

在Grafana的仪表盘配置界面选择上传,将上述文件导入。该插件默认选择名称为TDengine的数据源,如选取其他数据源需要在图表界面进行修改。

TDengine会将监控信息写入log数据库,采集间隔由monitorInterval 参数控制,默认30s,如需要更小的采样数据,需要修改数据库参数。Grafana可以通过查询log库信息来展示TDengine状态。log库中超级表dn结构如下:

SQL 复制代码
Field              |         Type         |   Length    |   Note   |
=================================================================================
 ts                             | TIMESTAMP            |           8 |          |
 cpu_taosd                      | FLOAT                |           4 |          |
 cpu_system                     | FLOAT                |           4 |          |
 cpu_cores                      | INT                  |           4 |          |
 mem_taosd                      | FLOAT                |           4 |          |
 mem_system                     | FLOAT                |           4 |          |
 mem_total                      | INT                  |           4 |          |
 disk_used                      | FLOAT                |           4 |          |
 disk_total                     | INT                  |           4 |          |
 band_speed                     | FLOAT                |           4 |          |
 io_read                        | FLOAT                |           4 |          |
 io_write                       | FLOAT                |           4 |          |
 req_http                       | INT                  |           4 |          |
 req_select                     | INT                  |           4 |          |
 req_insert                     | INT                  |           4 |          |
 dnodeid                        | INT                  |           4 | TAG      |
 fqdn                           | BINARY               |         128 | TAG      |

5.3.数字运算与Timeshift

【TDengine 2.1.5.0以后版本支持数字运算和时间对齐(Timeshift)】

5.3.1.数字运算

TDengine的Grafana插件支持对数据库存储的数值以及函数计算值进行基础的数字运算。

支持的函数与计算式见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math

示例:显示taosd内存占总内存使用率

SQL 复制代码
select avg(mem_taosd)*100/avg(mem_total) from log.dn where ts>$from and ts<$to interval($interval)
5.3.2.Timeshift

Timeshift 支持在同一张图表中显示将不同时间点的数据进行叠加显示,该功能主要用于数据对比。

TDengine的Timeshift支持按秒、分钟、小时、天、星期、月为单位对于数据进行迁移显示。

示例:显示当前与前一天taosd内存使用。设置Timeshift=1, Unit=days。

5.4常见问题
5.4.1.avg_disk_used 无法显示

【问题已在2.1.6.0修复】

手动修复方法:

将原查询语句

SQL 复制代码
select avg(disk_used)  disk_used from log.dn where ts >= $from and ts < $to interval(1s) group by ipaddr

修改为:

SQL 复制代码
select avg(disk_used)  disk_used from log.dn where ts >= $from and ts < $to interval(1s) group by fqdn

对于TDengine集群监控,建议在查询语句后添加 group by fqdn。

访问官网

更多内容欢迎访问 TDengine 官网

相关推荐
bigcarp14 分钟前
理解langchain langgraph 官方文档示例代码中的MemorySaver
java·前端·langchain
奥顺互联V20 分钟前
泛目录程序:无需数据库的高效站群解决方案
数据库·搜索引擎·php
17´34 分钟前
Qt从入门到入土(十) -数据库操作--SQLITE
数据库·c++·qt·sqlite
橘猫云计算机设计1 小时前
基于jspm校园安全管理系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·安全·毕业设计
幽络源小助理1 小时前
SpringBoot学生宿舍管理系统的设计与开发
java·spring boot·后端·学生宿舍管理
猿java1 小时前
源码分析:Spring IOC容器初始化过程
java·后端·spring
ClouGence1 小时前
时序数据库 TDengine 到 MySQL 数据迁移同步
mysql·时序数据库·tdengine
阿拉保1 小时前
C++复试笔记(四)
java·c++·笔记
多敲代码防脱发1 小时前
数据库MySQL原理(相关程序)
数据库·mysql
Future_yzx1 小时前
分布式存储学习——HBase表结构设计
数据库·oracle