文章目录

  • 1. 基本概念
    • 1.1 表设计的优点
  • 2. 开发指南
    • 2.1 建立连接
      • 2.1.1 原生连接
      • 2.1.2 REST 连接
    • 2.2 数据建模
      • 2.2.1 建库
      • 2.2.2 创建超级表
      • 2.2.3 创建表
      • 2.2.4 多列模型 vs 单列模型
    • 2.3. 写入数据
      • 2.3.1 InfluxDB 行协议
      • 2.3.2 OpenTSDB 行协议
      • 2.3.3 OpenTSDB JSON 格式协议
    • 2.4. 查询数据
      • 2.4.1 多表聚合查询
      • 2.4.2 降采样查询、插值
    • 2.5. 连续查询
      • 2.5.1 使用
      • 2.5.2 Note
      • 2.5.3 管理连续查询
    • 2.6. 数据订阅
      • 2.6.1 提出问题
      • 2.6.2 问题解决
        • 2.6.2.1 创建订阅
        • 2.6.2.2 参数解析
        • 2.6.2.3 消费数据
        • 2.6.2.4 测试订阅功能
        • 2.6.2.5 问题
    • 2.7. 缓存
    • 2.8. 用户自定义函数(难)
  • 3. 集群管理
    • 3.1 集群部署
      • 3.1.1 准备步骤:
      • 3.1.2 启动集群
    • 3.2 数据节点管理
      • 3.2.1 dnode 、vnode 、mnode三者关系
      • 3.2.2 数据节点常规操作
      • 3.2.3 手动迁移数据节点
        • 3.2.3.1 参数解析
        • 3.2.3.2 Note
      • 3.2.4 高可用与负载均衡
        • 3.2.4.1 高可用
        • 3.2.4.2 负载均衡
  • 4. SQL手册
    • 4.1 My
    • 4.2 INFO
    • 4.3 TIP
    • 4.4 NOTE
  • 5. 运维指南
    • 4.3 TIP
    • 4.4 NOTE
  • 5. 运维指南

观测云简介

数据洞察

基础设施监测:进程资源消耗,类似TOP命令

日志监测:检查日志,过滤,分析查询,安全排查

应用性能监测:程序运行结点的消耗和API请求,SQL语句

CI可视化、用户访问监测、安全巡检

可用性监测:服务结点的响应情况,数据的表现,网络延迟和出错的情况

智能监控:配置告警的检测项

协作、使用场景、SRE套件

可编程性:可二次开发,自定义场景,告警的开发

存储架构

小的知识点

超级表的列分成两部分:动态部分、静态部分

TDengine使用的是Posix标准,所以是UTC-8,表示东八区,而UTC+8表示的是西八区

子查询注意事项

1. 基本概念

  • All in One:将数据库、消息队列、缓存、流式计算等功能融合一起,应用无需再集成 Kafka/Redis/HBase/Spark 等软件,大幅降低应用开发和维护成本。
  • 无缝集成:不用一行代码,即可与 Telegraf、Grafana、Prometheus、EMQX、HiveMQ、StatsD、collectd、icinga、TCollector、Matlab、R 等第三方工具无缝集成。

1.1 表设计的优点

  1. 由于不同数据采集点产生数据的过程完全独立,每个数据采集点的数据源是唯一的,一张表也就只有一个写入者,这样就可采用无锁方式来写,写入速度就能大幅提升。
  2. 对于一个数据采集点而言,其产生的数据是按照时间排序的,因此写的操作可用追加的方式实现,进一步大幅提高数据写入速度。
  3. 一个数据采集点的数据是以块为单位连续存储的。如果读取一个时间段的数据,它能大幅减少随机读取操作,成数量级的提升读取和查询速度。
  4. 一个数据块内部,采用列式存储,对于不同数据类型,采用不同压缩算法。

2. 开发指南

  1. 如果你要基于时序数据做实时的统计分析,包括各种监测看板,那么建议你采用TDengine的连续查询功能,而不用上线Spark, Flink等复杂的流式计算系统。
  2. 如果你的应用有模块需要消费插入的数据,希望有新的数据插入时,就能获取通知,那么建议你采用TDengine提供的数据订阅功能,而无需专门部署Kafka或其他消息队列软件。
  3. 在很多场景下(如车辆管理),应用需要获取每个数据采集点的最新状态,那么建议你采用TDengine的cache功能,而不用单独部署Redis等缓存软件。

