TDengine RPC 通信层深度解析 — 协议格式、连接管理与重试机制

在这里插入图片描述

适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-05-15

概述

RPC(Remote Procedure Call)通信层是 TDengine 分布式系统的网络基础设施。集群中所有节点间的通信——客户端到 taosd、dnode 到 mnode 的心跳、Raft 日志复制、查询分发——都通过 RPC 层完成。

本文深入解析 RPC 通信层的五大核心机制:

  1. 协议格式:消息头结构、魔数校验、序列号追踪
  2. 连接管理:基于 libuv 的 TCP 连接池、空闲回收、多路复用
  3. 重试机制:指数退避、EP 轮转、快速失败
  4. 通道隔离:多 RPC 实例分离不同类型流量
  5. 流控与背压:队列内存限额、连接数上限、磁盘空间检查

核心概念速查表

概念说明
RPC 消息所有节点间通信的基本单元,由固定格式的消息头 + 可变长消息体组成
消息类型(msgType)标识消息用途的枚举值,按模块分段(MND/VND/SCH/SYNC 等)
EP Set端点集合,包含最多 3 个 mnode 的地址,用于自动切换
连接池客户端按目标地址维护的可复用 TCP 连接队列
消息队列服务端按功能划分的处理队列(写队列、读队列、同步队列等)
traceId贯穿请求全生命周期的追踪标识,用于分布式链路追踪
QID查询 ID,标识一个查询请求,用于关联请求和响应
魔数固定值 0x5f375a86,用于快速识别合法的 TDengine 数据包

详细解析

1. 协议格式

1.1 消息头结构

每条 RPC 消息都包含一个固定格式的二进制消息头,紧接着是可变长度的消息体:

RPC 消息二进制布局:

  ┌──────────────────────────────────────────────────────────┐
  │                      消息头(固定大小)                    │
  ├──────────────────────────────────────────────────────────┤
  │ 标志位(1B) │ 标志位(1B) │ 时间戳(8B) │ 兼容版本号(4B)    │
  ├──────────────────────────────────────────────────────────┤
  │ 魔数(4B)   │ traceId(16B)        │ QID(8B)             │
  ├──────────────────────────────────────────────────────────┤
  │ 状态码(4B) │ 消息类型(4B) │ 消息总长度(4B) │ 序列号(8B) │
  ├──────────────────────────────────────────────────────────┤
  │                    消息体(可变长度)                      │
  └──────────────────────────────────────────────────────────┘

各字段说明:

字段大小说明
version4 bitRPC 协议版本号,当前固定为 2
comp2 bit压缩标志:0=未压缩,1=LZ4 压缩
noResp2 bit是否需要响应:0=需要,1=不需要
withUserInfo2 bit是否携带用户认证信息
hasEpSet2 bit响应中是否包含 EP Set 更新信息
timestamp8 字节发送时的时间戳
compatibilityVer4 字节客户端/服务端的兼容版本号
magicNum4 字节魔数 0x5f375a86,用于包合法性校验
traceId16 字节分布式追踪 ID,贯穿请求全链路
qid8 字节查询 ID
code4 字节响应状态码(请求时为 0)
msgType4 字节消息类型枚举值
msgLen4 字节消息总长度(消息头 + 消息体)
seqNum8 字节每连接递增的序列号
1.2 消息大小限制
限制说明
单消息最大长度512 MB包含消息头的总长度上限
默认最大消息体10 MB应用层默认限制(可调整)
压缩头额外开销8 字节压缩时额外的长度信息
1.3 消息类型分段

TDengine 将消息类型按目标模块分为多个段(segment),便于路由和管理:

段号前缀目标模块典型消息
0TDMT_DND_*DNode 管理创建/删除 vnode、mnode
1TDMT_MND_*MNodeDDL 操作、心跳、元数据查询
2TDMT_VND_*VNode数据写入、子表创建
3TDMT_SCH_*调度器查询执行、结果获取
4TDMT_STREAM_*流计算流任务调度
5TDMT_MON_*监控监控数据上报
6TDMT_SYNC_*Raft 同步选举、日志复制、心跳
7TDMT_VND_STREAM_*VNode 流计算VNode 上的流处理
8TDMT_VND_TMQ_*TMQ 订阅消费请求
9TDMT_MND_ARB_*仲裁仲裁心跳与同步

每个消息类型都有对应的请求(xxx_REQ)和响应(xxx_RSP)成对定义。

1.4 魔数与版本校验

收到数据包后,RPC 层执行两层校验:

  1. 魔数校验:检查消息头中的魔数是否为 0x5f375a86。非法包(如端口扫描、误连接)在此步即被丢弃
  2. 版本兼容性校验:比对客户端和服务端的 compatibilityVer,允许最多 3 个版本的差异。超出范围时返回版本不兼容错误

2. 连接管理

2.1 网络基础 — libuv

TDengine 的 RPC 层基于 libuv 库构建,使用事件驱动的异步 I/O 模型:

  • 每个 RPC 线程运行一个独立的 uv_loop(事件循环)
  • TCP 连接使用 uv_tcp_t 句柄
  • 线程间通信使用 uv_async_t(异步通知)和 uv_pipe_t(管道)
2.2 服务端架构
服务端连接模型:

  ┌─────────────────────────────────────────────────┐
  │              RPC Server (端口 6030)               │
  │                                                   │
  │   Accept 线程                                     │
  │     │  uv_tcp_t (监听 socket)                     │
  │     │                                             │
  │     ├── 新连接到达 → 按轮转分配到 Worker 线程       │
  │     │                                             │
  │   ┌─▼──────────┐  ┌───────────┐  ┌───────────┐  │
  │   │ Worker 0   │  │ Worker 1  │  │ Worker N  │  │
  │   │ uv_loop    │  │ uv_loop   │  │ uv_loop   │  │
  │   │            │  │           │  │           │  │
  │   │ conn pool  │  │ conn pool │  │ conn pool │  │
  │   │ ├ conn A   │  │ ├ conn D  │  │ ├ conn G  │  │
  │   │ ├ conn B   │  │ ├ conn E  │  │ └ conn H  │  │
  │   │ └ conn C   │  │ └ conn F  │  │           │  │
  │   └────────────┘  └───────────┘  └───────────┘  │
  └─────────────────────────────────────────────────┘
  • Accept 线程:负责接受新的 TCP 连接,通过管道将连接分发给 Worker 线程
  • Worker 线程:处理连接上的读写事件,解析消息,将请求分发到对应的处理队列
  • 线程数由 numOfRpcThreads 参数控制
2.3 客户端连接池

客户端(taosc 和 dnode 内部通信)为每个目标地址维护一个连接池

客户端连接池模型:

  ┌────────────────────────────────────────────┐
  │           RPC Client 线程 0                  │
  │                                              │
  │  连接池(按目标地址分组):                    │
  │    "node1:6030" → [idle_conn1, idle_conn2]  │
  │    "node2:6030" → [idle_conn3]              │
  │    "node3:6030" → [](无空闲连接)           │
  │                                              │
  │  共享连接堆缓存:                             │
  │    允许多个请求复用同一 TCP 连接              │
  └────────────────────────────────────────────┘

连接复用策略

  1. 发送请求时,先从连接池中查找目标地址的空闲连接
  2. 如果有空闲连接,直接复用
  3. 如果无空闲连接且未达上限,创建新连接
  4. 如果已达连接上限,等待现有连接释放(最多等待 timeToGetAvailableConn 毫秒)
  5. 请求完成后,连接归还到池中供后续请求使用

连接多路复用

在 Linux 上,单个 TCP 连接允许最多 10 个并发的未完成请求(shareConnLimit),通过序列号(seqNum)匹配请求和响应。macOS/Windows 上限制为 1(不启用多路复用)。

