homework-jianmu/2.0/documentation/webdocs/markdowndocs/Data model and architecture...

100 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据模型和设计
## 数据模型
### 物联网典型场景
在典型的物联网、车联网、运维监测场景中,往往有多种不同类型的数据采集设备,采集一个到多个不同的物理量。而同一种采集设备类型,往往又有多个具体的采集设备分布在不同的地点。大数据处理系统就是要将各种采集的数据汇总,然后进行计算和分析。对于同一类设备,其采集的数据类似如下的表格:
| Device ID | Time Stamp | Value 1 | Value 2 | Value 3 | Tag 1 | Tag 2 |
| :-------: | :-----------: | :-----: | :-----: | :-----: | :---: | :---: |
| D1001 | 1538548685000 | 10.3 | 219 | 0.31 | Red | Tesla |
| D1002 | 1538548684000 | 10.2 | 220 | 0.23 | Blue | BMW |
| D1003 | 1538548686500 | 11.5 | 221 | 0.35 | Black | Honda |
| D1004 | 1538548685500 | 13.4 | 223 | 0.29 | Red | Volvo |
| D1001 | 1538548695000 | 12.6 | 218 | 0.33 | Red | Tesla |
| D1004 | 1538548696600 | 11.8 | 221 | 0.28 | Black | Honda |
每一条记录都有设备ID时间戳采集的物理量还有与每个设备相关的静态标签。每个设备是受外界的触发或按照设定的周期采集数据。采集的数据点是时序的是一个数据流。
### 数据特征
除时序特征外,仔细研究发现,物联网、车联网、运维监测类数据还具有很多其他明显的特征。
1. 数据是结构化的;
2. 数据极少有更新或删除操作;
3. 无需传统数据库的事务处理;
4. 相对互联网应用,写多读少;
5. 流量平稳,根据设备数量和采集频次,可以预测出来;
6. 用户关注的是一段时间的趋势,而不是某一特点时间点的值;
7. 数据是有保留期限的;
8. 数据的查询分析一定是基于时间段和地理区域的;
9. 除存储查询外,还往往需要各种统计和实时计算操作;
10. 数据量巨大一天采集的数据就可以超过100亿条。
充分利用上述特征TDengine采取了一特殊的优化的存储和计算设计来处理时序数据能将系统处理能力显著提高。
### 关系型数据库模型
因为采集的数据一般是结构化数据而且为降低学习门槛TDengine采用传统的关系型数据库模型管理数据。因此用户需要先创建库然后创建表之后才能插入或查询数据。
### 一个设备一张表
为充分利用其数据的时序性和其他数据特点TDengine要求**对每个数据采集点单独建表**比如有一千万个智能电表就需创建一千万张表上述表格中的D1001, D1002, D1003, D1004都需单独建表用来存储这个采集点所采集的时序数据。这种设计能保证一个采集点的数据在存储介质上是一块一块连续的大幅减少随机读取操作成数量级的提升读取和查询速度。而且由于不同数据采集设备产生数据的过程完全独立每个设备只产生属于自己的数据一张表也就只有一个写入者。这样每个表就可以采用无锁方式来写写入速度就能大幅提升。同时对于一个数据采集点而言其产生的数据是时序的因此写的操作可用追加的方式实现进一步大幅提高数据写入速度。
### 数据建模最佳实践
**表(Table)**TDengine 建议用数据采集点的名字(如上表中的D1001)来做表名。每个数据采集点可能同时采集多个物理量(如上表中的value1, value2, value3),每个物理量对应一张表中的一列,数据类型可以是整型、浮点型、字符串等。除此之外,表的第一列必须是时间戳,即数据类型为 timestamp。有的设备有多组采集量每一组的采集频次是不一样的这是需要对同一个设备建多张表。对采集的数据TDengine将自动按照时间戳建立索引但对采集的物理量不建任何索引。数据是用列式存储方式保存。
**超级表(Super Table)**对于同一类型的采集点为保证Schema的一致性而且为便于聚合统计操作可以先定义超级表STable(详见第10章),然后再定义表。每个采集点往往还有静态标签信息(如上表中的Tag 1, Tag 2),比如设备型号、颜色等,这些静态信息不会保存在存储采集数据的数据节点中,而是通过超级表保存在元数据节点中。这些静态标签信息将作为过滤条件,用于采集点之间的数据聚合统计操作。
**库(DataBase)**不同的数据采集点往往具有不同的数据特征包括数据采集频率高低数据保留时间长短备份数目单个字段大小等等。为让各种场景下TDengine都能最大效率的工作TDengine建议将不同数据特征的表创建在不同的库里。创建一个库时除SQL标准的选项外应用还可以指定保留时长、数据备份的份数、cache大小、文件块大小、是否压缩等多种参数(详见第19章)。
**Schemaless vs Schema**: 与NoSQL的各种引擎相比由于应用需要定义schema插入数据的灵活性降低。但对于物联网、金融这些典型的时序数据场景schema会很少变更因此这个灵活性不够的设计就不成问题。相反TDengine采用结构化数据来进行处理的方式将让查询、分析的性能成数量级的提升。
TDengine对库的数量、超级表的数量以及表的数量没有做任何限制而且其多少不会对性能产生影响应用按照自己的场景创建即可。
## 主要模块
如图所示TDengine服务主要包含两大模块**管理节点模块(MGMT)** 和 **数据节点模块(DNODE)**。整个TDengine还包含**客户端模块**。
<center> <img src="../assets/structure.png"> </center>
<center> 图 1 TDengine架构示意图 </center>
### 管理节点模块
管理节点模块主要负责元数据的存储和查询等工作其中包括用户信息的管理、数据库和表信息的创建、删除以及查询等。应用连接TDengine时会首先连接到管理节点。在创建/删除数据库和表时,请求也会首先发送请求到管理节点模块。由管理节点模块首先创建/删除元数据信息,然后发送请求到数据节点模块进行分配/删除所需要的资源。在数据写入和查询时,应用同样会首先访问管理节点模块,获取元数据信息。然后根据元数据管理信息访问数据节点模块。
### 数据节点模块
写入数据的存储和查询工作是由数据节点模块负责。 为了更高效地利用资源以及方便将来进行水平扩展TDengine内部对数据节点进行了虚拟化引入了虚拟节点(virtual node, 简称vnode的概念作为存储、资源分配以及数据备份的单元。如图2所示在一个dnode上通过虚拟化可以将该dnode视为多个虚拟节点的集合。
创建一个库时系统会自动分配vnode。每个vnode存储一定数量的表中的数据但一个表只会存在于一个vnode里不会跨vnode。一个vnode只会属于一个库但一个库会有一到多个vnode。不同的vnode之间资源互不共享。每个虚拟节点都有自己的缓存在硬盘上也有自己的存储目录。而同一vnode内部无论是缓存还是硬盘的存储都是共享的。通过虚拟化TDengine可以将dnode上有限的物理资源合理地分配给不同的vnode大大提高资源的利用率和并发度。一台物理机器上的虚拟节点个数可以根据其硬件资源进行配置。
<center> <img src="../assets/vnode.png"> </center>
<center> 图 2 TDengine虚拟化 </center>
### 客户端模块
TDengine客户端模块主要负责将应用传来的请求SQL语句进行解析转化为内部结构体再发送到服务端。TDengine的各种接口都是基于TDengine的客户端模块进行开发的。客户端模块与管理模块使用TCP/UDP通讯端口号由系统参数mgmtShellPort配置, 缺省值为6030。客户端与数据节点模块也是使用TCP/UDP通讯端口号由系统参数vnodeShellPort配置, 缺省值为6035。两个端口号均可通过<a href="../administrator/#Configuration-on-Server">系统配置文件taos.cfg</a>进行个性化设置。
## 写入流程
TDengine的完整写入流程如图3所示。为了保证写入数据的安全性和完整性TDengine在写入数据时采用[预写日志算法]。客户端发来的数据在经过验证以后首先会写入预写日志中以保证TDengine能够在断电等因素导致的服务重启时从预写日志中恢复数据避免数据的丢失。写入预写日志后数据会被写到对应的vnode的缓存中。随后服务端会发送确认信息给客户端表示写入成功。TDengine中存在两种机制可以促使缓存中的数据写入到硬盘上进行持久化存储
<center> <img src="../assets/write_process.png"> </center>
<center> 图 3 TDengine写入流程 </center>
1. **时间驱动的落盘**TDengine服务会定时将vnode缓存中的数据写入到硬盘上默认为一个小时落一次盘。落盘间隔可在配置文件taos.cfg中通过参数commitTime配置。
2. **数据驱动的落盘**当vnode中缓存的数据达到一定规模时为了不阻塞后续数据的写入TDengine也会拉起落盘线程将缓存中的数据清空。数据驱动的落盘会刷新定时落盘的时间。
TDengine在数据落盘时会打开新的预写日志文件在落盘后则会删除老的预写日志文件避免日志文件无限制的增长。TDengine对缓存按照先进先出的原则进行管理以保证每个表的最新数据都在缓存中。
## 数据存储
TDengine将所有数据存储在/var/lib/taos/目录下您可以通过系统配置参数dataDir进行个性化配置。
TDengine中的元数据信息包括TDengine中的数据库、表、用户等信息。每个超级表、以及每个表的标签数据也存放在这里。为提高访问速度元数据全部有缓存。
TDengine中写入的数据在硬盘上是按时间维度进行分片的。同一个vnode中的表在同一时间范围内的数据都存放在同一文件组中。这一数据分片方式可以大大简化数据在时间维度的查询提高查询速度。在默认配置下硬盘上的每个数据文件存放10天数据。用户可根据需要修改系统配置参数daysPerFile进行个性化配置。
表中的数据都有保存时间一旦超过保存时间缺省是3650天数据将被系统自动删除。您可以通过系统配置参数daysToKeep进行个性化设置。
数据在文件中是按块存储的。每个数据块只包含一张表的数据,且数据是按照时间主键递增排列的。数据在数据块中按列存储,这样使得同列的数据存放在一起,对于不同的数据类型还采用不同的压缩方法,大大提高压缩的比例,节省存储空间。
数据文件总共有三类文件一类是data文件它存放了真实的数据块该文件只进行追加操作一类文件是head文件, 它存放了其对应的data文件中数据块的索引信息第三类是last文件专门存储最后写入的数据每次落盘操作时这部分数据会与内存里的数据合并并决定是否写入data文件还是last文件。