news 2026/9/14 10:40:01

TDengine 三副本高可用方案:RAFT 一致性原理、集群部署与运维命令详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TDengine 三副本高可用方案:RAFT 一致性原理、集群部署与运维命令详解

TDengine 三副本高可用方案:RAFT 一致性原理、集群部署与运维命令详解

【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine

TDengine 三副本方案基于 RAFT 一致性算法,将元数据与时序数据一并纳入多副本保护,使集群在不超过半数节点故障时仍能持续提供读写服务。本文以三副本方案的部署与运维为主线,完整覆盖集群配置、创建/修改副本的 SQL 命令、Out of dnodesVnodes exhausted等常见报错的成因与解决方案,并结合 Mnode 副本分配源码剖析建库时的资源调度逻辑。读完本文,你将能够独立完成一套 TDengine 三副本高可用集群的搭建,并理解副本数据一致性的底层机制。

一、三副本的一致性模型:基于 RAFT 的 VGroup

TDengine 的三副本方案采用 RAFT 算法来实现数据的一致性,覆盖元数据和时序数据两部分。核心组织单元是虚拟节点组(VGroup):一个 VGroup 构成一个 RAFT 组,VGroup 中的虚拟节点(Vnode)即该 RAFT 组的成员节点,也称作副本。三副本数据库即意味着每个 VGroup 包含 3 个编号相同的 Vnode,分属 3 个不同的物理节点(Dnode)。

从官方文档与源码结构看,该一致性模型包含以下要点:

  1. 角色划分:每个 Vnode 都有自己的角色,可以是 Leader(领导者)、Follower(跟随者)、Candidate(候选人)。Vnode 启动时角色不确定,通过组内节点交换版本号、任期等信息完成选主(详见 架构文档中的主从选择说明)。
  2. 连续日志:每个 Vnode 都维护一份连续的日志,记录数据写入、变更或删除等全部操作指令。日志由一系列有序日志条目组成,每条日志都有唯一编号,用于标识日志协商或执行的进度。
  3. 高可用边界:Leader 角色的 Vnode 提供读写服务,在故障节点不超过半数(三副本中即允许 1 个节点故障)的情况下保证集群高可用。即使发生节点重启及 Leader 重新选举,RAFT 协议也能保证新选出的 Leader 可以提供已经写入成功的全部完整数据的读写服务。
  4. 日志同步:每一次对数据库的变更请求(比如数据写入)都对应一条日志。持续写入过程中,各成员节点上会按协议机制产生完全相同的日志记录,并以相同顺序执行数据变更操作,日志以 WAL 文件形式存储在数据文件目录中。
  5. 提交确认:只有当过半数节点把该条日志追加到 WAL 文件、并且收到确认消息之后,Leader 才认为这条日志是安全的;此时日志进入 committed 状态,完成数据插入,随后被标记为 applied 状态。

完整的写入与复制流程(包括 Leader/Follower 写入路径、同步复制、流水线复制、learner 角色与写请求重定向)可参见 数据写入与复制流程。其中与三副本运维最相关的两点是:

  • 重定向机制:写入请求只有 Leader Vnode 接受,客户端 taosc 维护节点组拓扑缓存,被 follower 拒绝时会自动重定向到 leader,应用层无需关心重试;
  • 成员变更:调整 VGroup 副本数(如单副本改三副本)时,TDengine 扩展了 RAFT 引入 learner 角色——learner 只接收数据复制、不参与投票,数据差距大时先做快照同步,追上后再转为 follower 参与投票。这正是alter database ... replica能在集群运行中无缝调整副本的底层机制。

二、集群配置:三副本的最低部署要求

三副本要求集群至少配置三个服务器节点,基本部署与配置步骤如下:

  1. 确定服务器节点数量、主机名或域名,配置好所有节点的域名解析(DNS 或/etc/hosts);
  2. 各节点分别安装 TDengine 服务端安装包,按需编辑好各节点taos.cfg
  3. 启动各节点taosd服务,其他服务可按需启动(taosAdapter / taosX / taosKeeper / taosExplorer)。