2.4 空闲连接回收
空闲回收机制:

  连接空闲时间超过阈值 → 自动关闭

  阈值计算:
    基础空闲时间 = max(shellActivityTimer × 1000ms, 90秒)
    实际关闭时间 ≈ 基础空闲时间 × 3.3
    默认情况 ≈ 5 分钟无活动后关闭
2.5 连接建立超时
超时类型默认值说明
TCP 连接超时5 秒TCP 三次握手的超时时间
读超时3 秒等待数据读取的超时
等待可用连接500 秒连接池满时等待空闲连接的超时

3. 重试机制

3.1 指数退避算法

当 RPC 请求失败时,客户端使用指数退避策略进行重试:

重试算法:

  第 1 次重试:等待 10ms
  第 2 次重试:等待 20ms    (10 × 2¹)
  第 3 次重试:等待 40ms    (10 × 2²)
  第 4 次重试:等待 80ms    (10 × 2³)
  ...
  第 N 次重试:等待 min(10 × 2^(N-1), 1000ms)
  
  最大重试间隔:1000ms(不再增长)
  总超时限制:20秒(默认)
  
  超过总超时 → 放弃重试,返回错误给上层

关键参数

参数默认值说明
retryMinInterval10 ms首次重试等待时间
retryStepFactor2退避倍数
retryMaxInterval1000 ms单次重试最大等待时间
maxRetryWaitTime20000 ms总重试超时(可配置,范围 3秒~24小时)
3.2 可重试的错误码

RPC 层只对临时性错误进行重试,永久性错误(如权限不足、SQL 语法错误)直接返回:

错误码含义重试原因
TSDB_CODE_RPC_NETWORK_UNAVAIL网络不可达可能是瞬时网络波动
TSDB_CODE_RPC_BROKEN_LINK连接断开服务端可能重启中
TSDB_CODE_MNODE_NOT_FOUNDMNode 不可达Leader 可能在切换
TSDB_CODE_SYN_NOT_LEADER非 Leader 节点需要切换到新 Leader
TSDB_CODE_SYN_RESTORINGRaft 恢复中等待恢复完成
TSDB_CODE_APP_IS_STARTING服务启动中等待服务就绪
TSDB_CODE_APP_IS_STOPPING服务关闭中切换到其他节点
TSDB_CODE_VND_STOPPEDVNode 已停止可能在迁移中
3.3 不重试的消息类型