2.1 建立连接

2.1.1 原生连接

public class JNIConnectExample {public static void main(String[] args) throws SQLException {String jdbcUrl = "jdbc:TAOS://localhost:6030?user=root&password=taosdata";Properties connProps = new Properties();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, "UTC-8");Connection conn = DriverManager.getConnection(jdbcUrl, connProps);System.out.println("Connected");conn.close();}
}// if you want to connect a specified database named "dbName"
// String jdbcUrl = "jdbc:TAOS://localhost:6030/dbName?user=root&password=taosdata";

2.1.2 REST 连接

public static void main(String[] args) throws SQLException {String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata";Connection conn = DriverManager.getConnection(jdbcUrl);conn.close();
}

使用 REST 连接时,如果查询数据量比较大,还可开启批量拉取功能。

public static void main(String[] args) throws SQLException {String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata";Properties connProps = new Properties();connProps.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");Connection conn = DriverManager.getConnection(jdbcUrl, connProps);conn.close();
}

2.2 数据建模

2.2.1 建库

CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 6 UPDATE 1;

上述语句将创建一个名为 power 的库,这个库的数据将保留 365 天(超过 365 天将被自动删除),每 10 天一个数据文件,内存块数为 6,允许更新数据。

2.2.2 创建超级表

CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);
Device ID Time Stamp Collected Metrics Tags
Device ID Time Stamp current voltage phase location groupId
d1001 1538548685000 10.3 219 0.31 California.SanFrancisco 2
d1002 1538548684000 10.2 220 0.23 California.SanFrancisco 3

2.2.3 创建表

CREATE TABLE d1001 USING meters TAGS ("California.SanFrancisco", 2);

其中 d1001 是表名,meters 是超级表的表名,后面紧跟标签 Location 的具体标签值 “California.SanFrancisco”,标签 groupId 的具体标签值 2。虽然在创建表时,需要指定标签值,但可以事后修改

自动建表(在写数据时并不确定某个数据采集点的表是否存在)

INSERT INTO d1001 USING meters TAGS ("California.SanFrancisco", 2) VALUES (now, 10.2, 219, 0.32);

2.2.4 多列模型 vs 单列模型

TDengine 支持多列模型,只要物理量是一个数据采集点同时采集的(时间戳一致),这些量就可以作为不同列放在一张超级表里。

但还有一种极限的设计,单列模型,每个采集的物理量都单独建表,因此每种类型的物理量都单独建立一超级表。比如电流、电压、相位,就建三张超级表。

TDengine 建议尽可能采用多列模型,因为插入效率以及存储效率更高。但对于有些场景,一个采集点的采集量的种类经常变化,这个时候,如果采用多列模型,就需要频繁修改超级表的结构定义,让应用变的复杂,这个时候,采用单列模型会显得更简单。

2.3. 写入数据

2.3.1 InfluxDB 行协议

InfluxDB Line 协议采用一行字符串来表示一行数据。分为四部分:

measurement,tag_set field_set timestamp

分别用英文逗号、半角空格、半角空格来分隔四个部分的数据

  • measurement 将作为超级表名;

  • tag_set 将作为标签数据;

  • field_set 将作为普通列数据;

  • timestamp 即本行数据对应的主键时间戳。

meters,location=California.LosAngeles,groupid=2 current=13.4,voltage=223,phase=0.29 1648432611249500

Note:

  • tag_set 中的所有的数据自动转化为 nchar 数据类型;
  • field_set 中的每个数据项都需要对自身的数据类型进行描述, 比如 1.2f代表 float 类型的数值 1.2, 如果不带类型后缀会被当作 double 处理;
  • timestamp 支持多种时间精度。写入数据的时候需要用参数指定时间精度,支持从小时到纳秒的 6 种时间精度。

2.3.2 OpenTSDB 行协议

OpenTSDB 行协议同样采用一行字符串来表示一行数据。OpenTSDB 采用的是单列模型,因此一行只能包含一个普通数据列。标签列依然可以有多个。分为四部分:

<tagk_1>=<tagv_1>[ <tagk_n>=<tagv_n>]

  • metric 将作为超级表名
  • timestamp 本行数据对应的时间戳
  • value 度量值,必须为一个数值。对应的列名也是 “value”
  • 最后一部分是标签集, 用空格分隔不同标签, 所有标签自动转化为 nchar 数据类型

meters.current 1648432611250 11.3 location=California.LosAngeles groupid=3

2.3.3 OpenTSDB JSON 格式协议

[{"metric": "sys.cpu.nice","timestamp": 1346846400,"value": 18,"tags": {"host": "web01","dc": "lga"}},{"metric": "sys.cpu.nice","timestamp": 1346846400,"value": 9,"tags": {"host": "web02","dc": "lga"}}
]

2.4. 查询数据

和MySQL差不多

2.4.1 多表聚合查询

通过指定标签的过滤条件,TDengine 提供了一高效的方法将超级表(某一类型的数据采集点)所属的子表进行聚合查询。

示例一

查找加利福尼亚州所有智能电表采集的电压平均值,并按照 location 分组。

SELECT AVG(voltage) FROM meters GROUP BY location;
avg(voltage) location
222.000000000 California.LosAngeles
219.200000000 California.SanFrancisco

示例二

查找 groupId 为 2 的所有智能电表过去 24 小时的记录条数,电流的最大值

select count(*) , max(current) from meters where groupId = 2 and ts > now -24h;
count(*) max(current)
5 13.4

2.4.2 降采样查询、插值

通过降采样(down sampling)将采集的数据按时间段进行聚合

TDengine 提供了一个简便的关键词 interval 让按照时间窗口的查询操作变得极为简单

将智能电表 d1001 采集的电流值每 10 秒钟求和

SELECT sum(current) FROM d1001 INTERVAL(10s);

降采样也适用于超级表

将加利福尼亚州所有智能电表采集的电流值每秒钟求和

SELECT SUM(current) FROM meters where location like “California%” INTERVAL(1s);

降采样操作也支持时间偏移

将所有智能电表采集的电流值每秒钟求和,但要求每个时间窗口从 500 毫秒开始

SELECT SUM(current) FROM meters INTERVAL(1s, 500a);

2.5. 连续查询

TDengine 可提供定期自动执行的连续查询(Continuous Query)。每次执行的查询是一个时间窗口,时间窗口随着时间流动向前滑动。

2.5.1 使用

指定时间窗口(time window, 参数 interval)大小和每次前向增量时间(forward sliding times, 参数 sliding)。

以一分钟为时间窗口、30 秒为前向增量统计这些电表的平均电压

每隔 30 秒执行一次来增量计算最近一分钟的数据

create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s);

会自动创建一个名为 avg_vol 的新表,然后每隔 30 秒,TDengine 会增量执行 as 后面的 SQL 语句,并将查询结果写入这个表中,用户程序后续只要从 avg_vol 中查询数据即可。

2.5.2 Note

  • 查询时间窗口的最小值是 10 毫秒,没有时间窗口范围的上限。

  • 此外,TDengine 还支持用户指定连续查询的起止时间。

    如果不输入开始时间,连续查询将从第一条原始数据所在的时间窗口开始;

    如果没有输入结束时间,连续查询将永久运行;如果用户指定了结束时间,连续查询在系统时间达到指定的时间以后停止运行。比如使用下面的 SQL 创建的连续查询将运行一小时,之后会自动停止。

    create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s);
    
  • 为了尽量避免原始数据延迟写入导致的问题,TDengine 中连续查询的计算有一定的延迟。也就是说,一个时间窗口过去后,TDengine 并不会立即计算这个窗口的数据,所以要稍等一会(一般不会超过 1 分钟)才能查到计算结果。

2.5.3 管理连续查询

用户可在控制台中通过 show streams 命令来查看系统中全部运行的连续查询,并可以通过 kill stream 命令杀掉对应的连续查询。

2.6. 数据订阅

TDengine 在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说,TDengine 中每一张表均可视为一个标准的消息队列。

TDengine中与订阅相关的API有以下三个:

taos_subscribe、``taos_consumetaos_unsubscribe`

2.6.1 提出问题

我们希望当某个电表的电流超过一定限制(比如 10A)后能得到通知并进行一些处理==(也就是告警)==

有两种方法:一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据:

select * from D1001 where ts > {last_timestamp1} and current > 10;
select * from D1002 where ts > {last_timestamp2} and current > 10;

存在的问题是:随着电表数量的增加,查询数量也会增加,客户端和服务端的性能都会受到影响,当电表数增长到一定的程度,系统就无法承受了。

另一种方法是对超级表进行查询。这样,无论有多少电表,都只需一次查询:

select * from meters where ts > {last_timestamp} and current > 10;

存在的问题是:如何选择 last_timestamp,因为数据产生的时间(timeStamp)和数据入库的时间不一致。

如果选用最慢的一台电表的数据的时间戳作为last_timestamp,就可能会重复读取其他电表的数据;

如果选用最快的一台电表的数据的时间戳作为last_timestamp,就可能造成其他电表的数据的遗漏

2.6.2 问题解决

TDengine的订阅功能解决了此问题

2.6.2.1 创建订阅

首先是使用 taos_subscribe 创建订阅:

TAOS_SUB* tsub = NULL;
if (async) {  // 异步// create an asynchronized subscription, the callback function will be called every 1stsub = taos_subscribe(taos, restart, topic, sql, subscribe_callback, &blockFetch, 1000);
} else {  // 同步// create an synchronized subscription, need to call 'taos_consume' manuallytsub = taos_subscribe(taos, restart, topic, sql, NULL, NULL, 0);
}

上面的代码会根据从命令行获取的参数 async 的值来决定使用哪种方式。

这里,同步的意思是用户程序要直接调用 taos_consume 来拉取数据,而异步则由 API 在内部的另一个线程中调用 taos_consume,然后把拉取到的数据交给回调函数 subscribe_callback去处理。(注意subscribe_callback 中不宜做较为耗时的操作,否则有可能导致客户端阻塞等不可控的问题。)

2.6.2.2 参数解析

  • 参数 taos 是一个已经建立好的数据库连接,在同步模式下无特殊要求。但在异步模式下,需要注意它不会被其它线程使用,否则可能导致不可预计的错误,因为回调函数在 API 的内部线程中被调用,而 TDengine 的部分 API 不是线程安全的。

  • 参数 sql查询语句,可以在其中使用 where 子句指定过滤条件。

  • 订阅的 topic 实际上是它的名字,因为订阅功能是在客户端 API 中实现的,所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。

    如果名为 topic 的订阅不存在,参数 restart 没有意义;

    但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个 topic 时,restart 就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。本例中,如果 restart 是 true,用户程序肯定会读到所有数据。

    但如果这个订阅之前就存在了,并且已经读取了一部分数据,且 restart 是 false,用户程序就不会读到之前已经读取的数据了。

  • 参数taos_subscribe的最后一个参数是以毫秒为单位的轮询周期

    在同步模式下,如果前后两次调用 taos_consume 的时间间隔小于此时间,taos_consume 会阻塞,直到间隔超过此时间。异步模式下,这个时间是两次调用回调函数的最小时间间隔。

  • 参数taos_subscribe 的倒数第二个参数用于用户程序向回调函数传递附加参数,订阅 API 不对其做任何处理,只原样传递给回调函数。此参数在同步模式下无意义。

2.6.2.3 消费数据

if (async) {getchar();
} else while(1) {TAOS_RES* res = taos_consume(tsub);if (res == NULL) {printf("failed to consume data.");break;} else {print_result(res, blockFetch);getchar();}
}

这里是一个 while 循环,用户每按一次回车键就调用一次 taos_consume,而 taos_consume 的返回值是查询到的结果集,与 taos_use_result 完全相同

print_result函数没看懂

2.6.2.4 测试订阅功能

package com.taosdata.example.test;import com.taosdata.jdbc.TSDBConnection;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBResultSet;
import com.taosdata.jdbc.TSDBSubscribe;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;public class SubscribeDemo {// topic 是一个订阅的名字,可以自定义,但是需要保证在一台机器上不重复private static final String topic = "topic-meter-current-bg-10";// sql 是订阅的条件private static final String sql = "select * from meters where current > 10";public static void main(String[] args) {Connection connection = null;TSDBSubscribe subscribe = null;/*** 数据订阅debug记录* 1、首先创建一个TSDBSubscribe对象* 2、设置订阅100次,每次订阅间隔1秒,防止频繁回调* 3、消费数据,将符合sql结果的数据存入TSDBResultSet对象中* 4、设置回调函数,回调函数中输出订阅结果* 5、每成功订阅一次就count++,订阅不结束,程序不结束* 6、当订阅数据获取到100次,则结束订阅*/try {// 获取连接对象Class.forName("com.taosdata.jdbc.TSDBDriver");Properties properties = new Properties();properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");String jdbcUrl = "jdbc:TAOS://192.168.116.201:6030/power?user=root&password=taosdata";connection = DriverManager.getConnection(jdbcUrl, properties);// 创建订阅对象// 但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个 `topic` 时,// `restart` 就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。// 本例中,如果 `restart` 是 true,用户程序肯定会读到所有数据。// 我们设置为false,只订阅最新的数据。subscribe = ((TSDBConnection) connection).subscribe(topic, sql, false);// 设置订阅次数int count = 0;while (count < 100) {  // 订阅100次// wait 1 second to avoid frequent calls to consumeTimeUnit.SECONDS.sleep(1);// consume 详细的可debug进去查看消费流程TSDBResultSet resultSet = subscribe.consume();if (resultSet == null) {continue;}// 获取结果集的元数据做一个简单的输出ResultSetMetaData metaData = resultSet.getMetaData();while (resultSet.next()) {int columnCount = metaData.getColumnCount();for (int i = 1; i <= columnCount; i++) {System.out.print(metaData.getColumnLabel(i) + ": " + resultSet.getString(i) + "\t");}System.out.println();count++;}}} catch (Exception e) {e.printStackTrace();} finally {try {if (null != subscribe)// close subscribesubscribe.close(true);if (connection != null)connection.close();} catch (SQLException throwable) {throwable.printStackTrace();}}}
}

2.6.2.5 问题

REST 连接没有订阅功能,使用原生连接可以体验 TDengine 的全部功能。

但我本机REST连接可以连接到TDengine,但是原生连接失败

数据订阅暂时没实现

问题解决

$ systemctl taos adapter

报错:JNI ERROR (2351): failed to create subscription

去本地配置host,然后再下图:

2.7. 缓存

TDengine 采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制,直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine 充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。

Note

需要注意的是,TDengine 重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的 key-value 缓存系统再将之前缓存的数据重新加载到缓存中。

TDengine 分配固定大小的内存空间作为缓存空间,缓存空间可根据应用的需求和硬件资源配置。通过适当的设置缓存空间,TDengine 可以提供极高性能的写入和查询的支持。

可以通过函数 last_row() 快速获取一张表或一张超级表的最后一条记录,这样很便于在大屏显示各设备的实时状态或采集值。例如:

select last_row(voltage) from meters where location=‘California.SanFrancisco’;

2.8. 用户自定义函数(难)

先C语言定义UDF,(有规定的参数模板)

然后编译,(gcc -g -O0 -fPIC -shared add_one.c -o add_one.so)

再在TDengine中使用:

  • 创建:CREATE FUNCTION add_one AS “/home/taos/udf_example/add_one.so” OUTPUTTYPE INT;

  • 管理:删除(DROP FUNCTION ids(X);)、查看(SHOW FUNCTIONS;)

  • 调用:SELECT X© FROM table/stable;

3. 集群管理

TDengine 支持集群,提供水平扩展的能力。如果需要获得更高的处理能力,只需要多增加节点即可。

TDengine 采用虚拟节点技术,将一个节点虚拟化为多个虚拟节点,以实现负载均衡。同时,TDengine可以将多个节点上的虚拟节点组成虚拟节点组,通过多副本机制,以保证供系统的高可用。

进行了一些实践操作,但卡壳了,后续再学习

3.1 集群部署

3.1.1 准备步骤:

1.配置FQDN,在每个物理节点的hosts中都要进行修改;

2.打开6030-6042的TCP/UDP协议端口;(systemctl stop firewalld)

3.安装TDengine(版本一致),先不启动taosd,第一个物理节点直接回车创建新的,后续的输入任何一个在线的物理节点的FQDN:端口号;

4.检查集群里的各个节点是否能互通;

5.修改taso.cfg,每个节点的配置文件都需要修改,

// firstEp 是每个数据节点首次启动后连接的第一个数据节点
firstEp h1.taosdata.com:6030

// 必须配置为本数据节点的 FQDN,如果本机只有一个 hostname,可注释掉本项
fqdn h1.taosdata.com

// 配置本数据节点的端口号,缺省是 6030
serverPort 6030

// 副本数为偶数的时候,需要配置,请参考《Arbitrator 的使用》的部分
arbitrator ha.taosdata.com:6042

在每个数据节点,firstEp 需全部配置成一样,但 fqdn 一定要配置成其所在数据节点的值

3.1.2 启动集群

在第一个节点里面使用:CREATE DNODE “h2.taos.com:6030”;

3.2 数据节点管理

3.2.1 dnode 、vnode 、mnode三者关系

dnode:数据节点,是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例,一个工作的系统必须有至少一个数据节点。在系统中的唯一标识由实例的End Point (EP )决定。

vnode:虚拟节点,保存采集的时序数据,而且查询、计算都在这些节点上进行。为便于负载均衡、数据恢复、支持异构环境,TDengine 将一个物理节点根据其计算和存储资源切分为多个 vnode。这些 vnode 的管理是 TDengine 自动完成的,对应用完全透明。

vgroup:虚拟节点组,不同数据节点上的 vnode 可以组成一个虚拟节点组(vnode group)来保证系统的高可靠。

mnode:管理节点,dnode会报告状态(包括硬盘空间、内存大小、CPU、网络、虚拟节点个数等),因此 mnode 了解整个集群的状态。基于整体状态,当 mnode 发现某个 dnode 负载过重,它会将 dnode 上的一个或多个 vnode 挪到其他 dnode。在挪动过程中,对外服务继续进行,数据插入、查询和计算操作都不受影响。负载均衡操作结束后,应用也无需重启,将自动连接新的 vnode。

3.2.2 数据节点常规操作

show、create 、drop dnode;

WARNING

数据节点一旦被 drop 之后,不能重新加入集群。需要将此节点重新部署(清空数据文件夹)。

集群在完成 drop dnode 操作之前,会将该 dnode 的数据迁移走。 请注意 drop dnode 和 停止 taosd 进程是两个不同的概念,不要混淆:因为删除 dnode 之前要执行迁移数据的操作,因此被删除的 dnode 必须保持在线状态。待删除操作结束之后,才能停止 taosd 进程。

一个数据节点被 drop 之后,其他节点都会感知到这个 dnodeID 的删除操作,任何集群中的节点都不会再接收此 dnodeID 的请求。 dnodeID 是集群自动分配的,不得人工指定。它在生成时是递增的,不会重复。

3.2.3 手动迁移数据节点

$ ALTER DNODE <source-dnodeId> BALANCE "VNODE:<vgId>-DNODE:<dest-dnodeId>";

3.2.3.1 参数解析

source-dnodeId 是源 dnodeId,也就是待迁移的 vnode 所在的 dnodeID;

vgId 可以通过 SHOW VGROUPS 获得,列表的第一列;

dest-dnodeId 是目标 dnodeId。

举个例子:

先通过show vgroups;查看分布情况

vgId tables status onlines v1_dnode v1_status compacting
14 5000 ready 1 2 master 0
15 5000 ready 1 2 master 0
16 5001 ready 1 2 master 0
17 5001 ready 1 1 master 0

观察得到的结果是:dnode2中有3个vgroup,而dnode1中只有1个vgroup,我们想要把vgid为16的vroup从dnode2迁移到dnode1

alter dnode 2 balance “vnode:16-dnode:1”;

结果:DB error: Balance already enabled

表示数据库已经启动了balance选项,无法进行手动迁移,

需要先停止集群,将两个dnode的配置文件的balance的值设为0之后,重新启动集群,再次执行alter dnode

3.2.3.2 Note

只有在集群的自动负载均衡选项关闭时(balance 设置为 0),才允许手动迁移。 只有处于正常工作状态的 vnode 才能被迁移:master/slave;当处于 offline/unsynced/syncing 状态时,是不能迁移的。 迁移前,务必核实目标 dnode 的资源足够:CPU、内存、硬盘。

3.2.4 高可用与负载均衡

3.2.4.1 高可用

无论是 vnode 还是 mnode,都必须配置多个副本。

3.2.4.2 负载均衡

有三种情况,将触发负载均衡,而且都无需人工干预。

  • 当一个新数据节点添加进集群时,系统将自动触发负载均衡,一些节点上的数据将被自动转移到新数据节点上,无需任何人工干预。

  • 当一个数据节点从集群中移除时,系统将自动把该数据节点上的数据转移到其他数据节点,无需任何人工干预。

  • 如果一个数据节点过热(数据量过大),系统将自动进行负载均衡,将该数据节点的一些 vnode 自动挪到其他节点。

当上述三种情况发生时,系统将启动各个数据节点的负载计算,从而决定如何挪动。

负载均衡由参数 balance 控制,它决定是否启动自动负载均衡,0 表示禁用,1 表示启用自动负载均衡。

上面我们提到手动迁移数据节点需要把balace设置为0,就是这个原因。

4. SQL手册

4.1 My

My

  • 自动建表语法也支持在一条语句中向多个表插入记录。例如:
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) VALUES ('2021-07-13 14:06:34.630', 10.2, 219, 0.32) ('2021-07-13 14:06:35.779', 10.15, 217, 0.33)d21002 USING meters (groupId) TAGS (2) VALUES ('2021-07-13 14:06:34.255', 10.15, 217, 0.33)d21003 USING meters (groupId) TAGS (2) (ts, current, phase) VALUES ('2021-07-13 14:06:34.255', 10.27, 0.31);
  • 获取当前所在的数据库 ,如果登录的时候没有指定默认数据库,且没有使用USE命令切换,则返回 NULL。

    SELECT DATABASE();

  • 获取服务器和客户端版本号:

    SELECT CLIENT_VERSION(); SELECT SERVER_VERSION();

  • 服务器状态检测语句: 如果服务器正常,返回一个数字(例如 1)。如果服务器异常,返回 error code。

    SELECT SERVER_STATUS();

  • 官网有个小技巧部分:

    -- 获取一个超级表所有的子表名及相关的标签信息:
    SELECT TBNAME, location FROM meters;
    -- 统计超级表下辖子表数量:
    SELECT COUNT(TBNAME) FROM meters;
    -- 以上两个查询均只支持在 WHERE 条件子句中添加针对标签(TAGS)的过滤条件。
    暂不支持含列名的四则运算表达式用于条件过滤算子(例如,不支持 where a*2>6;,但可以写 where a>6/2;)。
    暂不支持含列名的四则运算表达式作为 SQL 函数的应用对象(例如,不支持 select min(2*a) from t;,但可以写 select 2*min(a) from t;)。
    
  • 关于嵌套查询,官网写了很多规则

4.2 INFO

INFO

  • 批量建表方式要求数据表必须以超级表为模板。
  • 如果不指定列,也即使用全列模式——那么在 VALUES 部分提供的数据,必须为数据表的每个列都显式地提供数据。全列模式写入速度会远快于指定列,因此建议尽可能采用全列写入方式,此时空列可以填入 NULL。

4.3 TIP

TIP

  • TDengine 对 SQL 语句中的英文字符不区分大小写,自动转化为小写执行。因此用户大小写敏感的字符串及密码,需要使用单引号将字符串引起来。aBcabc 是不同的表名,但是 abc 和 aBc 是相同的表名。

4.4 NOTE

NOTE

  • SQL 语句中的数值类型将依据是否存在小数点,或使用科学计数法表示,来判断数值类型是否为整型或者浮点型,因此在使用时要注意相应类型越界的情况。例如,9999999999999999999 会认为超过长整型的上边界而溢出,而 9999999999999999999.0 会被认为是有效的浮点数。

  • 字符串格式的时间戳写法不受所在 DATABASE 的时间精度设置影响;而长整形格式的时间戳写法会受到所在 DATABASE 的时间精度设置影响——例子中的时间戳在毫秒精度下可以写作 1626164208000,而如果是在微秒精度设置下就需要写为 1626164208000000,纳秒精度设置下需要写为 1626164208000000000。

  • JOIN 语句存在如下限制要求:

    • 不支持只对其中一部分表做 GROUP BY。

    • JOIN 查询的不同表的过滤条件之间不能为 OR。

    • JOIN 查询要求连接条件不能是普通列,只能针对标签和主时间字段列(第一列)。

5. 运维指南

4.3 TIP

TIP

  • TDengine 对 SQL 语句中的英文字符不区分大小写,自动转化为小写执行。因此用户大小写敏感的字符串及密码,需要使用单引号将字符串引起来。aBcabc 是不同的表名,但是 abc 和 aBc 是相同的表名。

4.4 NOTE

NOTE

  • SQL 语句中的数值类型将依据是否存在小数点,或使用科学计数法表示,来判断数值类型是否为整型或者浮点型,因此在使用时要注意相应类型越界的情况。例如,9999999999999999999 会认为超过长整型的上边界而溢出,而 9999999999999999999.0 会被认为是有效的浮点数。

  • 字符串格式的时间戳写法不受所在 DATABASE 的时间精度设置影响;而长整形格式的时间戳写法会受到所在 DATABASE 的时间精度设置影响——例子中的时间戳在毫秒精度下可以写作 1626164208000,而如果是在微秒精度设置下就需要写为 1626164208000000,纳秒精度设置下需要写为 1626164208000000000。

  • JOIN 语句存在如下限制要求:

    • 不支持只对其中一部分表做 GROUP BY。

    • JOIN 查询的不同表的过滤条件之间不能为 OR。

    • JOIN 查询要求连接条件不能是普通列,只能针对标签和主时间字段列(第一列)。

5. 运维指南

TDengine学习笔记相关推荐

  1. TDengine学习笔记:vnode

    TDengine学习笔记:vnode 1.vnode高可用测试 1.1.环境清理与准备 1.2.关闭vnode Slave节点 1.3.再次插入数据 1.4.启动节点ms08 2.vnode选主流程 ...

  2. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  3. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  4. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  5. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  6. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

  7. 知识图谱学习笔记(1)

    知识图谱学习笔记第一部分,包含RDF介绍,以及Jena RDF API使用 知识图谱的基石:RDF RDF(Resource Description Framework),即资源描述框架,其本质是一个 ...

  8. 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记

    计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...

  9. Go 学习推荐 —(Go by example 中文版、Go 构建 Web 应用、Go 学习笔记、Golang常见错误、Go 语言四十二章经、Go 语言高级编程)

    Go by example 中文版 Go 构建 Web 应用 Go 学习笔记:无痕 Go 标准库中文文档 Golang开发新手常犯的50个错误 50 Shades of Go: Traps, Gotc ...

最新文章

  1. 一款强大而实用的图片去水印神器
  2. 4.Azure创建点到站点的***隧道(下)
  3. java中接口适配器实现,12.1.8 Java中的应用-AWT事件适配器(接口的适配器模式)...
  4. LeetCode 100. 相同的树(二叉树遍历)
  5. 1000道Python题库系列分享14(1道代码阅读题)
  6. 提高代码的运行效率 (4)
  7. mysql show slave_MySQL show slave status 参考
  8. 《0元搭建个人博客史上最详细教程》(阿里云学生服务器+宝塔一键部署篇)
  9. linux下vscode配置c++,使其和Visual Studio2019一样调试
  10. mysql根据身份证计算具体的年龄
  11. 3A锂电池充电管理芯片PW4035
  12. 3d打印机c语言程序下载,芯烨打印机设置软件工具
  13. Nginx服务(6)——实现Gzip网页压缩和图片压缩
  14. 使用smtp服务器发送邮件_如何使用SMTP服务器发送WordPress电子邮件
  15. Object-Oriented Programming Summary Ⅱ
  16. 转铁蛋白(Tf)修饰去氢骆驼蓬碱磁纳米脂质体/香豆素-6脂质体/多柔比星脂质体
  17. python编写word_如何使用Python来编辑word
  18. 迟来的年度总结 —— 我与 csdn 的故事
  19. 室内定位——如何在微信小程序中获取Beacon的RSSI值
  20. 叮咚买菜2021第四季度财报数据公布:上海地区实现盈利

热门文章

  1. Winform下ToolStrip承载自定义控件或 Windows 窗体控件。
  2. 文本文件后缀修改为 .html
  3. Android 设置锁屏时间,屏幕常亮效果
  4. ABB机器人教程 (1)学习准备
  5. 软件测试技术 实验一:黑盒测试1
  6. 10条网站易用性技巧
  7. U盘启动安装Windows7 系统
  8. program received signal sigfpe,Arithmetic exception
  9. ASPX页面AJAX调用ASPX后台
  10. Gitte (https://gitee.com/) 常用git指令--实例