[TD-4181] <docs>: update Architecture related doc.

This commit is contained in:
Elias Soong 2021-08-17 18:27:19 +08:00
parent 356865a9fd
commit 25d2e2e903
2 changed files with 88 additions and 58 deletions

View File

@ -6,6 +6,8 @@
在典型的物联网、车联网、运维监测场景中,往往有多种不同类型的数据采集设备,采集一个到多个不同的物理量。而同一种采集设备类型,往往又有多个具体的采集设备分布在不同的地点。大数据处理系统就是要将各种采集的数据汇总,然后进行计算和分析。对于同一类设备,其采集的数据都是很规则的。以智能电表为例,假设每个智能电表采集电流、电压、相位三个量,其采集的数据类似如下的表格:
<a class="anchor" id="model_table1"></a>
<figure><table>
<thead><tr>
<th style="text-align:center;">设备ID</th>
@ -162,7 +164,7 @@ TDengine 分布式架构的逻辑结构图如下:
**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机可以是安装有OS的物理机、虚拟机或Docker容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯如果不了解FQDN请看博文[《一篇文章说清楚TDengine的FQDN》](https://www.taosdata.com/blog/2020/09/11/1824.html)。
**数据节点(dnode):** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例一个工作的系统必须有至少一个数据节点。dnode包含零到多个逻辑的虚拟节点(VNODE),零或者至多一个逻辑的管理节点(mnode)。dnode在系统中的唯一标识由实例的End Point (EP )决定。EP是dnode所在物理节点的FQDN (Fully Qualified Domain Name)和系统所配置的网络端口号(Port)的组合。通过配置不同的端口,一个物理节点(一台物理机、虚拟机或容器)可以运行多个实例,或有多个数据节点。
**数据节点(dnode):** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例一个工作的系统必须有至少一个数据节点。dnode包含零到多个逻辑的虚拟节点(vnode),零或者至多一个逻辑的管理节点(mnode)。dnode在系统中的唯一标识由实例的End Point (EP)决定。EP是dnode所在物理节点的FQDN (Fully Qualified Domain Name)和系统所配置的网络端口号(Port)的组合。通过配置不同的端口,一个物理节点(一台物理机、虚拟机或容器)可以运行多个实例,或有多个数据节点。
**虚拟节点(vnode)**: 为更好的支持数据分片、负载均衡,防止数据过热或倾斜,数据节点被虚拟化成多个虚拟节点(vnode图中V2, V3, V4等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个DB但一个DB可以有多个 vnode。一个 vnode 除存储的时序数据外也保存有所包含的表的schema、标签值等。一个虚拟节点由所属的数据节点的EP以及所属的VGroup ID在系统内唯一标识由管理节点创建并管理。
@ -176,23 +178,39 @@ TDengine 分布式架构的逻辑结构图如下:
**通讯方式:**TDengine系统的各个数据节点之间以及应用驱动与各数据节点之间的通讯是通过TCP/UDP进行的。因为考虑到物联网场景数据写入的包一般不大因此TDengine 除采用TCP做传输之外还采用UDP方式因为UDP 更加高效而且不受连接数的限制。TDengine实现了自己的超时、重传、确认等机制以确保UDP的可靠传输。对于数据量不到15K的数据包采取UDP的方式进行传输超过15K的或者是查询类的操作自动采取TCP的方式进行传输。同时TDengine根据配置和数据包会自动对数据进行压缩/解压缩,数字签名/认证等处理。对于数据节点之间的数据复制只采用TCP方式进行数据传输。
**FQDN配置**一个数据节点有一个或多个FQDN可以在系统配置文件taos.cfg通过参数fqdn"进行指定如果没有指定系统将自动获取计算机的hostname作为其FQDN。如果节点没有配置FQDN可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP因为IP地址可变一旦变化将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN需要保证DNS服务正常工作或者在节点以及应用所在的节点配置好hosts文件。另外这个参数值的长度需要控制在 96 个字符以内。
**FQDN配置**一个数据节点有一个或多个FQDN可以在系统配置文件taos.cfg通过参数"fqdn"进行指定如果没有指定系统将自动获取计算机的hostname作为其FQDN。如果节点没有配置FQDN可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP因为IP地址可变一旦变化将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN需要保证DNS服务正常工作或者在节点以及应用所在的节点配置好hosts文件。另外这个参数值的长度需要控制在 96 个字符以内。
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定对集群内部通讯的端口是serverPort+5。集群内数据节点之间的数据复制操作还占有一个TCP端口是serverPort+10. 为支持多线程高效的处理UDP数据每个对内和对外的UDP连接都需要占用5个连续的端口。因此一个数据节点总的端口范围为serverPort到serverPort + 10总共11个TCP/UDP端口。另外还可能有 RESTful、Arbitrator 所使用的端口,那样的话就一共是 13 个。使用时需要确保防火墙将这些端口打开以备使用。每个数据节点可以配置不同的serverPort。详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port)
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定对集群内部通讯的端口是serverPort+5。为支持多线程高效的处理UDP数据每个对内和对外的UDP连接都需要占用5个连续的端口。
**集群对外连接:** TDengine集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可连接需要提供的网络参数是一数据节点的End Point(FQDN加配置的端口号。通过命令行CLI启动应用taos时可以通过选项-h来指定数据节点的FQDN, -P来指定其配置的端口号如果端口不配置将采用TDengine的系统配置参数serverPort
集群内数据节点之间的数据复制操作占用一个TCP端口是serverPort+10
**集群内部通讯**: 各个数据节点之间通过TCP/UDP进行连接。一个数据节点启动时将获取mnode所在的dnode的EP信息然后与系统中的mnode建立起连接交换信息。获取mnode的EP信息有三步1检查mnodeEpSet文件是否存在如果不存在或不能正常打开获得mnode EP信息进入第二步2检查系统配置文件taos.cfg, 获取节点配置参数firstEp, secondEp这两个参数指定的节点可以是不带mnode的普通节点这样的话节点被连接时会尝试重定向到mnode节点如果不存在或者taos.cfg里没有这两个配置参数或无效进入第三步3将自己的EP设为mnode EP, 并独立运行起来。获取mnode EP列表后数据节点发起连接如果连接成功则成功加入进工作的集群如果不成功则尝试mnode EP列表中的下一个。如果都尝试了但连接都仍然失败则休眠几秒后再进行尝试
集群数据节点对外提供RESTful服务占用一个TCP端口是serverPort+11
**MNODE的选择:** TDengine逻辑上有管理节点但没有单独的执行代码服务器侧只有一套执行代码taosd。那么哪个数据节点会是管理节点呢这是系统自动决定的无需任何人工干预。原则如下一个数据节点启动时会检查自己的End Point, 并与获取的mnode EP List进行比对如果在其中该数据节点认为自己应该启动mnode模块成为mnode。如果自己的EP不在mnode EP List里则不启动mnode模块。在系统的运行过程中由于负载均衡、宕机等原因mnode有可能迁移至新的dnode但一切都是透明的无需人工干预配置参数的修改是mnode自己根据资源做出的决定
集群内数据节点与Arbitrator节点之间通讯占用一个TCP端口是serverPort+12
**新数据节点的加入**系统有了一个数据节点后就已经成为一个工作的系统。添加新的节点进集群时有两个步骤第一步使用TDengine CLI连接到现有工作的数据节点然后用命令”create dnode"将新的数据节点的End Point添加进去; 第二步在新的数据节点的系统配置参数文件taos.cfg里将firstEp, secondEp参数设置为现有集群中任意两个数据节点的EP即可。具体添加的详细步骤请见详细的用户手册。这样就把集群一步一步的建立起来。
因此一个数据节点总的端口范围为serverPort到serverPort+12总共13个TCP/UDP端口。使用时需要确保防火墙将这些端口打开。每个数据节点可以配置不同的serverPort。详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port)
**重定向**无论是dnode还是taosc最先都是要发起与mnode的连接但mnode是系统自动创建并维护的因此对于用户来说并不知道哪个dnode在运行mnode。TDengine只要求向系统中任何一个工作的dnode发起连接即可。因为任何一个正在运行的dnode都维护有目前运行的mnode EP List。当收到一个来自新启动的dnode或taosc的连接请求如果自己不是mnode则将mnode EP List回复给对方taosc或新启动的dnode收到这个list, 就重新尝试建立连接。当mnode EP List发生改变通过节点之间的消息交互各个数据节点就很快获取最新列表并通知taosc。
**集群对外连接:**TDengine集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可连接需要提供的网络参数是一数据节点的End Point(FQDN加配置的端口号。通过命令行CLI启动应用taos时可以通过选项-h来指定数据节点的FQDN, -P来指定其配置的端口号如果端口不配置将采用TDengine的系统配置参数serverPort。
**集群内部通讯:**各个数据节点之间通过TCP/UDP进行连接。一个数据节点启动时将获取mnode所在的dnode的EP信息然后与系统中的mnode建立起连接交换信息。获取mnode的EP信息有三步
1检查mnodeEpSet.json文件是否存在如果不存在或不能正常打开获得mnode EP信息进入第二步
2检查系统配置文件taos.cfg获取节点配置参数firstEp、secondEp这两个参数指定的节点可以是不带mnode的普通节点这样的话节点被连接时会尝试重定向到mnode节点如果不存在或者taos.cfg里没有这两个配置参数或无效进入第三步
3将自己的EP设为mnode EP并独立运行起来。
获取mnode EP列表后数据节点发起连接如果连接成功则成功加入进工作的集群如果不成功则尝试mnode EP列表中的下一个。如果都尝试了但连接都仍然失败则休眠几秒后再进行尝试。
**MNODE的选择**TDengine逻辑上有管理节点但没有单独的执行代码服务器侧只有一套执行代码taosd。那么哪个数据节点会是管理节点呢这是系统自动决定的无需任何人工干预。原则如下一个数据节点启动时会检查自己的End Point, 并与获取的mnode EP List进行比对如果在其中该数据节点认为自己应该启动mnode模块成为mnode。如果自己的EP不在mnode EP List里则不启动mnode模块。在系统的运行过程中由于负载均衡、宕机等原因mnode有可能迁移至新的dnode但一切都是透明的无需人工干预配置参数的修改是mnode自己根据资源做出的决定。
**新数据节点的加入:**系统有了一个数据节点后就已经成为一个工作的系统。添加新的节点进集群时有两个步骤第一步使用TDengine CLI连接到现有工作的数据节点然后用命令”create dnode"将新的数据节点的End Point添加进去; 第二步在新的数据节点的系统配置参数文件taos.cfg里将firstEp, secondEp参数设置为现有集群中任意两个数据节点的EP即可。具体添加的详细步骤请见详细的用户手册。这样就把集群一步一步的建立起来。
**重定向:**无论是dnode还是taosc最先都是要发起与mnode的连接但mnode是系统自动创建并维护的因此对于用户来说并不知道哪个dnode在运行mnode。TDengine只要求向系统中任何一个工作的dnode发起连接即可。因为任何一个正在运行的dnode都维护有目前运行的mnode EP List。当收到一个来自新启动的dnode或taosc的连接请求如果自己不是mnode则将mnode EP List回复给对方taosc或新启动的dnode收到这个list, 就重新尝试建立连接。当mnode EP List发生改变通过节点之间的消息交互各个数据节点就很快获取最新列表并通知taosc。
### 一个典型的消息流程
为解释vnode, mnode, taosc和应用之间的关系以及各自扮演的角色下面对写入数据这个典型操作的流程进行剖析。
为解释vnode、mnode、taosc和应用之间的关系以及各自扮演的角色下面对写入数据这个典型操作的流程进行剖析。
![TDengine典型的操作流程](page://images/architecture/message.png)
<center> 图 2 TDengine典型的操作流程 </center>
@ -249,7 +267,7 @@ TDengine除vnode分片之外还对时序数据按照时间段进行分区。
每个dnode都定时向 mnode(虚拟管理节点)报告其状态包括硬盘空间、内存大小、CPU、网络、虚拟节点个数等因此mnode了解整个集群的状态。基于整体状态当mnode发现某个dnode负载过重它会将dnode上的一个或多个vnode挪到其他dnode。在挪动过程中对外服务继续进行数据插入、查询和计算操作都不受影响。
如果mnode一段时间没有收到dnode的状态报告mnode会认为这个dnode已经离线。如果离线时间超过一定时长时长由配置参数offlineThreshold决定该dnode将被mnode强制剔除出集群。该dnode上的vnodes如果副本数大于系统将自动在其他dnode上创建新的副本以保证数据的副本数。如果该dnode上还有mnode, 而且mnode的副本数大于系统也将自动在其他dnode上创建新的mnode, 以保证mnode的副本数。
如果mnode一段时间没有收到dnode的状态报告mnode会认为这个dnode已经离线。如果离线时间超过一定时长时长由配置参数offlineThreshold决定该dnode将被mnode强制剔除出集群。该dnode上的vnodes如果副本数大于1系统将自动在其他dnode上创建新的副本以保证数据的副本数。如果该dnode上还有mnode, 而且mnode的副本数大于1系统也将自动在其他dnode上创建新的mnode, 以保证mnode的副本数。
当新的数据节点被添加进集群,因为新的计算和存储被添加进来,系统也将自动启动负载均衡流程。
@ -258,55 +276,52 @@ TDengine除vnode分片之外还对时序数据按照时间段进行分区。
## <a class="anchor" id="replication"></a>数据写入与复制流程
如果一个数据库有N个副本那一个虚拟节点组就有N个虚拟节点但是只有一个是Master其他都是slave。当应用将新的记录写入系统时只有Master vnode能接受写的请求。如果slave vnode收到写的请求系统将通知taosc需要重新定向。
如果一个数据库有N个副本那一个虚拟节点组就有N个虚拟节点但是只有一个是master其他都是slave。当应用将新的记录写入系统时只有master vnode能接受写的请求。如果slave vnode收到写的请求系统将通知taosc需要重新定向。
### Master vnode写入流程
### Master Vnode写入流程
Master Vnode遵循下面的写入流程
![TDengine Master写入流程](page://images/architecture/write_master.png)
<center> 图 3 TDengine Master写入流程 </center>
1. Master vnode收到应用的数据插入请求验证OK进入下一步
1. master vnode收到应用的数据插入请求验证OK进入下一步
2. 如果系统配置参数walLevel大于0vnode将把该请求的原始数据包写入数据库日志文件WAL。如果walLevel设置为2而且fsync设置为0TDengine还将WAL数据立即落盘以保证即使宕机也能从数据库日志文件中恢复数据避免数据的丢失
3. 如果有多个副本vnode将把数据包转发给同一虚拟节点组内slave vnodes, 该转发包带有数据的版本号(version)
3. 如果有多个副本vnode将把数据包转发给同一虚拟节点组内slave vnodes, 该转发包带有数据的版本号(version)
4. 写入内存并将记录加入到skip list
5. Master vnode返回确认信息给应用表示写入成功。
5. master vnode返回确认信息给应用表示写入成功。
6. 如果第234步中任何一步失败将直接返回错误给应用。
### Slave vnode写入流程
### Slave Vnode写入流程
对于slave vnode, 写入流程是:
![TDengine Slave写入流程](page://images/architecture/write_slave.png)
<center> 图 4 TDengine Slave写入流程 </center>
1. Slave vnode收到Master vnode转发了的数据插入请求。
1. slave vnode收到Master vnode转发了的数据插入请求。检查last version是否与master一致如果一致进入下一步。如果不一致需要进入同步状态。
2. 如果系统配置参数walLevel大于0vnode将把该请求的原始数据包写入数据库日志文件WAL。如果walLevel设置为2而且fsync设置为0TDengine还将WAL数据立即落盘以保证即使宕机也能从数据库日志文件中恢复数据避免数据的丢失
3. 写入内存更新内存中的skip list。
Master vnode相比slave vnode不存在转发环节也不存在回复确认环节少了两步。但写内存与WAL是完全一样的。
master vnode相比slave vnode不存在转发环节也不存在回复确认环节少了两步。但写内存与WAL是完全一样的。
### 异地容灾、IDC迁移
从上述Master和Slave流程可以看出TDengine采用的是异步复制的方式进行数据同步。这种方式能够大幅提高写入性能网络延时对写入速度不会有大的影响。通过配置每个物理节点的IDC和机架号可以保证对于一个虚拟节点组虚拟节点由来自不同IDC、不同机架的物理节点组成从而实现异地容灾。因此TDengine原生支持异地容灾无需再使用其他工具。
从上述master和slave流程可以看出TDengine采用的是异步复制的方式进行数据同步。这种方式能够大幅提高写入性能网络延时对写入速度不会有大的影响。通过配置每个物理节点的IDC和机架号可以保证对于一个虚拟节点组虚拟节点由来自不同IDC、不同机架的物理节点组成从而实现异地容灾。因此TDengine原生支持异地容灾无需再使用其他工具。
一方面TDengine支持动态修改副本数一旦副本数增加新加入的虚拟节点将立即进入数据同步流程同步结束后新加入的虚拟节点即可提供服务。而在同步过程中master以及其他已经同步的虚拟节点都可以对外提供服务。利用这一特性TDengine可以实现无服务中断的IDC机房迁移。只需要将新IDC的物理节点加入现有集群等数据同步完成后再将老的IDC的物理节点从集群中剔除即可。
另一方面TDengine支持动态修改副本数一旦副本数增加新加入的虚拟节点将立即进入数据同步流程同步结束后新加入的虚拟节点即可提供服务。而在同步过程中master以及其他已经同步的虚拟节点都可以对外提供服务。利用这一特性TDengine可以实现无服务中断的IDC机房迁移。只需要将新IDC的物理节点加入现有集群等数据同步完成后再将老的IDC的物理节点从集群中剔除即可。
但是,这种异步复制的方式,存在极小的时间窗口,丢失写入的数据。具体场景如下:
1. Master vnode完成了它的5步操作已经给APP确认写入成功然后宕机
2. Slave vnode收到写入请求后在第2步写入日志之前处理失败
3. Slave vnode将成为新的master, 从而丢失了一条记录
1. master vnode完成了它的5步操作已经给APP确认写入成功然后宕机
2. slave vnode收到写入请求后在第2步写入日志之前处理失败
3. slave vnode将成为新的master从而丢失了一条记录
理论上只要是异步复制就无法保证100%不丢失。但是这个窗口极小mater与slave要同时发生故障而且发生在刚给应用确认写入成功之后。
异地容灾、IDC无中断迁移仅仅企业版支持。
**提示:该功能暂未提供**
理论上只要是异步复制就无法保证100%不丢失。但是这个窗口极小master与slave要同时发生故障而且发生在刚给应用确认写入成功之后。
### 主从选择
Vnode会保持一个数据版本号(Version),对内存数据进行持久化存储时,对该版本号也进行持久化存储。每个数据更新操作,无论是采集的时序数据还是元数据,这个版本号将增
Vnode会保持一个数据版本号(version),对内存数据进行持久化存储时,对该版本号也进行持久化存储。每个数据更新操作,无论是采集的时序数据还是元数据,这个版本号将增加1
一个vnode启动时角色(master、slave) 是不定的数据是处于未同步状态它需要与虚拟节点组内其他节点建立TCP连接并互相交换status其中包括version和自己的角色。通过status的交换系统进入选主流程规则如下
@ -319,7 +334,7 @@ Vnode会保持一个数据版本号(Version),对内存数据进行持久化存
### 同步复制
对于数据一致性要求更高的场景异步数据复制无法满足要求因为有极小的概率丢失数据因此TDengine提供同步复制的机制供用户选择。在创建数据库时除指定副本数replica之外用户还需要指定新的参数quorum。如果quorum大于它表示每次Master转发给副本时需要等待quorum-1个回复确认才能通知应用数据在slave已经写入成功。如果在一定的时间内得不到quorum-1个回复确认master vnode将返回错误给应用。
对于数据一致性要求更高的场景异步数据复制无法满足要求因为有极小的概率丢失数据因此TDengine提供同步复制的机制供用户选择。在创建数据库时除指定副本数replica之外用户还需要指定新的参数quorum。如果quorum大于1它表示每次master转发给副本时需要等待quorum-1个回复确认才能通知应用数据在slave已经写入成功。如果在一定的时间内得不到quorum-1个回复确认master vnode将返回错误给应用。
采用同步复制系统的性能会有所下降而且latency会增加。因为元数据要强一致mnode之间的数据同步缺省就是采用的同步复制。
@ -329,19 +344,19 @@ Vnode会保持一个数据版本号(Version),对内存数据进行持久化存
TDengine采用时间驱动缓存管理策略First-In-First-OutFIFO又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式Least-Recent-UsedLRU直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候将最早的数据批量写入磁盘。一般意义上来说对于物联网数据的使用用户最为关心的是刚产生的数据即当前状态。TDengine充分利用这一特性将最近到达的当前状态数据保存在缓存中。
TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中可以更加快速地响应用户针对最近一条或一批数据的查询分析整体上提供更快的数据库查询响应能力。从这个意义上来说**可通过设置合适的配置参数将TDengine作为数据缓存来使用而不需要再部署Redis或其他额外的缓存系统**可有效地简化系统架构降低运维的成本。需要注意的是TDengine重启以后系统的缓存将被清空之前缓存的数据均会被批量写入磁盘缓存的数据将不会像专门的Key-value缓存系统再将之前缓存的数据重新加载到缓存中。
TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中可以更加快速地响应用户针对最近一条或一批数据的查询分析整体上提供更快的数据库查询响应能力。从这个意义上来说**可通过设置合适的配置参数将TDengine作为数据缓存来使用而不需要再部署Redis或其他额外的缓存系统**可有效地简化系统架构降低运维的成本。需要注意的是TDengine重启以后系统的缓存将被清空之前缓存的数据均会被批量写入磁盘缓存的数据将不会像专门的key-value缓存系统再将之前缓存的数据重新加载到缓存中。
每个vnode有自己独立的内存而且由多个固定大小的内存块组成不同vnode之间完全隔离。数据写入时类似于日志的写法数据被顺序追加写入内存但每个vnode维护有自己的skip list便于迅速查找。当三分之一以上的内存块写满时启动落盘操作而且后续写的操作在新的内存块进行。这样一个vnode里有三分之一内存块是保留有最近的数据的以达到缓存、快速查找的目的。一个vnode的内存块的个数由配置参数blocks决定内存块的大小由配置参数cache决定。
### 持久化存储
TDengine采用数据驱动的方式让缓存中的数据写入硬盘进行持久化存储。当vnode中缓存的数据达到一定规模时为了不阻塞后续数据的写入TDengine也会拉起落盘线程将缓存的数据写入持久化存储。TDengine在数据落盘时会打开新的数据库日志文件在落盘成功后则会删除老的数据库日志文件避免日志文件无限制增长。
TDengine采用数据驱动的方式让缓存中的数据写入硬盘进行持久化存储。当vnode中缓存的数据达到一定规模时为了不阻塞后续数据的写入TDengine也会拉起落盘线程将缓存的数据写入持久化存储。TDengine在数据落盘时会打开新的数据库日志文件在落盘成功后则会删除老的数据库日志文件避免日志文件无限制增长。
为充分利用时序数据特点TDengine将一个vnode保存在持久化存储的数据切分成多个文件每个文件只保存固定天数的数据这个天数由系统配置参数days决定。切分成多个文件后给定查询的起止日期无需任何索引就可以立即定位需要打开哪些数据文件大大加快读取速度。
对于采集的数据一般有保留时长这个时长由系统配置参数keep决定。超过这个设置天数的数据文件将被系统自动删除释放存储空间。
给定days与keep两个参数一个典型工作状态的vnode中总的数据文件数为`向上取整(keep/days)+1`个。总的数据文件个数不宜过大也不宜过小。10到100以内合适。基于这个原则可以设置合理的days。 目前的版本参数keep可以修改但对于参数days设置后,不可修改。
给定days与keep两个参数一个典型工作状态的vnode中总的数据文件数为`向上取整(keep/days)+1`个。总的数据文件个数不宜过大也不宜过小。10到100以内合适。基于这个原则可以设置合理的days。目前的版本参数keep可以修改但对于参数days设置后,不可修改。
在每个数据文件里一张表的数据是一块一块存储的。一张表可以有一到多个数据文件块。在一个文件块里数据是列式存储的占用的是一片连续的存储空间这样大大提高读取速度。文件块的大小由系统参数maxRows每块最大记录条数决定缺省值为4096。这个值不宜过大也不宜过小。过大定位具体时间段的数据的搜索时间会变长影响读取速度过小数据块的索引太大压缩效率偏低也影响读取速度。
@ -351,32 +366,47 @@ TDengine采用数据驱动的方式让缓存中的数据写入硬盘进行持久
### 多级存储
在默认配置下TDengine会将所有数据保存在/var/lib/taos目录下而且每个vnode的数据文件保存在该目录下的不同目录。为扩大存储空间尽量减少文件读取的瓶颈提高数据吞吐率 TDengine可通过配置系统参数dataDir让多个挂载的硬盘被系统同时使用。除此之外TDengine也提供了数据分级存储的功能即根据数据文件的新老程度存储在不同的存储介质上。比如最新的数据存储在SSD上超过一周的数据存储在本地硬盘上超过4周的数据存储在网络存储设备上这样来降低存储成本而又保证高效的访问数据。数据在不同存储介质上的移动是由系统自动完成的对应用是完全透明的。数据的分级存储也是通过系统参数dataDir来配置
说明:多级存储功能仅企业版支持,从 2.0.16.0 版本开始提供
dataDir的配置格式如下
```
dataDir data_path [tier_level]
```
其中data_path为挂载点的文件夹路径tier_level为介质存储等级。介质存储等级越高盛放数据文件越老。同一存储等级可挂载多个硬盘同一存储等级上的数据文件分布在该存储等级的所有硬盘上。TDengine最多支持3级存储所以tier_level的取值为0、1和2。在配置dataDir时必须存在且只有一个挂载路径不指定tier_level称之为特殊挂载盘路径。该挂载路径默认为0级存储介质且包含特殊文件链接不可被移除否则会对写入的数据产生毁灭性影响。
在默认配置下TDengine会将所有数据保存在/var/lib/taos目录下而且每个vnode的数据文件保存在该目录下的不同目录。为扩大存储空间尽量减少文件读取的瓶颈提高数据吞吐率 TDengine可通过配置系统参数dataDir让多个挂载的硬盘被系统同时使用。
假设一物理节点有六个可挂载的硬盘/mnt/disk1、/mnt/disk2、…、/mnt/disk6其中disk1和disk2需要被指定为0级存储介质disk3和disk4为1级存储介质 disk5和disk6为2级存储介质。disk1为特殊挂载盘则可在/etc/taos/taos.cfg中做如下配置
除此之外TDengine也提供了数据分级存储的功能将不同时间段的数据存储在挂载的不同介质上的目录里从而实现不同“热度”的数据存储在不同的存储介质上充分利用存储节约成本。比如最新采集的数据需要经常访问对硬盘的读取性能要求高那么用户可以配置将这些数据存储在SSD盘上。超过一定期限的数据查询需求量没有那么高那么可以存储在相对便宜的HDD盘上。
多级存储支持3级每级最多可配置16个挂载点。
TDengine多级存储配置方式如下在配置文件/etc/taos/taos.cfg中
```
dataDir /mnt/disk1/taos
dataDir /mnt/disk2/taos 0
dataDir /mnt/disk3/taos 1
dataDir /mnt/disk4/taos 1
dataDir /mnt/disk5/taos 2
dataDir /mnt/disk6/taos 2
dataDir [path] <level> <primary>
```
挂载的盘也可以是非本地的网络盘,只要系统能访问即可。
- path: 挂载点的文件夹路径
- level: 介质存储等级取值为012。
0级存储最新的数据1级存储次新的数据2级存储最老的数据省略默认为0。
各级存储之间的数据流向0级存储 -> 1级存储 -> 2级存储。
同一存储等级可挂载多个硬盘,同一存储等级上的数据文件分布在该存储等级的所有硬盘上。
需要说明的是,数据在不同级别的存储介质上的移动,是由系统自动完成的,用户无需干预。
- primary: 是否为主挂载点0或1省略默认为1。
注:多级存储功能仅企业版支持
在配置中只允许一个主挂载点的存在level=0, primary=0例如采用如下的配置方式
```
dataDir /mnt/data1 0 0
dataDir /mnt/data2 0 1
dataDir /mnt/data3 1 1
dataDir /mnt/data4 1 1
dataDir /mnt/data5 2 1
dataDir /mnt/data6 2 1
```
注意:
1. 多级存储不允许跨级配置合法的配置方案有仅0级仅0级+1级以及0级+1级+2级。而不允许只配置level=0和level=2而不配置level=1。
2. 禁止手动移除使用中的挂载盘,挂载盘目前不支持非本地的网络盘。
3. 多级存储目前不支持删除已经挂载的硬盘的功能。
## <a class="anchor" id="query"></a>数据查询
TDengine提供了多种多样针对表和超级表的查询处理功能除了常规的聚合查询之外还提供针对时序数据的窗口查询、统计聚合等功能。TDengine的查询处理需要客户端、vnode, mnode节点协同完成。
TDengine提供了多种多样针对表和超级表的查询处理功能除了常规的聚合查询之外还提供针对时序数据的窗口查询、统计聚合等功能。TDengine的查询处理需要客户端、vnodemnode节点协同完成。
### 单表查询
@ -388,31 +418,31 @@ SQL语句的解析和校验工作在客户端完成。解析SQL语句并生成
### 按时间轴聚合、降采样、插值
时序数据有别于普通数据的显著特征是每条记录均具有时间戳,因此针对具有时间戳数据在时间轴上进行聚合是不同于普通数据库的重要功能。从这点上来看,与流计算引擎的窗口查询有相似的地方。
时序数据有别于普通数据的显著特征是每条记录均具有时间戳,因此针对具有时间戳数据在时间轴上进行聚合是不同于普通数据库的重要功能。从这点上来看,与流计算引擎的窗口查询有相似的地方。
在TDengine中引入关键词interval来进行时间轴上固定长度时间窗口的切分并按照时间窗口对数据进行聚合对窗口范围内的数据按需进行聚合。例如
```mysql
select count(*) from d1001 interval(1h);
```sql
SELECT COUNT(*) FROM d1001 INTERVAL(1h);
```
针对d1001设备采集的数据按照1小时的时间窗口返回每小时存储的记录数量。
在需要连续获得查询结果的应用场景下如果给定的时间区间存在数据缺失会导致该区间数据结果也丢失。TDengine提供策略针对时间轴聚合计算的结果进行插值通过使用关键词Fill就能够对时间轴聚合结果进行插值。例如
```mysql
select count(*) from d1001 interval(1h) fill(prev);
在需要连续获得查询结果的应用场景下如果给定的时间区间存在数据缺失会导致该区间数据结果也丢失。TDengine提供策略针对时间轴聚合计算的结果进行插值通过使用关键词fill就能够对时间轴聚合结果进行插值。例如
```sql
SELECT COUNT(*) FROM d1001 WHERE ts >= '2017-7-14 00:00:00' AND ts < '2017-7-14 23:59:59' INTERVAL(1h) FILL(PREV);
```
针对d1001设备采集数据统计每小时记录数如果某一个小时不存在数据则返回之前一个小时的统计数据。TDengine提供前向插值(prev)、线性插值(linear)、NULL值填充(NULL)、特定值填充(value)。
### 多表聚合查询
TDengine对每个数据采集点单独建表但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作TDengine引入超级表STable的概念。超级表用来代表一特定类型的数据采集点它是包含多张表的表集合集合里每张表的模式schema完全一致但每张表都带有自己的静态标签标签可以多个可以随时增加、删除和修改。 应用可通过指定标签的过滤条件对一个STable下的全部或部分表进行聚合或统计操作这样大大简化应用的开发。其具体流程如下图所示
TDengine对每个数据采集点单独建表但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作TDengine引入超级表STable的概念。超级表用来代表一特定类型的数据采集点它是包含多张表的表集合集合里每张表的模式schema完全一致但每张表都带有自己的静态标签标签可以多个可以随时增加、删除和修改。应用可通过指定标签的过滤条件对一个STable下的全部或部分表进行聚合或统计操作这样大大简化应用的开发。其具体流程如下图所示
![多表聚合查询原理图](page://images/architecture/multi_tables.png)
<center> 图 5 多表聚合查询原理图 </center>
1. 应用将一个查询条件发往系统;
2. taosc将超级表的名字发往 Meta Node管理节点)
2. taosc将超级表的名字发往 meta node管理节点)
3. 管理节点将超级表所拥有的 vnode 列表发回 taosc
4. taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点
5. 每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合然后扫描存储的时序数据完成相应的聚合计算将结果返回给taosc

View File

@ -31,7 +31,7 @@ USE power;
## <a class="anchor" id="create-stable"></a>创建超级表
一个物联网系统往往存在多种类型的设备比如对于电网存在智能电表、变压器、母线、开关等等。为便于多表之间的聚合使用TDengine, 需要对每个类型的数据采集点创建一个超级表。以表1中的智能电表为例可以使用如下的SQL命令创建超级表
一个物联网系统往往存在多种类型的设备比如对于电网存在智能电表、变压器、母线、开关等等。为便于多表之间的聚合使用TDengine, 需要对每个类型的数据采集点创建一个超级表。以[表1](https://www.taosdata.com/cn/documentation/architecture#model_table1)中的智能电表为例可以使用如下的SQL命令创建超级表
```mysql
CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);
@ -47,7 +47,7 @@ CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAG
## <a class="anchor" id="create-table"></a>创建表
TDengine对每个数据采集点需要独立建表。与标准的关系型数据库一样一张表有表名Schema但除此之外还可以带有一到多个标签。创建时需要使用超级表做模板同时指定标签的具体值。以表1中的智能电表为例可以使用如下的SQL命令建表
TDengine对每个数据采集点需要独立建表。与标准的关系型数据库一样一张表有表名Schema但除此之外还可以带有一到多个标签。创建时需要使用超级表做模板同时指定标签的具体值。以[表1](https://www.taosdata.com/cn/documentation/architecture#model_table1)中的智能电表为例可以使用如下的SQL命令建表
```mysql
CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2);