其中在taos.cfg层面值得特别关注的是supportVnodes参数——它决定了单个 Dnode 可承载的 Vnode 上限,直接影响“三副本能否建库成功”。从源码看,该参数在服务端全局配置中定义:

  • tglobal.c#L62 声明了tsNumOfSupportVnodes,启动时按CPU 核数 × 2 + 5计算默认值且最小为 2(tglobal.c#L1011-L1012);
  • tglobal.c#L1061 将其注册为服务端可配置项,取值范围为 0~1024;
  • 各 Dnode 会在状态上报中携带该值(dmHandle.c#L268),Mnode 据此维护每个 Dnode 的numOfSupportVnodes(mndDnode.c#L1312),作为后续副本分配的依据。

也就是说,一个 4 核服务器默认支持 13 个 Vnode。如果建库所需的 VGroup 数(vgroups参数)乘以副本数超过了各节点可用 Vnode 余量,就会触发下文“Vnodes exhausted”报错,可通过调大supportVnodes或增加 CPU 核数来解决。

三、运维命令:创建集群、建库与调整副本数

1. 创建集群

首先将三台服务器节点注册进集群(<dnode_ep>为节点地址,<dnode_port>为通信端口,默认 6030):

CREATE dnode <dnode_ep> port <dnode_port>; CREATE dnode <dnode_ep> port <dnode_port>; CREATE dnode <dnode_ep> port <dnode_port>;

然后创建三副本的 Mnode(集群元数据管理节点),保证 Mnode 自身高可用:

CREATE mnode on dnode <dnode_id>; CREATE mnode on dnode <dnode_id>; CREATE mnode on dnode <dnode_id>;

2. 数据库创建

创建三副本数据库时通过replica参数指定副本数,并可同时指定vgroups(虚拟节点组数)与buffer(单 Vnode 内存)等参数:

create database <dbname> replica 3 vgroups xx buffer xx ...

3. 修改数据库副本数

单副本数据库可升级为三副本,反之亦然,使用alter命令在线完成(底层走上文提到的 learner 成员变更流程,不停写):

alter database <dbname> replica 3|1

四、源码剖析:Mnode 如何为三副本分配 Vnode

建库时 Mnode 需要为每个 VGroup 挑选replica个不同的 Dnode 来放置副本。核心分配逻辑在 mndGetAvailableDnode()(mndVgroup.c),其步骤如下:

  1. 打分排序:按 Dnode 负载得分对候选节点排序,得分公式为(已有 Vnode 数 + 其他节点数 × 0.9) / numOfSupportVnodes(mndGetDnodeScore()),得分低的节点优先被选中,实现副本的均衡分布;
  2. 节点数检查:若在线 Dnode 总数少于replica,返回TSDB_CODE_MND_NO_ENOUGH_DNODES(对应报错Out of dnodes)(mndVgroup.c#L1050-L1053);
  3. Vnode 容量检查:若目标 Dnode 已有 Vnode 数达到numOfSupportVnodes上限,返回TSDB_CODE_MND_NO_ENOUGH_VNODES(对应报错Vnodes exhausted)(mndVgroup.c#L1062-L1064);
  4. 内存检查:扣除本 VGroup 所需内存后,若 Dnode 可用内存不足,返回TSDB_CODE_MND_NO_ENOUGH_MEM_IN_DNODE(mndVgroup.c#L1066-L1073);
  5. 初始角色:分配完成后,单副本 VGroup 的 Vnode 直接标记为 Leader,多副本 VGroup 则全部初始为 Follower,待 Vnode 启动选主后再确定真正的 Leader(mndVgroup.c#L1076-L1080)。

对应的错误码定义见 terror.c#L249 与 terror.c#L364,错误码数值(0x80000334/0x800003BA)可对照 errorCodeTable.ini 查询。

五、常见问题与排查

1. 创建三副本数据库或修改为三副本时,报错:DB error: Out of dnodes

  • 服务器节点数不足:原因是服务器节点数少于三个。从源码看,当在线 Dnode 数量小于目标副本数时,分配函数即返回NO_ENOUGH_DNODES(mndVgroup.c#L1050-L1053);alter database ... replica 3同样受此约束。
  • 解决方案:增加服务器节点数量,满足最低要求(三个在线 Dnode)。

2. 创建三副本数据库或 split vgroup 时,报错:DB error: Vnodes exhausted

  • 服务器可用 Vnodes 不足:原因是某些服务器节点可用 Vnodes 数少于建库或 split vgroup 的需求数。源码中的触发条件是numOfVnodes >= numOfSupportVnodes(mndVgroup.c#L1062-L1064),其中numOfSupportVnodes即各节点上报的supportVnodes配置值。
  • 解决方案:调整服务器 CPU 数量、或在taos.cfg中调大supportVnodes配置参数(取值范围 0~1024,默认约为 CPU 核数 × 2 + 5),使单节点可承载的 Vnode 数满足建库要求,然后重启该节点服务使配置生效。

小结

TDengine 三副本方案的本质是以 VGroup 为 RAFT 组、以 WAL 日志为一致性载体:写入经过半数副本确认(committed)后方可生效(applied),从而在允许单节点故障的前提下保证数据完整与可用。运维落地时的关键路径是——部署不少于 3 个节点并完成域名解析与taos.cfg配置(重点关注supportVnodes),通过CREATE dnode/CREATE mnode搭建集群,用create database ... replica 3建库,必要时用alter database ... replica 3|1在线调整副本数;遇到Out of dnodes应检查在线 Dnode 数,遇到Vnodes exhausted应核对各节点的supportVnodes与已有 Vnode 负载。更深入的复制流程、选主与成员变更细节,可继续阅读 数据写入与复制流程 及 Mnode 副本分配源码。

【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 10:37:47

InstaPy 如何手动指定 geckodriver 二进制路径?

InstaPy 如何手动指定 geckodriver 二进制路径&#xff1f; 【免费下载链接】InstaPy &#x1f4f7; Instagram Bot - Tool for automated Instagram interactions 项目地址: https://gitcode.com/GitHub_Trending/in/InstaPy InstaPy 通过 Selenium 驱动 Firefox 完成自…

作者头像 李华
网站建设 2026/9/14 10:37:27

新能源电力系统调度:鲁棒优化与N-1安全校验实践

1. 项目背景与核心挑战在新能源占比持续攀升的现代电力系统中&#xff0c;调度决策面临着前所未有的复杂性。传统调度方法在高比例可再生能源场景下暴露出三个致命缺陷&#xff1a;面对风电、光伏出力的强随机性时要么过于保守导致经济性损失&#xff0c;要么过于激进带来运行风…

作者头像 李华
网站建设 2026/9/14 10:34:38

区间覆盖贪心模型:从经典问题到跳跃游戏II的解法转换

在贪心算法里&#xff0c;区间覆盖是我最常拿来跟人“安利”的一类问题。它的贪心策略看起来非常直观——每一步都选覆盖到最远处的区间&#xff0c;可真正动手写代码时&#xff0c;很多人会栽在“什么时候计数、什么时候更新边界”这些细节上。今天这篇想聊的&#xff0c;是区…

作者头像 李华
网站建设 2026/9/14 10:33:25

企业级Agent平台:从超级个体到超级团队的协作基座与落地指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 10:29:03

SpringBoot交友平台开发:毕业设计实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华