以下消息类型不进行 RPC 层重试(由上层自行处理):

  • 查询执行消息(QUERY / MERGE_QUERY
  • 结果获取消息(FETCH / MERGE_FETCH
  • 查询心跳消息
  • 任务通知和任务清理消息

原因:这些消息是有状态的查询操作,简单重试可能导致重复执行或状态不一致。

3.4 EP Set 轮转

当请求发往 MNode 失败时,RPC 层会自动切换到 EP Set 中的下一个地址重试:

EP Set 轮转示例:

  EP Set = [node1:6030, node2:6030, node3:6030]
  当前使用 = node1 (inUse=0)
  
  请求失败 → inUse 前移到 node2 (inUse=1) → 重试
  再次失败 → inUse 前移到 node3 (inUse=2) → 重试
  再次失败 → inUse 回绕到 node1 (inUse=0) → 等待退避后重试

这保证了 MNode Leader 切换时,客户端能自动找到新 Leader。

3.5 快速失败机制

为了避免对已确认故障的节点持续发送请求,RPC 层实现了快速失败:

  • 连续 3 次请求失败(failFastThreshold = 3
  • 5 秒内(failFastInterval = 5000ms
  • → 后续请求直接返回失败,不再尝试连接该节点
  • 超过 5 秒后恢复正常重试

4. 通道隔离

4.1 服务端 — 单端口多队列

TDengine 服务端只监听一个 TCP 端口(默认 6030),但通过消息队列实现不同类型请求的隔离:

服务端消息分发:

  TCP 端口 6030 (所有请求)
        │
        ▼
  消息头解析 → 提取 msgType + vgId
        │
        ├── TDMT_MND_* (mnode 消息)
        │     ├── DDL 操作 → 写队列
        │     ├── SHOW 命令 → 读队列
        │     └── 心跳状态 → 状态队列
        │
        ├── TDMT_VND_* (vnode 消息)
        │     ├── 数据写入 → 写队列(检查磁盘空间)
        │     ├── 子表创建 → 写队列
        │     └── 查询执行 → 查询队列
        │
        ├── TDMT_SCH_* (调度消息)
        │     ├── 查询 → 查询队列(带预处理)
        │     └── 获取结果 → 获取队列
        │
        ├── TDMT_SYNC_* (Raft 消息)
        │     ├── 选举/日志 → 同步队列
        │     └── 心跳 → 同步读队列
        │
        └── TDMT_STREAM_* (流计算消息)
              ├── 普通任务 → 流计算队列
              ├── 控制消息 → 流计算控制队列
              └── 长任务 → 长执行队列
4.2 服务端队列类型
队列用途特点
写队列DDL、数据写入写入前检查磁盘空间
读队列元数据查询、SHOW 命令只读操作,可高并发
查询队列SQL 查询执行请求预处理后入队
获取队列查询结果获取轻量操作
同步队列Raft 选举、日志复制高优先级
同步读队列Raft 心跳高频低延迟
应用队列Raft 提交应用有独立内存限额
流计算队列流任务处理可能长时间执行
流控制队列流管理操作控制面消息
检查点队列流计算状态持久化周期性触发
状态队列DNode 心跳上报MNode 专用
仲裁队列Arbitrator 通信独立隔离
4.3 客户端 — 多 RPC 实例

客户端(包括 dnode 内部通信)使用多个独立的 RPC 实例,分离不同类型的流量:

RPC 实例线程数用途为什么隔离
通用实例numOfRpcThreads / 2dnode 间一般通信默认通道
状态实例1心跳/状态上报到 MNode防止被大量业务消息阻塞,保证心跳不超时
同步实例numOfRpcThreads / 2Raft 日志复制防止 Raft 消息被业务消息饿死

为什么要隔离心跳?

如果心跳和数据写入共用同一个 RPC 实例,当写入量极大时,心跳消息可能被积压在队列中无法及时发送,导致 MNode 误判节点离线。独立的状态 RPC 实例保证心跳消息始终有专用通道。

4.4 客户端(taosc)RPC 实例

用户应用程序通过 taosc 驱动连接时,使用一个独立的 RPC 实例:

参数
线程数numOfRpcThreads
最大会话数1024
连接池上限10~1000(按配置计算)
消息批量发送未启用
连接多路复用shareConnLimit 控制

5. 认证与安全

5.1 用户信息传递

RPC 层使用首次消息携带的方式完成认证:

认证流程:

  客户端                          服务端
    │                              │
    │  首次请求(withUserInfo=1)    │
    │  [消息头][用户名+密码哈希]     │
    │─────────────────────────────→│
    │                              │  提取用户信息
    │                              │  绑定到连接对象
    │                              │  后续请求无需再传
    │                              │
    │  后续请求(withUserInfo=0)    │
    │  [消息头][消息体]             │
    │─────────────────────────────→│
    │                              │  从连接对象获取用户
  • 每个新建的 TCP 连接,第一条消息会附带用户名和密码摘要
  • 服务端验证后将用户信息绑定到该连接
  • 后续消息不再传递用户信息,减少网络开销
5.2 IP 白名单

服务端支持按用户配置 IP 白名单

  • 每次收到请求时,检查发送方 IP 是否在该用户的白名单中
  • 白名单信息从 MNode 同步,带有版本号用于增量更新
  • 不在白名单中的请求返回 TSDB_CODE_IP_NOT_IN_WHITE_LIST
-- 配置 IP 白名单
ALTER USER test_user ADD HOST '192.168.1.0/24';
ALTER USER test_user DROP HOST '10.0.0.0/8';
5.3 版本兼容性校验

每条消息头都携带发送方的兼容版本号(compatibilityVer)。服务端收到请求后:

  • 比对客户端版本与服务端版本
  • 允许最多 3 个版本号的差异
  • 超出范围时返回版本不兼容错误

这确保了滚动升级时,新旧版本节点可以短暂共存通信。

6. 消息压缩

6.1 LZ4 压缩

RPC 层支持对消息体进行 LZ4 压缩,减少网络传输量:

压缩判断逻辑:

  消息体大小 > compressMsgSize?
    ├── 是 → 执行 LZ4 压缩
    │         ├── 压缩后更小 → 使用压缩数据,标记 comp=1
    │         └── 压缩后反而更大 → 保持原始数据
    └── 否 → 不压缩
6.2 压缩配置
compressMsgSize行为
-1(默认)不压缩任何消息
0压缩所有消息
N > 0仅压缩消息体超过 N 字节的消息

配置范围:-1 到 100000000(100MB)。

建议:在跨机房或带宽受限的网络环境中,设置 compressMsgSize = 65536(64KB)可以显著减少大批量写入时的网络流量,但会增加少量 CPU 开销。

7. 流控与背压

7.1 队列内存限额

服务端对消息处理队列实施内存限制,防止请求堆积导致 OOM:

内存限额计算:

  总可用内存 = 系统总内存
  RPC 队列内存 = 总可用内存 × 10% × 60%
  应用队列内存 = 总可用内存 × 10% × 40%
  
  示例(64GB 内存机器):
    RPC 队列上限 ≈ 3.84 GB
    应用队列上限 ≈ 2.56 GB

当队列内存使用超过限额时:

  • 新请求被拒绝,返回 TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE
  • 客户端收到此错误后会进入重试逻辑
  • 相当于 TCP 层面的流控——告知客户端"我处理不过来,请稍后再试"
7.2 连接数限制
限制维度参数默认值说明
服务端最大连接数maxShellConns50000所有客户端连接总数上限
客户端单目标连接数connLimitNum自动计算(10~1000)到同一目标地址的最大连接数
客户端总会话数numOfRpcSessions30000所有目标的连接总数

超过连接数限制时返回 TSDB_CODE_RPC_MAX_SESSIONS

7.3 磁盘空间检查

写队列有额外的前置检查——将消息入队前验证磁盘空间是否充足:

  • 磁盘空间不足时直接拒绝写入请求
  • 返回 TSDB_CODE_NO_ENOUGH_DISKSPACE
  • 避免消息入队后因磁盘满而处理失败
7.4 消息批量发送

dnode 间通信(非客户端)支持消息批量发送——将多条待发送消息合并为一次 TCP 写入:

  • 减少系统调用次数
  • 降低网络开销(TCP 小包问题)
  • 批量大小有上限,防止单次发送过大

8. 请求的完整生命周期

以客户端发送一条写入请求为例:

RPC 请求完整生命周期:

  客户端应用
    │
    │ 1. 调用 API(如 taos_query)
    ▼
  taosc 客户端驱动
    │ 2. 构建消息体(序列化 SQL/数据)
    │ 3. 根据表名 hash 确定目标 VGroup
    │ 4. 从 Catalog 缓存获取 Leader 地址
    ▼
  RPC 客户端层
    │ 5. 选择 RPC 线程(轮转分配)
    │ 6. 从连接池获取/创建 TCP 连接
    │ 7. 填充消息头(msgType, traceId, qid, seq, timestamp, magic)
    │ 8. 压缩判断(消息体 > compressMsgSize?)
    │ 9. 首次连接?附加用户认证信息
    │ 10. uv_write() 发送到网络
    ▼
  网络传输(TCP)
    ▼
  RPC 服务端层
    │ 11. Worker 线程的 uv_loop 收到数据
    │ 12. 解析消息头,校验魔数和版本
    │ 13. 解压缩(如果 comp=1)
    │ 14. 提取用户信息(如果 withUserInfo=1)
    │ 15. IP 白名单检查
    │ 16. 根据 msgType 确定目标队列
    │ 17. 检查队列内存限额
    │ 18. 入队
    ▼
  业务处理层
    │ 19. Worker 从队列取出消息
    │ 20. 执行业务逻辑(写入 WAL、MemTable 等)
    │ 21. 构建响应消息
    ▼
  RPC 服务端层
    │ 22. 填充响应头(code, EP Set 更新等)
    │ 23. uv_write() 发送响应
    ▼
  网络传输(TCP)
    ▼
  RPC 客户端层
    │ 24. 收到响应,通过 seqNum 匹配请求
    │ 25. 检查 code:成功?需要重试?
    │     ├── 成功 → 回调上层
    │     └── 可重试错误 → 指数退避后重发
    │ 26. 归还连接到连接池
    ▼
  taosc 客户端驱动
    │ 27. 解析响应,返回结果给应用
    ▼
  客户端应用

代码示例

配置 RPC 参数

# /etc/taos/taos.cfg

# RPC 线程数(默认 CPU 核数/2)
numOfRpcThreads    4

# 最大会话数
numOfRpcSessions   30000

# 消息压缩阈值(字节,-1=不压缩)
compressMsgSize    65536

# 服务端最大连接数
maxShellConns      50000

# 空闲连接基础超时(秒)
shellActivityTimer 3

# 读超时(秒)
readTimeout        900

# 最大重试等待时间(毫秒)
maxRetryWaitTime   20000

# 连接多路复用上限
shareConnLimit     10

监控 RPC 连接状态

-- 查看当前活跃连接
SHOW CONNECTIONS;

-- 输出示例:
-- connId | user  | program    | pid  | endpoint        | login_time          | last_access
--      1 | root  | taos       | 1234 | 192.168.1.10:56789 | 2024-01-15 10:00:00 | 2024-01-15 10:05:30

-- 查看查询(可间接反映 RPC 活跃度)
SHOW QUERIES;

-- 杀掉特定连接
KILL CONNECTION <connId>;

排查连接问题

# 检查端口是否监听
netstat -tlnp | grep 6030

# 检查 FQDN 解析
ping node1.example.com

# 检查防火墙(6030 是唯一需要开放的端口)
telnet node1.example.com 6030

# 检查 RPC 相关日志(包含 traceId 用于链路追踪)
grep "RPC" /var/log/taos/taosdlog.* | tail -20

跨机房部署的压缩优化

# 场景:客户端和服务端不在同一机房,带宽有限
# 建议开启消息压缩

# 客户端 taos.cfg
compressMsgSize    0    # 压缩所有消息(跨机房场景)

# 或者只压缩大消息(> 64KB)
compressMsgSize    65536

高并发场景的 RPC 调优

# 场景:大量客户端并发连接,每秒数万请求
# 在服务端 taos.cfg 中:

# 增加 RPC 线程数
numOfRpcThreads    8

# 增加最大连接数
maxShellConns      100000

# 增加会话数
numOfRpcSessions   50000

# 场景:客户端到服务端延迟高(如跨地域)
# 在客户端 taos.cfg 中:

# 增加重试等待时间
maxRetryWaitTime   60000

# 增加读超时
readTimeout        1800

# 增加连接多路复用(减少连接数)
shareConnLimit     20

性能考量

RPC 延迟构成

一次 RPC 请求的延迟 = 
    客户端序列化 + 
    TCP 传输(往返) + 
    服务端反序列化 + 
    队列排队等待 + 
    业务处理 + 
    响应序列化 + 
    TCP 传输(返回) + 
    客户端反序列化

典型值(同机房):
    网络往返:0.1~0.5ms
    序列化:< 0.1ms
    队列等待:0~数ms(取决于负载)
    业务处理:视操作而定
    
    总体:简单操作 0.5~2ms,复杂查询取决于执行时间

关键调优参数总结

场景建议调整
高并发连接增加 numOfRpcThreadsmaxShellConns
跨机房/高延迟增加 maxRetryWaitTimereadTimeout、开启压缩
大批量写入增加 shareConnLimit 复用连接
内存紧张减少 numOfRpcSessions,降低连接池规模
频繁超时检查网络、增加 shellActivityTimer

性能瓶颈识别

现象可能原因排查方式
请求延迟突增队列积压查看 TSDB_CODE_OUT_OF_RPC_MEMORY_QUEUE 错误
连接被拒绝达到连接上限查看 TSDB_CODE_RPC_MAX_SESSIONS 错误
频繁重连空闲超时过短增大 shellActivityTimer
写入超时磁盘满查看 TSDB_CODE_NO_ENOUGH_DISKSPACE 错误
偶发失败后恢复正常重试行为检查日志中的 retry 信息

FAQ

Q1: TDengine 使用什么网络协议通信?

TCP。TDengine 的 RPC 层基于 libuv 构建,所有节点间通信(客户端→服务端、dnode→mnode、Raft 复制)都使用 TCP 长连接。不使用 UDP,也不使用 HTTP(HTTP/WebSocket 由 taosAdapter 提供,是另一层封装)。

Q2: 只需要开放一个端口就够了吗?

是的。TDengine v3.x 只使用一个 TCP 端口(默认 6030)。所有类型的消息(写入、查询、心跳、Raft 复制)都通过这一个端口传输,在内部通过消息类型路由到不同的处理队列。

v2.x 时代需要开放多个端口(6030~6042),v3.x 简化为单端口。

Q3: 客户端到服务端的连接会一直保持吗?

不会无限保持。默认情况下,空闲约 5 分钟后连接会被自动关闭。下次请求时会自动重新建立连接。这个行为对应用程序是透明的。

如果需要保持长连接(如实时监控场景),可以增大 shellActivityTimer 参数。

Q4: 网络断开后会自动重连吗?

是的。RPC 层会在发送请求失败时自动重试(指数退避,默认总超时 20 秒)。在此期间如果网络恢复,请求会自动成功。如果超过总超时仍然失败,会返回错误码给应用程序,应用层可以自行决定是否继续重试。

Q5: 为什么 SHOW CONNECTIONS 显示的连接数比客户端数多?

因为客户端和服务端之间可能建立多条 TCP 连接(连接池机制)。此外,dnode 之间的内部通信(心跳、Raft)也会占用连接。每个独立的 TCP 连接都会显示为一行。

Q6: compressMsgSize 设为 0 会影响性能吗?

会有轻微的 CPU 开销(LZ4 压缩/解压)。但对于可压缩性高的数据(如时序数据的批量写入),网络传输减少带来的收益通常远大于 CPU 开销。

建议:

  • 同机房、万兆网络:不压缩(默认 -1
  • 跨机房或带宽受限:设为 065536
  • CPU 瓶颈场景:不压缩

Q7: RPC 超时参数应该如何调整?

场景maxRetryWaitTimereadTimeout
同机房,低延迟20000(默认)900(默认)
跨城市,中等延迟600001800
跨国际,高延迟1200003600
大查询,结果集很大200003600~86400

readTimeout 特别重要——如果查询执行时间超过这个值,连接会被断开。对于复杂的大数据量查询,务必设置足够大的 readTimeout

Q8: traceId 有什么用?如何利用?

traceId 是一个 128 位的标识符,在请求发起时生成,贯穿整个处理链路(客户端 → RPC → 服务端 → 写入/查询)。所有相关日志都会打印 traceId,用于:

  1. 问题排查:根据 traceId 搜索 taosd 日志,追踪一个请求的完整执行路径
  2. 性能分析:对比请求在各阶段的耗时
  3. 关联分析:将客户端错误与服务端日志对应起来
# 根据 traceId 搜索日志
grep "QID:0x<qid_hex>" /var/log/taos/taosdlog.*

参考

第一篇 系统构架

关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TDengine (老段)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值