Merge branch '3.0' of github.com:taosdata/TDengine into fix/TD-31288

This commit is contained in:
54liuyao 2024-08-07 19:25:53 +08:00
commit 3b88a48b6f
58 changed files with 183 additions and 24 deletions

View File

@ -6,7 +6,7 @@ toc_max_heading_level: 4
TDengine 是一个高性能、分布式的时序数据库。通过集成的缓存、数据订阅、流计算和数据清洗与转换等功能TDengine 已经发展成为一个专为物联网、工业互联网、金融和 IT 运维等关键行业量身定制的时序大数据平台。该平台能够高效地汇聚、存储、分析、计算和分发来自海量数据采集点的大规模数据流,每日处理能力可达 TB 乃至 PB 级别。借助 TDengine企业可以实现实时的业务监控和预警进而发掘出有价值的商业洞察。
自 2019 年 7 月 以 来, 涛 思 数 据 陆 续 将 TDengine 的 不 同 版 本 开 源, 包 括 单 机版2019 年 7 月、集群版2020 年 8 月以及云原生版2022 年 8 月。开源之后TDengine 迅速获得了全球开发者的关注,多次在 GitHub 网站全球趋势排行榜上位居榜首。截至编写本书时TDengine 在 GitHub 网站上已积累近 2.3 万颗星安装实例超过53 万个,覆盖 60 多个国家和地区,广泛应用于电力、石油、化工、新能源、智能制造、汽车、环境监测等行业或领域,赢得了全球开发者的广泛认可
自 2019 年 7 月 以 来, 涛 思 数 据 陆 续 将 TDengine 的 不 同 版 本 开 源, 包 括 单 机版2019 年 7 月、集群版2020 年 8 月以及云原生版2022 年 8 月。开源之后TDengine 迅速获得了全球开发者的关注,多次在 GitHub 网站全球趋势排行榜上位居榜首,最新的关注热度见[涛思数据首页](https://www.taosdata.com/)。
## TDengine 产品

View File

@ -71,4 +71,54 @@ taos>
## 快速体验
想要快速体验 TDengine 的写入和查询能力,请参考[快速体验](../use)
### 体验写入
taosBenchmark 是一个专为测试 TDengine 性能而设计的工具它能够全面评估TDengine 在写入、查询和订阅等方面的功能表现。该工具能够模拟大量设备产生的数据,并允许用户灵活控制数据库、超级表、标签列的数量和类型、数据列的数量和类型、子表数量、每张子表的数据量、写入数据的时间间隔、工作线程数量以及是否写入乱序数据等策略。
启动 TDengine 的服务,在终端中执行如下命令
```shell
taosBenchmark -y
```
系统将自动在数据库 test 下创建一张名为 meters的超级表。这张超级表将包含 10 000 张子表,表名从 d0 到 d9999每张表包含 10,000条记录。每条记录包含 ts时间戳、current电流、voltage电压和 phase相位4个字段。时间戳范围从“2017-07-14 10:40:00 000”到“2017-07-14 10:40:09 999”。每张表还带有 location 和 groupId 两个标签其中groupId 设置为 1 到 10而 location 则设置为 California.Campbell、California.Cupertino 等城市信息。
执行该命令后,系统将迅速完成 1 亿条记录的写入过程。实际所需时间取决于硬件性能,但即便在普通 PC 服务器上,这个过程通常也只需要十几秒。
taosBenchmark 提供了丰富的选项,允许用户自定义测试参数,如表的数目、记录条数等。要查看详细的参数列表,请在终端中输入如下命令
```shell
taosBenchmark --help
```
有关taosBenchmark 的详细使用方法,请参考[taosBenchmark 参考手册](../../reference/components/taosbenchmark)
### 体验查询
使用上述 taosBenchmark 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
1. 查询超级表 meters 下的记录总条数
```shell
SELECT COUNT(*) FROM test.meters;
```
2. 查询 1 亿条记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
3. 查询 location = "California.SanFrancisco" 的记录总条数
```shell
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
4. 查询 groupId = 10 的所有记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
5. 对表 d1001 按每 10 秒进行平均值、最大值和最小值聚合统计
```shell
SELECT _wstart, AVG(current), MAX(voltage), MIN(phase) FROM test.d1001 INTERVAL(10s);
```
在上面的查询中使用系统提供的伪列_wstart 来给出每个窗口的开始时间。

View File

@ -267,4 +267,54 @@ Query OK, 2 row(s) in set (0.003128s)
## 快速体验
想要快速体验 TDengine 的写入和查询能力,请参考[快速体验](../use)
### 体验写入
taosBenchmark 是一个专为测试 TDengine 性能而设计的工具它能够全面评估TDengine 在写入、查询和订阅等方面的功能表现。该工具能够模拟大量设备产生的数据,并允许用户灵活控制数据库、超级表、标签列的数量和类型、数据列的数量和类型、子表数量、每张子表的数据量、写入数据的时间间隔、工作线程数量以及是否写入乱序数据等策略。
启动 TDengine 的服务,在终端中执行如下命令
```shell
taosBenchmark -y
```
系统将自动在数据库 test 下创建一张名为 meters的超级表。这张超级表将包含 10 000 张子表,表名从 d0 到 d9999每张表包含 10,000条记录。每条记录包含 ts时间戳、current电流、voltage电压和 phase相位4个字段。时间戳范围从“2017-07-14 10:40:00 000”到“2017-07-14 10:40:09 999”。每张表还带有 location 和 groupId 两个标签其中groupId 设置为 1 到 10而 location 则设置为 California.Campbell、California.Cupertino 等城市信息。
执行该命令后,系统将迅速完成 1 亿条记录的写入过程。实际所需时间取决于硬件性能,但即便在普通 PC 服务器上,这个过程通常也只需要十几秒。
taosBenchmark 提供了丰富的选项,允许用户自定义测试参数,如表的数目、记录条数等。要查看详细的参数列表,请在终端中输入如下命令
```shell
taosBenchmark --help
```
有关taosBenchmark 的详细使用方法,请参考[taosBenchmark 参考手册](../../reference/components/taosbenchmark)
### 体验查询
使用上述 taosBenchmark 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
1. 查询超级表 meters 下的记录总条数
```shell
SELECT COUNT(*) FROM test.meters;
```
2. 查询 1 亿条记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
3. 查询 location = "California.SanFrancisco" 的记录总条数
```shell
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
4. 查询 groupId = 10 的所有记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
5. 对表 d1001 按每 10 秒进行平均值、最大值和最小值聚合统计
```shell
SELECT _wstart, AVG(current), MAX(voltage), MIN(phase) FROM test.d1001 INTERVAL(10s);
```
在上面的查询中使用系统提供的伪列_wstart 来给出每个窗口的开始时间。

View File

@ -8,6 +8,10 @@ sidebar_label: 集群维护
本节介绍 TDengine Enterprise 中提供的高阶集群维护手段,能够使 TDengine 集群长期运行得更健壮和高效。
## 节点管理
如何管理集群节点请参考[节点管理](../../reference/taos-sql/node)
## 数据重整
TDengine 面向多种写入场景而很多写入场景下TDengine 的存储会导致数据存储的放大或数据文件的空洞等。这一方面影响数据的存储效率另一方面也会影响查询效率。为了解决上述问题TDengine 企业版提供了对数据的重整功能,即 DATA COMPACT 功能,将存储的数据文件重新整理,删除文件空洞和无效数据,提高数据的组织度,从而提高存储和查询的效率。数据重整功能在 3.0.3.0 版本第一次发布,此后又经过了多次迭代优化,建议使用最新版本。

View File

@ -4,27 +4,27 @@ sidebar_label: taosExplorer
toc_max_heading_level: 4
---
taos-explorer 是一个为用户提供 TDengine 实例的可视化管理交互工具的 web 服务。本节主要讲述其安装和部署。它的各项功能都是基于简单易上手的图形界面,可以直接尝试,如果有需要也可以考高级功能和运维指南中的相关内容。
taosExplorer 是一个为用户提供 TDengine 实例的可视化管理交互工具的 web 服务。本节主要讲述其安装和部署。它的各项功能都是基于简单易上手的图形界面,可以直接尝试,如果有需要也可以考高级功能和运维指南中的相关内容。
## 安装
taos-explorer 无需单独安装,从 TDengine 3.3.0.0 版本开始,它随着 TDengine Enterprise Server 安装包一起发布,安装完成后,就可以看到 `taos-explorer` 服务。
taosEexplorer 无需单独安装,从 TDengine 3.3.0.0 版本开始,它随着 TDengine Enterprise Server 安装包一起发布,安装完成后,就可以看到 `taos-explorer` 服务。
## 配置
在启动 Explorer 之前,请确保配置文件中的内容正确。
在启动 taosExplorer 之前,请确保配置文件中的内容正确。
```TOML
# Explorer listen port
# listen port
port = 6060
# Explorer listen address for IPv4
# listen address for IPv4
addr = "0.0.0.0"
# Explorer listen address for IPv4
# listen address for IPv4
#ipv6 = "::1"
# Explorer log level. Possible: error,warn,info,debug,trace
# log level. Possible: error,warn,info,debug,trace
log_level = "info"
# taosAdapter address.
@ -49,9 +49,9 @@ cors = false
说明:
- `port`Explorer 服务绑定的端口。
- `addr`Explorer 服务绑定的 IPv4 地址,默认为 `0.0.0.0`。如需修改,请配置为 `localhost` 之外的地址以对外提供服务。
- `ipv6`Explorer 服务绑定的 IPv6 地址,默认不绑定 IPv6 地址。
- `port`taosExplorer 服务绑定的端口。
- `addr`taosExplorer 服务绑定的 IPv4 地址,默认为 `0.0.0.0`。如需修改,请配置为 `localhost` 之外的地址以对外提供服务。
- `ipv6`taosExplorer 服务绑定的 IPv6 地址,默认不绑定 IPv6 地址。
- `log_level`:日志级别,可选值为 "error", "warn", "info", "debug", "trace"。
- `cluster`TDengine 集群的 taosAdapter 地址。
- `x_api`taosX 的 gRPC 地址。
@ -62,7 +62,7 @@ cors = false
## 启动停止
然后启动 Explorer可以直接在命令行执行 taos-explorer 或者使用 systemctl 命令:
然后启动 taosExplorer可以直接在命令行执行 taos-explorer 或者使用 systemctl 命令:
```bash
systemctl start taos-explorer # Linux
@ -78,7 +78,7 @@ sc.exe stop taos-explorer # Windows
## 问题排查
1. 当通过浏览器打开 Explorer 站点遇到“无法访问此网站”的错误信息时,请通过命令行登录 taosExplorer 所在机器,并使用命令 `systemctl status taos-explorer` 检查服务的状态,如果返回的状态是 `inactive`,请使用命令`systemctl start taos-explorer` 启动服务。
2. 如果需要获取 Explorer 的详细日志,可通过命令 `journalctl -u taos-explorer`
2. 如果需要获取 taosExplorer 的详细日志,可通过命令 `journalctl -u taos-explorer`
3. 当使用 Nginx 或其他工具进行转发时,注意进行 CORS 设置或在配置文件中使用 `cors = true`
这是一个 Nginx 配置文件 CORS 设置的例子:

View File

@ -1,7 +1,7 @@
---
sidebar_label: 集群管理
title: 集群管理
description: 管理集群的 SQL 命令的详细解析
sidebar_label: 节点管理
title: 节点管理
description: 管理集群节点的 SQL 命令的详细解析
---
组成 TDengine 集群的物理实体是 dnode (data node 的缩写),它是一个运行在操作系统之上的进程。在 dnode 中可以建立负责时序数据存储的 vnode (virtual node),在多节点集群环境下当某个数据库的 replica 为 3 时,该数据库中的每个 vgroup 由 3 个 vnode 组成;当数据库的 replica 为 1 时,该数据库中的每个 vgroup 由 1 个 vnode 组成。如果要想配置某个数据库为多副本,则集群中的 dnode 数量至少为 3。在 dnode 还可以创建 mnode (management node),单个集群中最多可以创建三个 mnode。在 TDengine 3.0.0.0 中为了支持存算分离,引入了一种新的逻辑节点 qnode (query node)qnode 和 vnode 既可以共存在一个 dnode 中,也可以完全分离在不同的 dnode 上。

View File

Before

Width:  |  Height:  |  Size: 319 KiB

After

Width:  |  Height:  |  Size: 319 KiB

View File

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 179 KiB

View File

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 476 KiB

After

Width:  |  Height:  |  Size: 476 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 359 KiB

After

Width:  |  Height:  |  Size: 359 KiB

View File

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 163 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 232 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 231 KiB

After

Width:  |  Height:  |  Size: 231 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 215 KiB

After

Width:  |  Height:  |  Size: 215 KiB

View File

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 194 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -1372,7 +1372,7 @@ static int32_t buildResult(SSDataBlock *pBlock, int32_t *numOfRows, int64_t cons
OffsetRows *tmp = taosArrayGet(offsetRows, i);
MND_TMQ_NULL_CHECK(tmp);
if (tmp->vgId != pVgEp->vgId) {
mError("mnd show subscriptions: do not find vgId:%d, %d in offsetRows", tmp->vgId, pVgEp->vgId);
mInfo("mnd show subscriptions: do not find vgId:%d, %d in offsetRows", tmp->vgId, pVgEp->vgId);
continue;
}
data = tmp;
@ -1396,7 +1396,7 @@ static int32_t buildResult(SSDataBlock *pBlock, int32_t *numOfRows, int64_t cons
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
MND_TMQ_NULL_CHECK(pColInfo);
colDataSetNULL(pColInfo, *numOfRows);
mError("mnd show subscriptions: do not find vgId:%d in offsetRows", pVgEp->vgId);
mInfo("mnd show subscriptions: do not find vgId:%d in offsetRows", pVgEp->vgId);
}
(*numOfRows)++;
}

View File

@ -1440,6 +1440,11 @@ int32_t metaGetTableTags(void *pVnode, uint64_t suid, SArray *pUidTagInfo) {
STUidTagInfo info = {.uid = uid, .pTagVal = pCur->pVal};
info.pTagVal = taosMemoryMalloc(pCur->vLen);
if (!info.pTagVal) {
metaCloseCtbCursor(pCur);
taosHashCleanup(pSepecifiedUidMap);
return TSDB_CODE_OUT_OF_MEMORY;
}
memcpy(info.pTagVal, pCur->pVal, pCur->vLen);
if (taosArrayPush(pUidTagInfo, &info) == NULL) {
metaCloseCtbCursor(pCur);
@ -1462,6 +1467,11 @@ int32_t metaGetTableTags(void *pVnode, uint64_t suid, SArray *pUidTagInfo) {
STUidTagInfo *pTagInfo = taosArrayGet(pUidTagInfo, *index);
if (pTagInfo->pTagVal == NULL) {
pTagInfo->pTagVal = taosMemoryMalloc(pCur->vLen);
if (!pTagInfo->pTagVal) {
metaCloseCtbCursor(pCur);
taosHashCleanup(pSepecifiedUidMap);
return TSDB_CODE_OUT_OF_MEMORY;
}
memcpy(pTagInfo->pTagVal, pCur->pVal, pCur->vLen);
}
}

View File

@ -347,6 +347,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
code = TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY);
goto END;
}
totalMetaRows++;
if ((taosArrayGetSize(btMetaRsp.batchMetaReq) >= tmqRowSize) || (taosGetTimestampMs() - st > 1000)) {
tqOffsetResetToLog(&btMetaRsp.rspOffset, fetchVer);
code = tqSendBatchMetaPollRsp(pHandle, pMsg, pRequest, &btMetaRsp, vgId);

View File

@ -1144,6 +1144,8 @@ int32_t chkpMayDelObsolete(void* arg, int64_t chkpId, char* path) {
int64_t id = *(int64_t*)taosArrayGet(chkpDel, i);
char tbuf[256] = {0};
sprintf(tbuf, "%s%scheckpoint%" PRId64 "", path, TD_DIRSEP, id);
stInfo("backend remove obsolete checkpoint: %s", tbuf);
if (taosIsDir(tbuf)) {
taosRemoveDir(tbuf);
}
@ -2661,6 +2663,7 @@ void taskDbDestroy(void* pDb, bool flush) {
if (wrapper->removeAllFiles) {
char* err = NULL;
stInfo("drop task remove backend dat:%s", wrapper->path);
taosRemoveDir(wrapper->path);
}
taosMemoryFree(wrapper->path);

View File

@ -321,7 +321,7 @@ void streamFreeTaskState(SStreamTask* pTask, int8_t remove) {
stDebug("s-task:0x%x start to free task state", pTask->id.taskId);
streamStateClose(pTask->pState, remove);
taskDbSetClearFileFlag(pTask->pBackend);
if (remove)taskDbSetClearFileFlag(pTask->pBackend);
taskDbRemoveRef(pTask->pBackend);
pTask->pBackend = NULL;
pTask->pState = NULL;

View File

@ -224,7 +224,10 @@ int tdbTbcOpen(TTB *pTb, TBC **ppTbc, TXN *pTxn) {
return -1;
}
(void)tdbBtcOpen(&pTbc->btc, pTb->pBt, pTxn);
if (tdbBtcOpen(&pTbc->btc, pTb->pBt, pTxn)) {
taosMemoryFree(pTbc);
return -1;
}
*ppTbc = pTbc;
return 0;

View File

@ -1075,14 +1075,14 @@ int32_t taosGetFqdn(char *fqdn) {
freeaddrinfo(result);
#else
#elif WINDOWS
struct addrinfo hints = {0};
struct addrinfo *result = NULL;
hints.ai_flags = AI_CANONNAME;
int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
if (!result) {
fprintf(stderr, "failed to get fqdn, code:%d, reason:%s\n", ret, gai_strerror(ret));
fprintf(stderr, "failed to get fqdn, code:%d, hostname:%s, reason:%s\n", ret, hostname, gai_strerror(ret));
return -1;
}
strcpy(fqdn, result->ai_canonname);

View File

@ -496,6 +496,43 @@ class TDTestCase:
consumer.close()
print("consume_ts_4551 ok")
def consume_td_31283(self):
tdSql.execute(f'create database if not exists d31283')
tdSql.execute(f'use d31283')
tdSql.execute(f'create topic topic_31283 with meta as database d31283')
consumer_dict = {
"group.id": "g1",
"td.connect.user": "root",
"td.connect.pass": "taosdata",
"auto.offset.reset": "earliest",
"experimental.snapshot.enable": "true",
# "msg.enable.batchmeta": "true"
}
consumer = Consumer(consumer_dict)
try:
consumer.subscribe(["topic_31283"])
except TmqError:
tdLog.exit(f"subscribe error")
tdSql.execute(f'create table stt(ts timestamp, i int) tags(t int)')
hasData = False
try:
while True:
res = consumer.poll(1)
if not res:
break
hasData = True
finally:
consumer.close()
if not hasData:
tdLog.exit(f"consume_td_31283 error")
print("consume_td_31283 ok")
def consume_TS_5067_Test(self):
tdSql.execute(f'create database if not exists d1 vgroups 1')
tdSql.execute(f'use d1')
@ -632,6 +669,7 @@ class TDTestCase:
self.consume_ts_4544()
self.consume_ts_4551()
self.consume_TS_4540_Test()
self.consume_td_31283()
tdSql.prepare()
self.checkWal1VgroupOnlyMeta()