From 9def1a72e95445f8ef1ede3dcf24fc69aaa1e966 Mon Sep 17 00:00:00 2001 From: leto-bbq Date: Wed, 8 Jul 2026 18:47:27 +0800 Subject: [PATCH] Update V2.0.10 load balance docs --- src/.vuepress/public/img/load-balance-en.png | Bin 0 -> 21896 bytes src/.vuepress/public/img/load-balance.png | Bin 0 -> 25447 bytes src/.vuepress/sidebar/V2.0.x/en-Table.ts | 4 +- src/.vuepress/sidebar/V2.0.x/en-Tree.ts | 4 +- src/.vuepress/sidebar/V2.0.x/zh-Table.ts | 4 +- src/.vuepress/sidebar/V2.0.x/zh-Tree.ts | 4 +- .../Cluster-Deployment_apache.md | 4 +- ...Load-Balance.md => Load-Balance_apache.md} | 393 +++++++--- .../Cluster-Deployment_apache.md | 4 +- .../Tree/User-Manual/Load-Balance_apache.md} | 393 +++++++--- .../Cluster-Deployment_apache.md | 4 +- .../User-Manual/Load-Balance_apache.md} | 391 ++++++++-- .../Cluster-Deployment_apache.md | 4 +- ...Load-Balance.md => Load-Balance_apache.md} | 391 ++++++++-- .../Cluster-Deployment_apache.md | 4 +- .../Master/Table/User-Manual/Load-Balance.md | 462 ------------ .../Table/User-Manual/Load-Balance_apache.md | 703 ++++++++++++++++++ .../Cluster-Deployment_apache.md | 4 +- .../Master/Tree/User-Manual/Load-Balance.md | 463 ------------ .../Tree/User-Manual/Load-Balance_apache.md | 703 ++++++++++++++++++ .../Cluster-Deployment_apache.md | 4 +- .../latest-Table/User-Manual/Load-Balance.md | 462 ------------ .../User-Manual/Load-Balance_apache.md | 703 ++++++++++++++++++ .../Cluster-Deployment_apache.md | 4 +- .../latest/User-Manual/Load-Balance.md | 463 ------------ .../latest/User-Manual/Load-Balance_apache.md | 703 ++++++++++++++++++ 26 files changed, 4076 insertions(+), 2202 deletions(-) create mode 100644 src/.vuepress/public/img/load-balance-en.png create mode 100644 src/.vuepress/public/img/load-balance.png rename src/UserGuide/Master/Table/User-Manual/{Load-Balance.md => Load-Balance_apache.md} (57%) rename src/UserGuide/{latest-Table/User-Manual/Load-Balance.md => Master/Tree/User-Manual/Load-Balance_apache.md} (57%) rename src/UserGuide/{Master/Tree/User-Manual/Load-Balance.md => latest-Table/User-Manual/Load-Balance_apache.md} (57%) rename src/UserGuide/latest/User-Manual/{Load-Balance.md => Load-Balance_apache.md} (57%) delete mode 100644 src/zh/UserGuide/Master/Table/User-Manual/Load-Balance.md create mode 100644 src/zh/UserGuide/Master/Table/User-Manual/Load-Balance_apache.md delete mode 100644 src/zh/UserGuide/Master/Tree/User-Manual/Load-Balance.md create mode 100644 src/zh/UserGuide/Master/Tree/User-Manual/Load-Balance_apache.md delete mode 100644 src/zh/UserGuide/latest-Table/User-Manual/Load-Balance.md create mode 100644 src/zh/UserGuide/latest-Table/User-Manual/Load-Balance_apache.md delete mode 100644 src/zh/UserGuide/latest/User-Manual/Load-Balance.md create mode 100644 src/zh/UserGuide/latest/User-Manual/Load-Balance_apache.md diff --git a/src/.vuepress/public/img/load-balance-en.png b/src/.vuepress/public/img/load-balance-en.png new file mode 100644 index 0000000000000000000000000000000000000000..828b67278075064dd59510cc9c09cb6d1eed7ee6 GIT binary patch literal 21896 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 Sodtx|GddcE@ZuW}0{#Wub}7dI literal 0 HcmV?d00001 diff --git a/src/.vuepress/public/img/load-balance.png b/src/.vuepress/public/img/load-balance.png new file mode 100644 index 0000000000000000000000000000000000000000..78c6dc35842cf534434dd3421370215ed266de85 GIT binary patch literal 25447 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 Qa11m#X(g%34+eq%4JU|+@Bjb+ literal 0 HcmV?d00001 diff --git a/src/.vuepress/sidebar/V2.0.x/en-Table.ts b/src/.vuepress/sidebar/V2.0.x/en-Table.ts index d47f91d65..8686cb3cd 100644 --- a/src/.vuepress/sidebar/V2.0.x/en-Table.ts +++ b/src/.vuepress/sidebar/V2.0.x/en-Table.ts @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -130,7 +130,7 @@ export const enSidebar = { collapsible: true, children: [ { text: 'Query Performance Analysis', link: 'Query-Performance-Analysis' }, - { text: 'Cluster Maintenance', link: 'Load-Balance' }, + { text: 'Cluster Maintenance', link: 'Load-Balance_apache' }, { text: 'Maintenance statement', link: 'Maintenance-commands_apache' }, { text: 'Auto-start On Boot', link: 'Auto-Start-On-Boot_apache' }, ], diff --git a/src/.vuepress/sidebar/V2.0.x/en-Tree.ts b/src/.vuepress/sidebar/V2.0.x/en-Tree.ts index 94661b437..811163053 100644 --- a/src/.vuepress/sidebar/V2.0.x/en-Tree.ts +++ b/src/.vuepress/sidebar/V2.0.x/en-Tree.ts @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -136,7 +136,7 @@ export const enSidebar = { collapsible: true, children: [ { text: 'Query Performance Analysis', link: 'Query-Performance-Analysis' }, - { text: 'Cluster Maintenance', link: 'Load-Balance' }, + { text: 'Cluster Maintenance', link: 'Load-Balance_apache' }, { text: 'Maintenance statement', link: 'Maintenance-commands_apache' }, { text: 'Auto-start On Boot', link: 'Auto-Start-On-Boot_apache' }, ], diff --git a/src/.vuepress/sidebar/V2.0.x/zh-Table.ts b/src/.vuepress/sidebar/V2.0.x/zh-Table.ts index 39b9a51b5..cdeb36a63 100644 --- a/src/.vuepress/sidebar/V2.0.x/zh-Table.ts +++ b/src/.vuepress/sidebar/V2.0.x/zh-Table.ts @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -130,7 +130,7 @@ export const zhSidebar = { collapsible: true, children: [ { text: '查询性能分析', link: 'Query-Performance-Analysis' }, - { text: '集群维护', link: 'Load-Balance' }, + { text: '集群维护', link: 'Load-Balance_apache' }, { text: '运维语句', link: 'Maintenance-statement_apache' }, { text: '开机自启', link: 'Auto-Start-On-Boot_apache' }, ], diff --git a/src/.vuepress/sidebar/V2.0.x/zh-Tree.ts b/src/.vuepress/sidebar/V2.0.x/zh-Tree.ts index f98b2e71a..bf97866ba 100644 --- a/src/.vuepress/sidebar/V2.0.x/zh-Tree.ts +++ b/src/.vuepress/sidebar/V2.0.x/zh-Tree.ts @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -130,7 +130,7 @@ export const zhSidebar = { collapsible: true, children: [ { text: '查询性能分析', link: 'Query-Performance-Analysis' }, - { text: '集群维护', link: 'Load-Balance' }, + { text: '集群维护', link: 'Load-Balance_apache' }, { text: '运维语句', link: 'Maintenance-statement_apache' }, { text: '开机自启', link: 'Auto-Start-On-Boot_apache' }, ], diff --git a/src/UserGuide/Master/Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md b/src/UserGuide/Master/Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md index ab4a84165..8ea2a50ac 100644 --- a/src/UserGuide/Master/Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md +++ b/src/UserGuide/Master/Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md @@ -1,4 +1,4 @@ - -# 集群维护 - -## 1. 集群扩容 - -当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 - -### 1.1 核心概念 - -在执行扩容操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 - -#### 1.1.1 名词汇总 - -| **名词** | **类型** | **解释** | -| ------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------ | -| ConfigNode | 节点角色 | 管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。 | -| DataNode | 节点角色 | 数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。 | -| Database | 元数据 | 数据库,不同数据库的数据物理隔离 | -| DeviceId | 设备名 | 元数据树中从 root 到倒数第二级的全路径表示一个设备名 | -| SeriesSlot | 序列分区槽 | 每个 Database会对应固定个数的序列槽,包含其中序列的元数据。 | -| SeriesTimeSlot | 一个序列槽的一个时间分区槽 | 对应一个 SeriesSlot 内所有序列一个时间分区的数据 | -| SchemaRegion | 一组元数据分区 | 多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。 | -| DataRegion | 一组数据分区 | 多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。 | -| ConfigNodeGroup | 逻辑概念(共识组) | 由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。 | -| SchemaRegionGroup | 逻辑概念(共识组) | 元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份 | -| DataRegionGroup | 逻辑概念(共识组) | 数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。 | - -#### 1.1.2 集群架构 - -IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 - -![](/img/cluster-extention-1.png) - -#### 1.1.3 分区管理 -##### 集群共识组 - -在IoTDB中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 - -![](/img/cluster-extention-2.png) - -##### 分区槽机制 - -在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 - -第一类是​**序列分区槽(SeriesPartitionSlot)**​,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 - -![](/img/cluster-extention-3.png) - -第二类是​**时间分区槽(TimePartitionSlot)**​,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 - -![](/img/cluster-extention-4.png) - -通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 - -### 1.2 实现原理 - -IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 - -默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 - -![](/img/cluster-extention-5.png) - -扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 - -![](/img/cluster-extention-6.png) - -如果希望在扩容后对所有新老数据进行重新均衡,则需要使用数据分区手动迁移功能(简称Region 迁移)。 - -Region迁移语法参考: - -```SQL --- 解释:将哪个RegionId节点的数据从哪个DataNodeId节点迁移到哪个目标DataNodeId节点 - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; -``` - -在迁移过程中,ConfigNode负责整体调度,原 region 和原 DataNode 提供被移除的数据,新 region 和新 DataNode 承担新增数据。 - -![](/img/cluster-extention-7.png) - -如上图由3个DataNode组成的集群中,region 1副本组分布在DataNode 1和DataNode 2中,假设此时想将DataNode 1中的region 1副本迁移至DataNode 3中,其运转流程如下: - -1. 在CLI命令行中执行以下命令: - -```SQL -migrate region 1 from 1 to 3 -``` - -2. 此时Region迁移进入到复制阶段,复制阶段的核心工作是在目标节点中创建新的region副本,将同步全量region 1的数据,此时region状态为Adding。 -3. 此时Region迁移进入到移除阶段,当目标节点中的数据已经全量同步完毕,旧region节点的数据则可以安全删除了,所以此步骤的核心工作是移除旧节点的所有数据,以释放磁盘空间,此时region状态为Removing。 -4. 当2和3步骤执行完毕后,Region迁移工作整体完成。 - -### 1.3 操作步骤 -#### 1.3.1 前置准备 - -1. 服务器环境检查,建议操作系统版本与原集群保持一致。 -2. 数据库版本检查,建议版本与原集群版本保持一致。 -3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 - - ```Shell - #如果命令有输出,则表示该端口已被占用。 - lsof -i:6667 或 netstat -tunp | grep 6667 - lsof -i:10710 或 netstat -tunp | grep 10710 - lsof -i:10720 或 netstat -tunp | grep 10720 - ``` -4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 -5. 软件依赖:安装 Java 运行环境 ,Java 版本 >= 1.8,请确保已设置 jdk 环境变量。 -6. 域名配置:部署时推荐优先使用hostname进行IP配置,可避免后期修改主机ip导致数据库无法启动的问题。设置hostname需要在目标服务器上配置/etc/hosts,如本机ip是192.168.1.3,hostname是iotdb-1,则可以使用以下命令设置服务器的 hostname,并使用hostname配置IoTDB的cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 - -```Shell -# 注意:本机和原集群节点的域名都需要配置 -echo "192.168.1.3 iotdb-1" >> /etc/hosts -``` - -#### 1.3.2 扩容操作 -1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 -2. 解压安装包并进入安装目录 - -```Shell -unzip apache-iotdb-{version}-bin.zip -cd apache-iotdb-{version}-bin -``` - -3. 修改相应配置 - -```Shell -cd apache-iotdb-{version}-bin/conf -vim iotdb-system.properies -``` - -| 配置项 | 说明 | 默认 | 备注 | -| ------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------- | --------------------------------------------------------------------------- | -| **dn\_seed\_config\_node** | **节点注册加入集群时连接的ConfigNode地址,即cn\_internal\_address:cn\_internal\_port** | **127.0.0.1:10710** | **\* 非常重要,强制修改此项,将其改为原集群ConfigNode主节点的地址** | -| dn\_rpc\_address | 客户端 RPC 服务的地址 | 0.0.0.0 | 按需修改,重启服务生效 | -| dn\_rpc\_port | 客户端 RPC 服务的端口 | 6667 | 按需修改,重启服务生效 | -| dn\_internal\_address | DataNode在集群内部通讯使用的地址 | 127.0.0.1 | 按需修改,首次启动后不能修改 | -| dn\_internal\_port | DataNode在集群内部通信使用的端口 | 10730 | 按需修改,首次启动后不能修改 | -| dn\_mpp\_data\_exchange\_port | DataNode用于接收数据流使用的端口 | 10740 | 按需修改,首次启动后不能修改 | -| dn\_data\_region\_consensus\_port | DataNode用于数据副本共识协议通信使用的端口 | 10750 | 按需修改,首次启动后不能修改 | -| dn\_schema\_region\_consensus\_port | DataNode用于元数据副本共识协议通信使用的端口 | 10760 | 按需修改,首次启动后不能修改 | - -4. 启动DataNode节点 - -进入iotdb的sbin目录下,启动datanode: - -```Shell -# Unix/OS X -./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 - -# Windows -# V2.0.4.x 版本之前 -.\sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -.\sbin\windows\start-datanode.bat -``` - -5. 通过CLI命令连接原集群,进行扩容后验证 - -```Shell -# Linux或MACOS系统 - ./apache-iotdb-{version}-bin/sbin/start-cli.sh - - # Windows - # V2.0.4.x 版本之前 - .\apache-iotdb-{version}-bin\sbin\start-cli.bat - - # V2.0.4.x 版本及之后 - .\apache-iotdb-{version}-bin\sbin\windows\start-cli.bat -``` - -6. 执行命令进行验证 - -执行show datanodes命令进行验证,预期结果列表中出现新加入的节点,且节点状态为Running - -```Shell -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -7. 其它节点重复以上操作,值得注意的是,新节点能够成功加入原集群需保证原集群允许加入的DataNode节点数量是足够的。 - -#### 1.3.3 手动负载均衡(按需选择) - -默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,需手动迁移 Region。迁移耗时可估算为:Region 数据量 ÷ 实际数据传输速度。如下图所示,假设将旧节点80TB的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为100 MB/s,迁移约需 3 小时完成。 - -![](/img/cluster-extention-8.png) - -具体操作如下: - -```SQL --- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 -migrate region 1 from 2 to 4 - --- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 -migrate region 2 from 3 to 5 - --- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 -migrate region 3 from 1 to 6 -``` - -迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 - -![](/img/cluster-extention-9.png) - -## 2. 节点管理 - -节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 - -### 2.1 ConfigNode 节点维护 - -ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: - -* 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加2个 ConfigNode,使得集群中有3个 ConfigNode。 -* 集群故障恢复:1个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 - -> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有1或者3个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过3个 ConfigNode 会导致性能损失。 - -#### 2.1.1 添加 ConfigNode 节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-confignode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-confignode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-confignode.bat -``` - -参数介绍: - -| 参数 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -#### 2.1.2 移除 ConfigNode 节点 - -首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: - -```SQL -IoTDB> show confignodes -+------+-------+---------------+------------+--------+ -|NodeID| Status|InternalAddress|InternalPort| Role| -+------+-------+---------------+------------+--------+ -| 0|Running| 127.0.0.1| 10710| Leader| -| 1|Running| 127.0.0.1| 10711|Follower| -| 2|Running| 127.0.0.1| 10712|Follower| -+------+-------+---------------+------------+--------+ -Total line number = 3 -It costs 0.030s -``` - -然后使用 SQL 将 ConfigNode 移除,SQL 命令: - -```Bash -remove confignode [confignode_id] -``` - -### 2.2 DataNode 节点维护 - -DataNode 节点维护有两个常见场景: - -* 集群扩容:出于集群能力扩容等目的,添加新的DataNode进入集群 -* 集群故障恢复:一个DataNode所在机器出现故障,使得该DataNode无法正常运行,此时可以移除该DataNode,并添加新的DataNode进入集群 - -> ❗️注意,为了使集群能正常工作,在DataNode节点维护过程中以及维护完成后,正常运行的DataNode总数不得少于数据副本数(通常为2),也不得少于元数据副本数(通常为3)。 - -#### 2.2.1 添加DataNode节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-datanode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-datanode.bat -``` - -参数介绍: - -| 缩写 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -说明:在添加DataNode后,随着新的写入到来(以及旧数据过期,如果设置了TTL),集群负载会逐渐向新的DataNode均衡,最终在所有节点上达到存算资源的均衡。 - -#### 2.2.2 移除DataNode节点 - -首先通过CLI连接集群,通过`show datanodes`确认想要移除的DataNode的NodeID: - -```SQL -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -然后使用SQL将DataNode移除,SQL命令: - -```Bash -remove datanode [datanode_id] -``` - - -## 3. 负载均衡 - -Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 - -### 3.1 功能介绍 - -IoTDB 是一个分布式数据库,数据的均衡分布对集群的磁盘空间、写入压力的负载均衡有着重要作用,region 是数据在 IoTDB 集群中进行分布式存储的基本单元,具体概念可见[region](../Background-knowledge/Cluster-Concept.md)。 - -集群正常运行情况下,IoTDB 将会自动对数据进行负载均衡,但在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,可通过手动 Region 迁移精细化调整集群负载和运维。 - -下面是一次region迁移过程的示意图: - - -![](/img/region%E8%BF%81%E7%A7%BB%E7%A4%BA%E6%84%8F%E5%9B%BE20241210.png) - -### 3.2 注意事项 - -1. 推荐仅在 IoTDB 1.3.3 以及更高版本使用 Region 迁移功能。 -2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(iotdb-system.properties中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 -3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 -4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 - -### 3.3 使用说明 - -- **语法定义**: - - 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 - - ```SQL - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; - ``` - -- **示例**: - - 将 region 1 从 DataNode 2 迁移至 DataNode 3: - - ```SQL - IoTDB> migrate region 1 from 2 to 3 - Msg: The statement is executed successfully. - ``` - - “The statement is executed successfully” 仅代表region迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 - -- **相关配置项**: - - - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 region 迁移速度。 - -- **耗时估算**: - - 如果迁移过程无并发写入,那么耗时可以简单通过 region 数据量除以数据传输速度来估算。例如对于 1TB 的 region,硬盘网络带宽和限速参数共同决定数据传输速度是 100MB/s,那么需要约 3 小时完成迁移。 - - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1.5来估算。 - -- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,region 所在共识组的状态会经历如下过程: - - 迁移开始前:`Running`,`Running`。 - - - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 - - - 缩容阶段:`Removing`,`Running`,`Running`。 - - - 迁移完成:`Running`,`Running`。 - - 以扩容阶段为例,`show regions`的结果可能为: - - ```Plain - IoTDB> show regions - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| - | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - Total line number = 3 - It costs 0.003s - ``` - -- **阻塞写入**: - - IoTConsensus 的 region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 - - 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: - ```plain - IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" - Msg: The statement is executed successfully. - ``` diff --git a/src/zh/UserGuide/Master/Table/User-Manual/Load-Balance_apache.md b/src/zh/UserGuide/Master/Table/User-Manual/Load-Balance_apache.md new file mode 100644 index 000000000..0580404da --- /dev/null +++ b/src/zh/UserGuide/Master/Table/User-Manual/Load-Balance_apache.md @@ -0,0 +1,703 @@ + + +# 集群维护 + +## 1. 核心概念 + +在进行集群维护操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 + +### 1.1 名词汇总 + +|**名词**|**类型**|**解释**| +|---|---|---| +|ConfigNode|节点角色|管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。| +|DataNode|节点角色|数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。| +|Database|元数据|数据库,不同数据库的数据物理隔离。| +|DeviceId|设备名|元数据树中从 root 到倒数第二级的全路径表示一个设备名。| +|SeriesSlot|序列分区槽|每个 Database 会对应固定个数的序列槽,包含其中序列的元数据。| +|TimeSlot|一个序列槽的一个时间分区槽|对应一个 SeriesSlot 内所有序列一个时间分区的数据。| +|DataPartition|数据分区槽|一个 SeriesSlot 加 一个 TimeSlot 对应一个 DataPartition| +|SchemaRegion|一组元数据分区|多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。| +|DataRegion|一组数据分区|多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。| +|ConfigNodeGroup|逻辑概念(共识组)|由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。| +|SchemaRegionGroup|逻辑概念(共识组)|元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份。| +|DataRegionGroup|逻辑概念(共识组)|数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。| + +### 1.2 集群架构 + +IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 + +![](/img/cluster-extention-1.png) + +### 1.3 分区管理 + +#### 1.3.1 集群共识组 + +在 IoTDB 中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 + +![](/img/cluster-extention-2.png) + +#### 1.3.2 分区槽机制 + +在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 + +第一类是**序列分区槽(SeriesPartitionSlot)**,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 + +![](/img/cluster-extention-3.png) + +第二类是**时间分区槽(TimePartitionSlot)**,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 + +![](/img/cluster-extention-4.png) + +通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 + +## 2. 集群扩容 + +当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 + +### 2.1 实现原理 + +IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 + +默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 + +![](/img/cluster-extention-5.png) + +扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 + +![](/img/cluster-extention-6.png) + +如果希望在扩容后进一步均衡历史数据,可按需执行 Region 迁移或 Region 重均衡:当需要精确指定 Region、源 DataNode 和目标 DataNode 时,可参考【4\. 手动 Region 迁移】;当希望系统自动计算迁移方案并完成整体均衡时,可参考【5\. 自动 Region 重均衡】。 + +### 2.2 操作步骤 + +#### 2.2.1 前置准备 + +1. 服务器环境检查,建议操作系统版本与原集群保持一致。 + +2. 数据库版本检查,建议版本与原集群版本保持一致。 + +3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 + + ```Shell + #如果命令有输出,则表示该端口已被占用。 + lsof -i:6667 或 netstat -tunp | grep 6667 + lsof -i:10710 或 netstat -tunp | grep 10710 + lsof -i:10720 或 netstat -tunp | grep 10720 + ``` + +4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 + +5. 软件依赖:安装 Java 运行环境 ,Java 版本 \>= 1\.8,请确保已设置 jdk 环境变量。 + +6. 域名配置:部署时推荐优先使用 hostname 进行 IP 配置,可避免后期修改主机 IP 导致数据库无法启动的问题。设置 hostname 需要在目标服务器上配置`/etc/hosts`,如本机 IP 是192\.168\.1\.3,hostname 是 iotdb\-1,则可以使用以下命令设置服务器的 hostname,并使用 hostname 配置 IoTDB 的 cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 + +```Shell +# 注意:本机和原集群节点的域名都需要配置 +echo "192.168.1.3 iotdb-1" >> /etc/hosts +``` + +#### 2.2.2 扩容操作 + +1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 + +2. 解压安装包并进入安装目录 + +```Shell +unzip iotdb-{version}-bin.zip +cd iotdb-{version}-bin +``` + +3. 修改相应配置 + +```Shell +cd iotdb-{version}-bin/conf +vim iotdb-system.properies +``` + +|配置项|说明|默认|备注| +|---|---|---|---| +|dn\_seed\_config\_node|节点注册加入集群时连接的 ConfigNode 地址,即 cn\_internal\_address:cn\_internal\_port|127\.0\.0\.1:10710
|非常重要,强制修改此项,将其改为原集群 ConfigNode 主节点的地址
| +|dn\_rpc\_address|客户端 RPC 服务的地址|0\.0\.0\.0|按需修改,重启服务生效| +|dn\_rpc\_port|客户端 RPC 服务的端口|6667|按需修改,重启服务生效| +|dn\_internal\_address|DataNode 在集群内部通讯使用的地址|127\.0\.0\.1|按需修改,首次启动后不能修改| +|dn\_internal\_port|DataNode 在集群内部通信使用的端口|10730|按需修改,首次启动后不能修改| +|dn\_mpp\_data\_exchange\_port|DataNode 用于接收数据流使用的端口|10740|按需修改,首次启动后不能修改| +|dn\_data\_region\_consensus\_port|DataNode 用于数据副本共识协议通信使用的端口|10750|按需修改,首次启动后不能修改| +|dn\_schema\_region\_consensus\_port|DataNode 用于元数据副本共识协议通信使用的端口|10760|按需修改,首次启动后不能修改| + +4. 启动 DataNode 节点 + +进入 IoTDB 的 sbin 目录下,启动 Datanode: + +```Shell +./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 +``` + +5. 通过 CLI 命令连接原集群,进行扩容后验证 + +```Shell +# Linux 或 macOS系统 + ./iotdb-{version}-bin/sbin/start-cli.sh + + # Windows 系统 + ./iotdb-{version}-bin/sbin/start-cli.bat +``` + +6. 执行命令进行验证 + +执行`show datanodes`命令进行验证,预期结果列表中出现新加入的节点,且节点状态为 Running。 + +```Shell +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| +| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 ++------+-------+----------+-------+-------------+---------------+ +Total line number = 4 +It costs 0.110s +``` + +7. 其他节点重复以上操作。新节点能够成功加入原集群的前提是原集群允许加入的 DataNode 节点数量足够,否则需要联系工作人员重新申请激活码信息。 + +#### 2.2.3 手动负载均衡(按需选择) + +默认情况下,扩容后历史数据不会自动迁移。若需进一步均衡各节点的数据分布,可选择以下方式: + +- 手动 Region 迁移:适用于已明确需要迁移的 Region、源 DataNode 和目标 DataNode 的场景,详见【4\. 手动 Region 迁移】。 + +- 自动 Region 重均衡:适用于扩容后希望系统自动选择迁移方案、整体均衡历史数据的场景,详见【5\. 自动 Region 重均衡】。 + +## 3. 节点管理 + +节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 + +### 3.1 ConfigNode 节点维护 + +ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: + +- 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加 2 个 ConfigNode,使得集群中有 3 个 ConfigNode。 + +- 集群故障恢复:1 个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 + +> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有 1 或者 3 个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过 3 个 ConfigNode 会导致性能损失。 +> +> + +#### 3.1.1 添加 ConfigNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-confignode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-confignode.bat + +# V2.0.4.x 版本及之后 +sbin\windows\start-confignode.bat +``` + +参数介绍: + +|参数|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +#### 3.1.2 移除 ConfigNode 节点 + +首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: + +```SQL +IoTDB> show confignodes ++------+-------+---------------+------------+--------+ +|NodeID| Status|InternalAddress|InternalPort| Role| ++------+-------+---------------+------------+--------+ +| 0|Running| 127.0.0.1| 10710| Leader| +| 1|Running| 127.0.0.1| 10711|Follower| +| 2|Running| 127.0.0.1| 10712|Follower| ++------+-------+---------------+------------+--------+ +Total line number = 3 +It costs 0.030s +``` + +然后使用 SQL 将 ConfigNode 移除,SQL 命令: + +```Bash +remove confignode [confignode_id] +``` + +### 3.2 DataNode 节点维护 + +DataNode 节点维护有两个常见场景: + +- 集群扩容:出于集群能力扩容等目的,添加新的 DataNode 进入集群。 + +- 集群故障恢复:一个 DataNode 所在机器出现故障,使得该 DataNode 无法正常运行,此时可以移除该 DataNode,并添加新的 DataNode 进入集群 + +> ❗️注意,为了使集群能正常工作,在 DataNode 节点维护过程中以及维护完成后,正常运行的 DataNode 总数不得少于数据副本数(通常为 2),也不得少于元数据副本数(通常为 3)。 +> +> + +#### 3.2.1 添加 DataNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-datanode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-datanode.bat + +# V2.0.4.x 版本及之后 +tools\windows\start-datanode.bat +``` + +参数介绍: + +|缩写|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +说明:在添加 DataNode 后,随着新的写入到来(以及旧数据过期,如果设置了 TTL),集群负载会逐渐向新的 DataNode 均衡,最终在所有节点上达到存算资源的均衡。 + +#### 3.2.2 移除DataNode节点 + +首先通过 CLI 连接集群,通过`show datanodes`确认想要移除的 DataNode 的 NodeID: + +```SQL +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| ++------+-------+----------+-------+-------------+---------------+ +Total line number = 3 +It costs 0.110s +``` + +然后使用 SQL 将 DataNode 移除,SQL 命令: + +```Bash +remove datanode [datanode_id] +``` + +## 4. 手动 Region 迁移 + +Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +### 4.1 功能介绍 + +IoTDB 是一个分布式数据库,Region 是数据在 IoTDB 集群中进行分布式存储的基本单元。集群正常运行情况下,IoTDB 会自动对新增数据进行负载均衡;在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,支持通过手动 Region 迁移精细化调整集群负载和运维。 + +### 4.2 注意事项 + +1. 推荐仅在 IoTDB 1\.3\.3 以及更高版本使用 Region 迁移功能。 + +2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(`iotdb-system.properties`中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 + +3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 + +4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 + +### 4.3 使用说明 + +- **语法定义**: + + 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 + + ```SQL + migrateRegion + : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL + ; + ``` + +- **语法示例**: + + 将 region 1 从 DataNode 2 迁移至 DataNode 3: + + ```SQL + IoTDB> migrate region 1 from 2 to 3 + Msg: The statement is executed successfully. + ``` + + “The statement is executed successfully” 仅代表 Region 迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 + +- **相关配置项**: + + - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 Region 迁移速度。 + +- **耗时估算**: + + - 如果迁移过程无并发写入,那么耗时可以简单通过 Region 数据量除以数据传输速度来估算。实际数据传输速度由硬盘、网络带宽和迁移限速参数共同决定。 + + - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1\.5来估算。 + +- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,Region 所在共识组的状态会经历如下过程: + + - 迁移开始前:`Running`,`Running`。 + + - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 + + - 缩容阶段:`Removing`,`Running`,`Running`。 + + - 迁移完成:`Running`,`Running`。 + + 以扩容阶段为例,`show regions`的结果可能为: + + ```Plain Text + IoTDB> show regions + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| + | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + Total line number = 6 + It costs 0.003s + ``` + +- **阻塞写入**: + + IoTConsensus 的 Region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 + + 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: + + ```Plain Text + IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" + Msg: The statement is executed successfully. + ``` + +- + +### 4.4 场景示例 + +默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,可手动迁移 Region。如下图所示,假设将旧节点 80 TB 的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为 100 MB/s,迁移约需 3 小时完成。 + +![](/img/cluster-extention-8.png) + +具体操作如下: + +```SQL +-- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 +migrate region 1 from 2 to 4 + +-- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 +migrate region 2 from 3 to 5 + +-- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 +migrate region 3 from 1 to 6 +``` + +迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 + +![](/img/cluster-extention-9.png) + +### 4.5 补充语法(不推荐) + +> **注意:** `EXTEND REGION` 和 `REMOVE REGION` 属于 **高危** 运维指令,不推荐常规使用,生产环境请慎用。一般情况下,Region 迁移应使用 `MIGRATE REGION`;Region 重建应使用 `RECONSTRUCT Region`。 +> +> + +#### 4.5.1 Extend Region + +将一个或多个 Region 扩容到指定 DataNode。 + +- 语法定义: + + ```SQL + extendRegion + : EXTEND REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* TO targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 将 Region 1 扩容到 DataNode 3: + + ```SQL + IoTDB> extend region 1 to 3 + Msg: The statement is executed successfully. + ``` + +#### 4.5.2 Remove Region + +从指定 DataNode 上移除一个或多个 Region 副本。 + +- 语法定义: + + ```SQL + removeRegion + : REMOVE REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* FROM targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 从 DataNode 2 上移除 Region 1: + + ```SQL + IoTDB> remove region 1 from 2 + Msg: The statement is executed successfully. + ``` + +## 5. 自动 Region 重均衡 + +Region 重均衡属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +> V2\.0\.10 起支持 +> +> + +### 5.1 功能介绍 + +Region 重均衡功能支持通过一条 SQL 提交重均衡任务,系统后台使用扩容均衡算法计算 Region 迁移方案,并由 ConfigNode 调度执行。该功能不局限于扩容场景,在未出现扩缩容的情况下,如果存在 Region 大小不均衡、节点间磁盘使用不均衡或写入负载集中在少部分 Region 等情况,也可以使用此功能。 + +`LOAD BALANCE` 本质上是由系统自动生成并执行一组 Region 迁移任务,适合进行整体重均衡;`migrate region` 则适合用户已经明确 RegionId、源 DataNode 和目标 DataNode 的精细化迁移场景。自动重均衡任务提交后,可通过 `SHOW MIGRATIONS` 观察实际生成的迁移任务和执行进度。 + +- 适用场景:扩容后希望历史 Region 自动迁移到新节点;节点间磁盘使用明显不均;部分 DataNode 写入压力较高,需要整体调整 Region 分布。 + +- 谨慎使用场景:业务高峰期、网络或磁盘 I/O 资源紧张时,建议先评估迁移带来的资源占用;如果需要精确控制某个 Region 的迁移路径,建议使用手动 Region 迁移。 + +### 5.2 LOAD BALANCE + +```SQL +-- 触发系统负载均衡(由系统自动选择目标节点) +LOAD BALANCE; + +-- 指定目标 DataNode 节点 ID,并执行负载均衡 +LOAD BALANCE TO DATANODES(*DataNodeId,DataNodeId*); +``` + +- **功能机制** + +向 ConfigNode 提交一个异步执行的全局或局部分布式均衡任务。任务触发后,集群 DataNode 会被划分为两类角色池,且数据物理迁移具备严格单向约束: + +- From 节点(源节点池):提供待迁移 Region 数据的节点 + +- To 节点(目标节点池):接收迁移数据的节点 + +- 单向迁移规则:数据仅允许从 From 节点单向迁移至 To 节点 + +- **参数说明** + +|参数|必填|说明| +|---|---|---| +|TO DATANODES|否|显式传入一个或多个 DataNodeId 列表(逗号分隔),传入的节点被划定为接收数据的 To 节点池,其余节点自动归属为提供数据的 From 节点池| + +- **默认行为** + +|执行方式|行为说明| +|---|---| +|不带参数 \(`LOAD BALANCE`\)|系统默认选择当前磁盘占用量最小的一个节点作为唯一的 To 节点| +|带参数 \(`LOAD BALANCE TO DATANODES(...)`\)|指定的节点被强行划定为接收数据的 To 节点池,其余节点为 From 节点池| + +- **预期结果** + +命令执行后,控制台将立即返回 `Msg: The statement is executed successfully.`。这仅表示 ConfigNode 成功受理了负载均衡任务并将测算生成的子任务编排入列,底层的海量物理迁移随即在后台异步展开。 + +- **配置项说明** + +在配置文件 `iotdb-system.properties` 中,可通过 `region_migration_speed_limit_bytes_per_second` 控制每个 DataNode 的 Region 迁移传输上限,单位为 byte/s,默认值为 `50331648`,约 48 MiB/s。业务繁忙时可适当降低该值,业务低峰期可适当调高;但不建议设置过低,否则迁移耗时会明显增加,甚至可能发生迁移阻塞。配置值小于等于 0 表示不限速;该参数仅对 IoTConsensus 协议生效,支持热加载。 + +### 5.3 SHOW MIGRATIONS + +由于平衡任务涉及数百 GB 级别的大文件跨节点流转,系统提供如下核心观测 SQL 获取具有细粒度状态指示的全局视图。该语句会返回当前集群内部正在执行的后台迁移任务清单,并以结构化列表展示任务状态、耗时和迁移进度。 + +```SQL +SHOW MIGRATIONS +``` + +- **结果集说明** + +|字段名|说明| +|---|---| +|ProcedureId|Procedure 唯一标识| +|RegionId|Region ID| +|Type|Region 类型| +|FromNodeId|源节点 DataNode ID| +|ToNodeId|目标节点 DataNode ID| +|CurrentState|当前状态(如 `REGION_MIGRATE_PREPARE`, `ADD_REGION_PEER`, `REMOVE_REGION_PEER` 等)| +|ProcedureStatus|Procedure 状态(如 RUNNING、FINISHED、FAILED 等)| +|SubmittedTime|任务提交时间| +|LastUpdateTime|最近更新时间| +|Duration|已耗时| +|Progress|迁移进度(已迁移文件数/总文件数)| + +例如: + +```SQL +IoTDB> show migrations ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 11| 5|DataRegion| 2| 3|CHECK_ADD_REGION_PEER| WAITING|2026-06-03T15:47:35.840|2026-06-03T15:47:35.966|31 second 169 ms|files 1/3, size 15.52 KB/15.61 KB| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +Total line number = 1 +It costs 0.004s +``` + +- Show Regions 联动状态观测 + +迁移过程中,相关 Region 的状态也会发生变化。以 2 副本集群为例,在 `SHOW MIGRATIONS` 显示某个任务正在执行时,执行 `show regions` 可观察到该 Region 经历如下状态变化: + +1. 稳态(迁移前): `Running`, `Running`。 + +2. 复制扩容过渡态: `Running`, `Running`, `Adding`(目标 To 节点新建 Region 副本并接收快照,处于 `Adding `状态,该状态不对外提供服务)。 + +3. 安全移除过渡态: `Removing`, `Running`, `Running`(目标节点追平数据变为 `Running`,原 From 节点变为 `Removing`进行删除回收)。 + +4. 新稳态(迁移后): 旧 Region 删除成功,重回 `Running` , `Running` 状态。 + +### 5.4 场景示例 + +以下示例模拟某个真实工业场景:随着业务数据持续增长,系统原有的“两台核心数据节点”配置需要扩展为具有更高吞吐量与存储余量的“三数据节点”架构,并使用双副本冗余(即 1C2D \-\> 1C3D 的平滑扩容)。集群初始为 1 个 ConfigNode 和 2 个 DataNode,新增 DataNode 3 后,通过自动 Region 重均衡让新节点承载部分历史 Region,从而缓解原有节点的存储压力。 + +![](/img/load-balance.png) + +以下 SQL 返回结果仅用于说明关键流程,部分输出为节选展示;实际返回结果会受集群规模、Region 数量、数据库名称、时间分区和节点地址等因素影响,请以实际运行结果为准。 + +1. 扩容前,通过 `show cluster` 查看集群节点,集群中只有 DataNode 1 和 DataNode 2。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +2. 扩容后,通过 `show cluster` 确认 DataNode 3 已加入集群,且状态为 Running。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| +| 3| DataNode|Running| datanode-3| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +3. 执行 `LOAD BALANCE` 提交重均衡任务。该命令提交成功仅表示 ConfigNode 已受理任务。如果希望明确指定新节点作为迁移目标,可使用 `TO DATANODES` 指定目标 DataNodeId。 + +```SQL +IoTDB> LOAD BALANCE; + +-- 或者指定 DataNode 3 作为目标节点 +IoTDB> LOAD BALANCE TO DATANODE 3; +``` + +4. 通过 `show migrations` 观察后台迁移任务。此时控制台可看到正在排队与流转的子任务,例如多个 Region 副本正从 DataNode 1、DataNode 2 迁移至 DataNode 3。 + +```SQL +IoTDB> show migrations ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 101| 3| DataRegion| 1| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.051|2026-06-03T16:29:25.159| 2 second 897 ms|files 8/96, size 24 GB/280 GB | +| 102| 5| DataRegion| 2| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.059|2026-06-03T16:29:25.163| 2 second 889 ms|files 5/72, size 18 GB/210 GB | +| 103| 4|SchemaRegion| 1| 3|CHECK_REMOVE_REGION_PEER| WAITING|2026-06-03T16:29:25.067|2026-06-03T16:29:26.807| 2 second 876 ms| | ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +``` + +4. 迁移过程中,通过 `show regions` 可观察到目标节点上的 Region 进入 `Adding` 状态。此时,DataNode 3 会在本机文件系统中创建对应 Region 的目录;源 DataNode 会将本地持久化 TsFile 打包为快照,并通过跨网络 RPC 投递到 DataNode 3。以下仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion| Adding|root.industry| 8| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.691| Unknown| NaN| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` + +5. 当 DataNode 3 接收完快照,并回放迁移期间产生的 WAL 数据后,新副本进入 `Running` 状态;同时,原节点上的对应 Region 副本会被标记为 `Removing` 并进行删除回收。当 `show migrations` 返回空结果时,表示迁移任务已结束,当前没有正在执行的迁移任务。 + +```SQL +IoTDB> show migrations ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +|ProcedureId|RegionId|Type|FromNodeId|ToNodeId|CurrentState|ProcedureStatus|SubmittedTime|LastUpdateTime|Duration|Progress| ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +``` + +6. 再次查询 `show regions`,确认相关 Region 已迁移至目标节点,并回到 `Running` 状态。如下所示,部分 Region 副本迁移到 DataNode 3 后,DataNode 1、DataNode 2 和 DataNode 3 都继续承载历史 DataRegion。以下仍仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 3| host3| 6667| datanode-3| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 5|DataRegion|Running|root.industry| 6| 1| 1| host1| 6667| datanode-1| Leader|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 5|DataRegion|Running|root.industry| 6| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 7|DataRegion|Running|root.industry| 7| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.717| 240 GB| 3.10| +| 7|DataRegion|Running|root.industry| 7| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.717| 240 GB| 3.10| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` diff --git a/src/zh/UserGuide/Master/Tree/Deployment-and-Maintenance/Cluster-Deployment_apache.md b/src/zh/UserGuide/Master/Tree/Deployment-and-Maintenance/Cluster-Deployment_apache.md index 5070a3620..84a555776 100644 --- a/src/zh/UserGuide/Master/Tree/Deployment-and-Maintenance/Cluster-Deployment_apache.md +++ b/src/zh/UserGuide/Master/Tree/Deployment-and-Maintenance/Cluster-Deployment_apache.md @@ -1,4 +1,4 @@ - -# 集群维护 - -## 1. 集群扩容 - -当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 - -### 1.1 核心概念 - -在执行扩容操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 - -#### 1.1.1 名词汇总 - -| **名词** | **类型** | **解释** | -| ------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------ | -| ConfigNode | 节点角色 | 管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。 | -| DataNode | 节点角色 | 数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。 | -| Database | 元数据 | 数据库,不同数据库的数据物理隔离 | -| DeviceId | 设备名 | 元数据树中从 root 到倒数第二级的全路径表示一个设备名 | -| SeriesSlot | 序列分区槽 | 每个 Database会对应固定个数的序列槽,包含其中序列的元数据。 | -| SeriesTimeSlot | 一个序列槽的一个时间分区槽 | 对应一个 SeriesSlot 内所有序列一个时间分区的数据 | -| SchemaRegion | 一组元数据分区 | 多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。 | -| DataRegion | 一组数据分区 | 多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。 | -| ConfigNodeGroup | 逻辑概念(共识组) | 由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。 | -| SchemaRegionGroup | 逻辑概念(共识组) | 元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份 | -| DataRegionGroup | 逻辑概念(共识组) | 数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。 | - -#### 1.1.2 集群架构 - -IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 - -![](/img/cluster-extention-1.png) - -#### 1.1.3 分区管理 -##### 集群共识组 - -在IoTDB中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 - -![](/img/cluster-extention-2.png) - -##### 分区槽机制 - -在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 - -第一类是​**序列分区槽(SeriesPartitionSlot)**​,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 - -![](/img/cluster-extention-3.png) - -第二类是​**时间分区槽(TimePartitionSlot)**​,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 - -![](/img/cluster-extention-4.png) - -通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 - -### 1.2 实现原理 - -IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 - -默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 - -![](/img/cluster-extention-5.png) - -扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 - -![](/img/cluster-extention-6.png) - -如果希望在扩容后对所有新老数据进行重新均衡,则需要使用数据分区手动迁移功能(简称Region 迁移)。 - -Region迁移语法参考: - -```SQL --- 解释:将哪个RegionId节点的数据从哪个DataNodeId节点迁移到哪个目标DataNodeId节点 - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; -``` - -在迁移过程中,ConfigNode负责整体调度,原 region 和原 DataNode 提供被移除的数据,新 region 和新 DataNode 承担新增数据。 - -![](/img/cluster-extention-7.png) - -如上图由3个DataNode组成的集群中,region 1副本组分布在DataNode 1和DataNode 2中,假设此时想将DataNode 1中的region 1副本迁移至DataNode 3中,其运转流程如下: - -1. 在CLI命令行中执行以下命令: - -```SQL -migrate region 1 from 1 to 3 -``` - -2. 此时Region迁移进入到复制阶段,复制阶段的核心工作是在目标节点中创建新的region副本,将同步全量region 1的数据,此时region状态为Adding。 -3. 此时Region迁移进入到移除阶段,当目标节点中的数据已经全量同步完毕,旧region节点的数据则可以安全删除了,所以此步骤的核心工作是移除旧节点的所有数据,以释放磁盘空间,此时region状态为Removing。 -4. 当2和3步骤执行完毕后,Region迁移工作整体完成。 - -### 1.3 操作步骤 -#### 1.3.1 前置准备 - -1. 服务器环境检查,建议操作系统版本与原集群保持一致。 -2. 数据库版本检查,建议版本与原集群版本保持一致。 -3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 - - ```Shell - #如果命令有输出,则表示该端口已被占用。 - lsof -i:6667 或 netstat -tunp | grep 6667 - lsof -i:10710 或 netstat -tunp | grep 10710 - lsof -i:10720 或 netstat -tunp | grep 10720 - ``` -4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 -5. 软件依赖:安装 Java 运行环境 ,Java 版本 >= 1.8,请确保已设置 jdk 环境变量。 -6. 域名配置:部署时推荐优先使用hostname进行IP配置,可避免后期修改主机ip导致数据库无法启动的问题。设置hostname需要在目标服务器上配置/etc/hosts,如本机ip是192.168.1.3,hostname是iotdb-1,则可以使用以下命令设置服务器的 hostname,并使用hostname配置IoTDB的cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 - -```Shell -# 注意:本机和原集群节点的域名都需要配置 -echo "192.168.1.3 iotdb-1" >> /etc/hosts -``` - -#### 1.3.2 扩容操作 -1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 -2. 解压安装包并进入安装目录 - -```Shell -unzip apache-iotdb-{version}-bin.zip -cd apache-iotdb-{version}-bin -``` - -3. 修改相应配置 - -```Shell -cd apache-iotdb-{version}-bin/conf -vim iotdb-system.properies -``` - -| 配置项 | 说明 | 默认 | 备注 | -| ------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------- | --------------------------------------------------------------------------- | -| **dn\_seed\_config\_node** | **节点注册加入集群时连接的ConfigNode地址,即cn\_internal\_address:cn\_internal\_port** | **127.0.0.1:10710** | **\* 非常重要,强制修改此项,将其改为原集群ConfigNode主节点的地址** | -| dn\_rpc\_address | 客户端 RPC 服务的地址 | 0.0.0.0 | 按需修改,重启服务生效 | -| dn\_rpc\_port | 客户端 RPC 服务的端口 | 6667 | 按需修改,重启服务生效 | -| dn\_internal\_address | DataNode在集群内部通讯使用的地址 | 127.0.0.1 | 按需修改,首次启动后不能修改 | -| dn\_internal\_port | DataNode在集群内部通信使用的端口 | 10730 | 按需修改,首次启动后不能修改 | -| dn\_mpp\_data\_exchange\_port | DataNode用于接收数据流使用的端口 | 10740 | 按需修改,首次启动后不能修改 | -| dn\_data\_region\_consensus\_port | DataNode用于数据副本共识协议通信使用的端口 | 10750 | 按需修改,首次启动后不能修改 | -| dn\_schema\_region\_consensus\_port | DataNode用于元数据副本共识协议通信使用的端口 | 10760 | 按需修改,首次启动后不能修改 | - -4. 启动DataNode节点 - -进入iotdb的sbin目录下,启动datanode: - -```Shell -# Unix/OS X -./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 - -# Windows -# V2.0.4.x 版本之前 -.\sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -.\sbin\windows\start-datanode.bat -``` - -5. 通过CLI命令连接原集群,进行扩容后验证 - -```Shell -# Linux或MACOS系统 - ./apache-iotdb-{version}-bin/sbin/start-cli.sh - - # Windows - # V2.0.4.x 版本之前 - .\apache-iotdb-{version}-bin\sbin\start-cli.bat - - # V2.0.4.x 版本及之后 - .\apache-iotdb-{version}-bin\sbin\windows\start-cli.bat -``` - -6. 执行命令进行验证 - -执行show datanodes命令进行验证,预期结果列表中出现新加入的节点,且节点状态为Running - -```Shell -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -7. 其它节点重复以上操作,值得注意的是,新节点能够成功加入原集群需保证原集群允许加入的DataNode节点数量是足够的。 - -#### 1.3.3 手动负载均衡(按需选择) - -默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,需手动迁移 Region。迁移耗时可估算为:Region 数据量 ÷ 实际数据传输速度。如下图所示,假设将旧节点80TB的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为100 MB/s,迁移约需 3 小时完成。 - -![](/img/cluster-extention-8.png) - -具体操作如下: - -```SQL --- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 -migrate region 1 from 2 to 4 - --- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 -migrate region 2 from 3 to 5 - --- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 -migrate region 3 from 1 to 6 -``` - -迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 - -![](/img/cluster-extention-9.png) - - -## 2. 节点管理 - -节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 - -### 2.1 ConfigNode 节点维护 - -ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: - -* 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加2个 ConfigNode,使得集群中有3个 ConfigNode。 -* 集群故障恢复:1个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 - -> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有1或者3个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过3个 ConfigNode 会导致性能损失。 - -#### 2.1.1 添加 ConfigNode 节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-confignode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-confignode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-confignode.bat -``` - -参数介绍: - -| 参数 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -#### 2.1.2 移除 ConfigNode 节点 - -首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: - -```SQL -IoTDB> show confignodes -+------+-------+---------------+------------+--------+ -|NodeID| Status|InternalAddress|InternalPort| Role| -+------+-------+---------------+------------+--------+ -| 0|Running| 127.0.0.1| 10710| Leader| -| 1|Running| 127.0.0.1| 10711|Follower| -| 2|Running| 127.0.0.1| 10712|Follower| -+------+-------+---------------+------------+--------+ -Total line number = 3 -It costs 0.030s -``` - -然后使用 SQL 将 ConfigNode 移除,SQL 命令: - -```Bash -remove confignode [confignode_id] -``` - -### 2.2 DataNode 节点维护 - -DataNode 节点维护有两个常见场景: - -* 集群扩容:出于集群能力扩容等目的,添加新的DataNode进入集群 -* 集群故障恢复:一个DataNode所在机器出现故障,使得该DataNode无法正常运行,此时可以移除该DataNode,并添加新的DataNode进入集群 - -> ❗️注意,为了使集群能正常工作,在DataNode节点维护过程中以及维护完成后,正常运行的DataNode总数不得少于数据副本数(通常为2),也不得少于元数据副本数(通常为3)。 - -#### 2.2.1 添加DataNode节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-datanode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-datanode.bat -``` - -参数介绍: - -| 缩写 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -说明:在添加DataNode后,随着新的写入到来(以及旧数据过期,如果设置了TTL),集群负载会逐渐向新的DataNode均衡,最终在所有节点上达到存算资源的均衡。 - -#### 2.2.2 移除DataNode节点 - -首先通过CLI连接集群,通过`show datanodes`确认想要移除的DataNode的NodeID: - -```SQL -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -然后使用SQL将DataNode移除,SQL命令: - -```Bash -remove datanode [datanode_id] -``` - - -## 3. 负载均衡 - -Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 - -### 3.1 功能介绍 - -IoTDB 是一个分布式数据库,数据的均衡分布对集群的磁盘空间、写入压力的负载均衡有着重要作用,region 是数据在 IoTDB 集群中进行分布式存储的基本单元,具体概念可见[region](../Background-knowledge/Cluster-Concept.md)。 - -集群正常运行情况下,IoTDB 将会自动对数据进行负载均衡,但在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,可通过手动 Region 迁移精细化调整集群负载和运维。 - -下面是一次region迁移过程的示意图: - - -![](/img/region%E8%BF%81%E7%A7%BB%E7%A4%BA%E6%84%8F%E5%9B%BE20241210.png) - -### 3.2 注意事项 - -1. 推荐仅在 IoTDB 1.3.3 以及更高版本使用 Region 迁移功能。 -2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(iotdb-system.properties中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 -3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 -4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 - -### 3.3 使用说明 - -- **语法定义**: - - 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 - - ```SQL - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; - ``` - -- **示例**: - - 将 region 1 从 DataNode 2 迁移至 DataNode 3: - - ```SQL - IoTDB> migrate region 1 from 2 to 3 - Msg: The statement is executed successfully. - ``` - - “The statement is executed successfully” 仅代表region迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 - -- **相关配置项**: - - - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 region 迁移速度。 - -- **耗时估算**: - - 如果迁移过程无并发写入,那么耗时可以简单通过 region 数据量除以数据传输速度来估算。例如对于 1TB 的 region,硬盘网络带宽和限速参数共同决定数据传输速度是 100MB/s,那么需要约 3 小时完成迁移。 - - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1.5来估算。 - -- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,region 所在共识组的状态会经历如下过程: - - 迁移开始前:`Running`,`Running`。 - - - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 - - - 缩容阶段:`Removing`,`Running`,`Running`。 - - - 迁移完成:`Running`,`Running`。 - - 以扩容阶段为例,`show regions`的结果可能为: - - ```Plain - IoTDB> show regions - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| - | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - Total line number = 3 - It costs 0.003s - ``` - -- **阻塞写入**: - - IoTConsensus 的 region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 - - 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: - ```plain - IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" - Msg: The statement is executed successfully. - ``` diff --git a/src/zh/UserGuide/Master/Tree/User-Manual/Load-Balance_apache.md b/src/zh/UserGuide/Master/Tree/User-Manual/Load-Balance_apache.md new file mode 100644 index 000000000..0580404da --- /dev/null +++ b/src/zh/UserGuide/Master/Tree/User-Manual/Load-Balance_apache.md @@ -0,0 +1,703 @@ + + +# 集群维护 + +## 1. 核心概念 + +在进行集群维护操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 + +### 1.1 名词汇总 + +|**名词**|**类型**|**解释**| +|---|---|---| +|ConfigNode|节点角色|管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。| +|DataNode|节点角色|数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。| +|Database|元数据|数据库,不同数据库的数据物理隔离。| +|DeviceId|设备名|元数据树中从 root 到倒数第二级的全路径表示一个设备名。| +|SeriesSlot|序列分区槽|每个 Database 会对应固定个数的序列槽,包含其中序列的元数据。| +|TimeSlot|一个序列槽的一个时间分区槽|对应一个 SeriesSlot 内所有序列一个时间分区的数据。| +|DataPartition|数据分区槽|一个 SeriesSlot 加 一个 TimeSlot 对应一个 DataPartition| +|SchemaRegion|一组元数据分区|多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。| +|DataRegion|一组数据分区|多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。| +|ConfigNodeGroup|逻辑概念(共识组)|由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。| +|SchemaRegionGroup|逻辑概念(共识组)|元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份。| +|DataRegionGroup|逻辑概念(共识组)|数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。| + +### 1.2 集群架构 + +IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 + +![](/img/cluster-extention-1.png) + +### 1.3 分区管理 + +#### 1.3.1 集群共识组 + +在 IoTDB 中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 + +![](/img/cluster-extention-2.png) + +#### 1.3.2 分区槽机制 + +在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 + +第一类是**序列分区槽(SeriesPartitionSlot)**,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 + +![](/img/cluster-extention-3.png) + +第二类是**时间分区槽(TimePartitionSlot)**,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 + +![](/img/cluster-extention-4.png) + +通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 + +## 2. 集群扩容 + +当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 + +### 2.1 实现原理 + +IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 + +默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 + +![](/img/cluster-extention-5.png) + +扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 + +![](/img/cluster-extention-6.png) + +如果希望在扩容后进一步均衡历史数据,可按需执行 Region 迁移或 Region 重均衡:当需要精确指定 Region、源 DataNode 和目标 DataNode 时,可参考【4\. 手动 Region 迁移】;当希望系统自动计算迁移方案并完成整体均衡时,可参考【5\. 自动 Region 重均衡】。 + +### 2.2 操作步骤 + +#### 2.2.1 前置准备 + +1. 服务器环境检查,建议操作系统版本与原集群保持一致。 + +2. 数据库版本检查,建议版本与原集群版本保持一致。 + +3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 + + ```Shell + #如果命令有输出,则表示该端口已被占用。 + lsof -i:6667 或 netstat -tunp | grep 6667 + lsof -i:10710 或 netstat -tunp | grep 10710 + lsof -i:10720 或 netstat -tunp | grep 10720 + ``` + +4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 + +5. 软件依赖:安装 Java 运行环境 ,Java 版本 \>= 1\.8,请确保已设置 jdk 环境变量。 + +6. 域名配置:部署时推荐优先使用 hostname 进行 IP 配置,可避免后期修改主机 IP 导致数据库无法启动的问题。设置 hostname 需要在目标服务器上配置`/etc/hosts`,如本机 IP 是192\.168\.1\.3,hostname 是 iotdb\-1,则可以使用以下命令设置服务器的 hostname,并使用 hostname 配置 IoTDB 的 cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 + +```Shell +# 注意:本机和原集群节点的域名都需要配置 +echo "192.168.1.3 iotdb-1" >> /etc/hosts +``` + +#### 2.2.2 扩容操作 + +1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 + +2. 解压安装包并进入安装目录 + +```Shell +unzip iotdb-{version}-bin.zip +cd iotdb-{version}-bin +``` + +3. 修改相应配置 + +```Shell +cd iotdb-{version}-bin/conf +vim iotdb-system.properies +``` + +|配置项|说明|默认|备注| +|---|---|---|---| +|dn\_seed\_config\_node|节点注册加入集群时连接的 ConfigNode 地址,即 cn\_internal\_address:cn\_internal\_port|127\.0\.0\.1:10710
|非常重要,强制修改此项,将其改为原集群 ConfigNode 主节点的地址
| +|dn\_rpc\_address|客户端 RPC 服务的地址|0\.0\.0\.0|按需修改,重启服务生效| +|dn\_rpc\_port|客户端 RPC 服务的端口|6667|按需修改,重启服务生效| +|dn\_internal\_address|DataNode 在集群内部通讯使用的地址|127\.0\.0\.1|按需修改,首次启动后不能修改| +|dn\_internal\_port|DataNode 在集群内部通信使用的端口|10730|按需修改,首次启动后不能修改| +|dn\_mpp\_data\_exchange\_port|DataNode 用于接收数据流使用的端口|10740|按需修改,首次启动后不能修改| +|dn\_data\_region\_consensus\_port|DataNode 用于数据副本共识协议通信使用的端口|10750|按需修改,首次启动后不能修改| +|dn\_schema\_region\_consensus\_port|DataNode 用于元数据副本共识协议通信使用的端口|10760|按需修改,首次启动后不能修改| + +4. 启动 DataNode 节点 + +进入 IoTDB 的 sbin 目录下,启动 Datanode: + +```Shell +./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 +``` + +5. 通过 CLI 命令连接原集群,进行扩容后验证 + +```Shell +# Linux 或 macOS系统 + ./iotdb-{version}-bin/sbin/start-cli.sh + + # Windows 系统 + ./iotdb-{version}-bin/sbin/start-cli.bat +``` + +6. 执行命令进行验证 + +执行`show datanodes`命令进行验证,预期结果列表中出现新加入的节点,且节点状态为 Running。 + +```Shell +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| +| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 ++------+-------+----------+-------+-------------+---------------+ +Total line number = 4 +It costs 0.110s +``` + +7. 其他节点重复以上操作。新节点能够成功加入原集群的前提是原集群允许加入的 DataNode 节点数量足够,否则需要联系工作人员重新申请激活码信息。 + +#### 2.2.3 手动负载均衡(按需选择) + +默认情况下,扩容后历史数据不会自动迁移。若需进一步均衡各节点的数据分布,可选择以下方式: + +- 手动 Region 迁移:适用于已明确需要迁移的 Region、源 DataNode 和目标 DataNode 的场景,详见【4\. 手动 Region 迁移】。 + +- 自动 Region 重均衡:适用于扩容后希望系统自动选择迁移方案、整体均衡历史数据的场景,详见【5\. 自动 Region 重均衡】。 + +## 3. 节点管理 + +节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 + +### 3.1 ConfigNode 节点维护 + +ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: + +- 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加 2 个 ConfigNode,使得集群中有 3 个 ConfigNode。 + +- 集群故障恢复:1 个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 + +> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有 1 或者 3 个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过 3 个 ConfigNode 会导致性能损失。 +> +> + +#### 3.1.1 添加 ConfigNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-confignode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-confignode.bat + +# V2.0.4.x 版本及之后 +sbin\windows\start-confignode.bat +``` + +参数介绍: + +|参数|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +#### 3.1.2 移除 ConfigNode 节点 + +首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: + +```SQL +IoTDB> show confignodes ++------+-------+---------------+------------+--------+ +|NodeID| Status|InternalAddress|InternalPort| Role| ++------+-------+---------------+------------+--------+ +| 0|Running| 127.0.0.1| 10710| Leader| +| 1|Running| 127.0.0.1| 10711|Follower| +| 2|Running| 127.0.0.1| 10712|Follower| ++------+-------+---------------+------------+--------+ +Total line number = 3 +It costs 0.030s +``` + +然后使用 SQL 将 ConfigNode 移除,SQL 命令: + +```Bash +remove confignode [confignode_id] +``` + +### 3.2 DataNode 节点维护 + +DataNode 节点维护有两个常见场景: + +- 集群扩容:出于集群能力扩容等目的,添加新的 DataNode 进入集群。 + +- 集群故障恢复:一个 DataNode 所在机器出现故障,使得该 DataNode 无法正常运行,此时可以移除该 DataNode,并添加新的 DataNode 进入集群 + +> ❗️注意,为了使集群能正常工作,在 DataNode 节点维护过程中以及维护完成后,正常运行的 DataNode 总数不得少于数据副本数(通常为 2),也不得少于元数据副本数(通常为 3)。 +> +> + +#### 3.2.1 添加 DataNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-datanode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-datanode.bat + +# V2.0.4.x 版本及之后 +tools\windows\start-datanode.bat +``` + +参数介绍: + +|缩写|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +说明:在添加 DataNode 后,随着新的写入到来(以及旧数据过期,如果设置了 TTL),集群负载会逐渐向新的 DataNode 均衡,最终在所有节点上达到存算资源的均衡。 + +#### 3.2.2 移除DataNode节点 + +首先通过 CLI 连接集群,通过`show datanodes`确认想要移除的 DataNode 的 NodeID: + +```SQL +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| ++------+-------+----------+-------+-------------+---------------+ +Total line number = 3 +It costs 0.110s +``` + +然后使用 SQL 将 DataNode 移除,SQL 命令: + +```Bash +remove datanode [datanode_id] +``` + +## 4. 手动 Region 迁移 + +Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +### 4.1 功能介绍 + +IoTDB 是一个分布式数据库,Region 是数据在 IoTDB 集群中进行分布式存储的基本单元。集群正常运行情况下,IoTDB 会自动对新增数据进行负载均衡;在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,支持通过手动 Region 迁移精细化调整集群负载和运维。 + +### 4.2 注意事项 + +1. 推荐仅在 IoTDB 1\.3\.3 以及更高版本使用 Region 迁移功能。 + +2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(`iotdb-system.properties`中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 + +3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 + +4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 + +### 4.3 使用说明 + +- **语法定义**: + + 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 + + ```SQL + migrateRegion + : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL + ; + ``` + +- **语法示例**: + + 将 region 1 从 DataNode 2 迁移至 DataNode 3: + + ```SQL + IoTDB> migrate region 1 from 2 to 3 + Msg: The statement is executed successfully. + ``` + + “The statement is executed successfully” 仅代表 Region 迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 + +- **相关配置项**: + + - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 Region 迁移速度。 + +- **耗时估算**: + + - 如果迁移过程无并发写入,那么耗时可以简单通过 Region 数据量除以数据传输速度来估算。实际数据传输速度由硬盘、网络带宽和迁移限速参数共同决定。 + + - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1\.5来估算。 + +- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,Region 所在共识组的状态会经历如下过程: + + - 迁移开始前:`Running`,`Running`。 + + - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 + + - 缩容阶段:`Removing`,`Running`,`Running`。 + + - 迁移完成:`Running`,`Running`。 + + 以扩容阶段为例,`show regions`的结果可能为: + + ```Plain Text + IoTDB> show regions + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| + | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + Total line number = 6 + It costs 0.003s + ``` + +- **阻塞写入**: + + IoTConsensus 的 Region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 + + 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: + + ```Plain Text + IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" + Msg: The statement is executed successfully. + ``` + +- + +### 4.4 场景示例 + +默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,可手动迁移 Region。如下图所示,假设将旧节点 80 TB 的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为 100 MB/s,迁移约需 3 小时完成。 + +![](/img/cluster-extention-8.png) + +具体操作如下: + +```SQL +-- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 +migrate region 1 from 2 to 4 + +-- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 +migrate region 2 from 3 to 5 + +-- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 +migrate region 3 from 1 to 6 +``` + +迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 + +![](/img/cluster-extention-9.png) + +### 4.5 补充语法(不推荐) + +> **注意:** `EXTEND REGION` 和 `REMOVE REGION` 属于 **高危** 运维指令,不推荐常规使用,生产环境请慎用。一般情况下,Region 迁移应使用 `MIGRATE REGION`;Region 重建应使用 `RECONSTRUCT Region`。 +> +> + +#### 4.5.1 Extend Region + +将一个或多个 Region 扩容到指定 DataNode。 + +- 语法定义: + + ```SQL + extendRegion + : EXTEND REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* TO targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 将 Region 1 扩容到 DataNode 3: + + ```SQL + IoTDB> extend region 1 to 3 + Msg: The statement is executed successfully. + ``` + +#### 4.5.2 Remove Region + +从指定 DataNode 上移除一个或多个 Region 副本。 + +- 语法定义: + + ```SQL + removeRegion + : REMOVE REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* FROM targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 从 DataNode 2 上移除 Region 1: + + ```SQL + IoTDB> remove region 1 from 2 + Msg: The statement is executed successfully. + ``` + +## 5. 自动 Region 重均衡 + +Region 重均衡属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +> V2\.0\.10 起支持 +> +> + +### 5.1 功能介绍 + +Region 重均衡功能支持通过一条 SQL 提交重均衡任务,系统后台使用扩容均衡算法计算 Region 迁移方案,并由 ConfigNode 调度执行。该功能不局限于扩容场景,在未出现扩缩容的情况下,如果存在 Region 大小不均衡、节点间磁盘使用不均衡或写入负载集中在少部分 Region 等情况,也可以使用此功能。 + +`LOAD BALANCE` 本质上是由系统自动生成并执行一组 Region 迁移任务,适合进行整体重均衡;`migrate region` 则适合用户已经明确 RegionId、源 DataNode 和目标 DataNode 的精细化迁移场景。自动重均衡任务提交后,可通过 `SHOW MIGRATIONS` 观察实际生成的迁移任务和执行进度。 + +- 适用场景:扩容后希望历史 Region 自动迁移到新节点;节点间磁盘使用明显不均;部分 DataNode 写入压力较高,需要整体调整 Region 分布。 + +- 谨慎使用场景:业务高峰期、网络或磁盘 I/O 资源紧张时,建议先评估迁移带来的资源占用;如果需要精确控制某个 Region 的迁移路径,建议使用手动 Region 迁移。 + +### 5.2 LOAD BALANCE + +```SQL +-- 触发系统负载均衡(由系统自动选择目标节点) +LOAD BALANCE; + +-- 指定目标 DataNode 节点 ID,并执行负载均衡 +LOAD BALANCE TO DATANODES(*DataNodeId,DataNodeId*); +``` + +- **功能机制** + +向 ConfigNode 提交一个异步执行的全局或局部分布式均衡任务。任务触发后,集群 DataNode 会被划分为两类角色池,且数据物理迁移具备严格单向约束: + +- From 节点(源节点池):提供待迁移 Region 数据的节点 + +- To 节点(目标节点池):接收迁移数据的节点 + +- 单向迁移规则:数据仅允许从 From 节点单向迁移至 To 节点 + +- **参数说明** + +|参数|必填|说明| +|---|---|---| +|TO DATANODES|否|显式传入一个或多个 DataNodeId 列表(逗号分隔),传入的节点被划定为接收数据的 To 节点池,其余节点自动归属为提供数据的 From 节点池| + +- **默认行为** + +|执行方式|行为说明| +|---|---| +|不带参数 \(`LOAD BALANCE`\)|系统默认选择当前磁盘占用量最小的一个节点作为唯一的 To 节点| +|带参数 \(`LOAD BALANCE TO DATANODES(...)`\)|指定的节点被强行划定为接收数据的 To 节点池,其余节点为 From 节点池| + +- **预期结果** + +命令执行后,控制台将立即返回 `Msg: The statement is executed successfully.`。这仅表示 ConfigNode 成功受理了负载均衡任务并将测算生成的子任务编排入列,底层的海量物理迁移随即在后台异步展开。 + +- **配置项说明** + +在配置文件 `iotdb-system.properties` 中,可通过 `region_migration_speed_limit_bytes_per_second` 控制每个 DataNode 的 Region 迁移传输上限,单位为 byte/s,默认值为 `50331648`,约 48 MiB/s。业务繁忙时可适当降低该值,业务低峰期可适当调高;但不建议设置过低,否则迁移耗时会明显增加,甚至可能发生迁移阻塞。配置值小于等于 0 表示不限速;该参数仅对 IoTConsensus 协议生效,支持热加载。 + +### 5.3 SHOW MIGRATIONS + +由于平衡任务涉及数百 GB 级别的大文件跨节点流转,系统提供如下核心观测 SQL 获取具有细粒度状态指示的全局视图。该语句会返回当前集群内部正在执行的后台迁移任务清单,并以结构化列表展示任务状态、耗时和迁移进度。 + +```SQL +SHOW MIGRATIONS +``` + +- **结果集说明** + +|字段名|说明| +|---|---| +|ProcedureId|Procedure 唯一标识| +|RegionId|Region ID| +|Type|Region 类型| +|FromNodeId|源节点 DataNode ID| +|ToNodeId|目标节点 DataNode ID| +|CurrentState|当前状态(如 `REGION_MIGRATE_PREPARE`, `ADD_REGION_PEER`, `REMOVE_REGION_PEER` 等)| +|ProcedureStatus|Procedure 状态(如 RUNNING、FINISHED、FAILED 等)| +|SubmittedTime|任务提交时间| +|LastUpdateTime|最近更新时间| +|Duration|已耗时| +|Progress|迁移进度(已迁移文件数/总文件数)| + +例如: + +```SQL +IoTDB> show migrations ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 11| 5|DataRegion| 2| 3|CHECK_ADD_REGION_PEER| WAITING|2026-06-03T15:47:35.840|2026-06-03T15:47:35.966|31 second 169 ms|files 1/3, size 15.52 KB/15.61 KB| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +Total line number = 1 +It costs 0.004s +``` + +- Show Regions 联动状态观测 + +迁移过程中,相关 Region 的状态也会发生变化。以 2 副本集群为例,在 `SHOW MIGRATIONS` 显示某个任务正在执行时,执行 `show regions` 可观察到该 Region 经历如下状态变化: + +1. 稳态(迁移前): `Running`, `Running`。 + +2. 复制扩容过渡态: `Running`, `Running`, `Adding`(目标 To 节点新建 Region 副本并接收快照,处于 `Adding `状态,该状态不对外提供服务)。 + +3. 安全移除过渡态: `Removing`, `Running`, `Running`(目标节点追平数据变为 `Running`,原 From 节点变为 `Removing`进行删除回收)。 + +4. 新稳态(迁移后): 旧 Region 删除成功,重回 `Running` , `Running` 状态。 + +### 5.4 场景示例 + +以下示例模拟某个真实工业场景:随着业务数据持续增长,系统原有的“两台核心数据节点”配置需要扩展为具有更高吞吐量与存储余量的“三数据节点”架构,并使用双副本冗余(即 1C2D \-\> 1C3D 的平滑扩容)。集群初始为 1 个 ConfigNode 和 2 个 DataNode,新增 DataNode 3 后,通过自动 Region 重均衡让新节点承载部分历史 Region,从而缓解原有节点的存储压力。 + +![](/img/load-balance.png) + +以下 SQL 返回结果仅用于说明关键流程,部分输出为节选展示;实际返回结果会受集群规模、Region 数量、数据库名称、时间分区和节点地址等因素影响,请以实际运行结果为准。 + +1. 扩容前,通过 `show cluster` 查看集群节点,集群中只有 DataNode 1 和 DataNode 2。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +2. 扩容后,通过 `show cluster` 确认 DataNode 3 已加入集群,且状态为 Running。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| +| 3| DataNode|Running| datanode-3| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +3. 执行 `LOAD BALANCE` 提交重均衡任务。该命令提交成功仅表示 ConfigNode 已受理任务。如果希望明确指定新节点作为迁移目标,可使用 `TO DATANODES` 指定目标 DataNodeId。 + +```SQL +IoTDB> LOAD BALANCE; + +-- 或者指定 DataNode 3 作为目标节点 +IoTDB> LOAD BALANCE TO DATANODE 3; +``` + +4. 通过 `show migrations` 观察后台迁移任务。此时控制台可看到正在排队与流转的子任务,例如多个 Region 副本正从 DataNode 1、DataNode 2 迁移至 DataNode 3。 + +```SQL +IoTDB> show migrations ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 101| 3| DataRegion| 1| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.051|2026-06-03T16:29:25.159| 2 second 897 ms|files 8/96, size 24 GB/280 GB | +| 102| 5| DataRegion| 2| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.059|2026-06-03T16:29:25.163| 2 second 889 ms|files 5/72, size 18 GB/210 GB | +| 103| 4|SchemaRegion| 1| 3|CHECK_REMOVE_REGION_PEER| WAITING|2026-06-03T16:29:25.067|2026-06-03T16:29:26.807| 2 second 876 ms| | ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +``` + +4. 迁移过程中,通过 `show regions` 可观察到目标节点上的 Region 进入 `Adding` 状态。此时,DataNode 3 会在本机文件系统中创建对应 Region 的目录;源 DataNode 会将本地持久化 TsFile 打包为快照,并通过跨网络 RPC 投递到 DataNode 3。以下仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion| Adding|root.industry| 8| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.691| Unknown| NaN| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` + +5. 当 DataNode 3 接收完快照,并回放迁移期间产生的 WAL 数据后,新副本进入 `Running` 状态;同时,原节点上的对应 Region 副本会被标记为 `Removing` 并进行删除回收。当 `show migrations` 返回空结果时,表示迁移任务已结束,当前没有正在执行的迁移任务。 + +```SQL +IoTDB> show migrations ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +|ProcedureId|RegionId|Type|FromNodeId|ToNodeId|CurrentState|ProcedureStatus|SubmittedTime|LastUpdateTime|Duration|Progress| ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +``` + +6. 再次查询 `show regions`,确认相关 Region 已迁移至目标节点,并回到 `Running` 状态。如下所示,部分 Region 副本迁移到 DataNode 3 后,DataNode 1、DataNode 2 和 DataNode 3 都继续承载历史 DataRegion。以下仍仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 3| host3| 6667| datanode-3| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 5|DataRegion|Running|root.industry| 6| 1| 1| host1| 6667| datanode-1| Leader|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 5|DataRegion|Running|root.industry| 6| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 7|DataRegion|Running|root.industry| 7| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.717| 240 GB| 3.10| +| 7|DataRegion|Running|root.industry| 7| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.717| 240 GB| 3.10| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` diff --git a/src/zh/UserGuide/latest-Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md b/src/zh/UserGuide/latest-Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md index c6e75bb8c..efb60ba20 100644 --- a/src/zh/UserGuide/latest-Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md +++ b/src/zh/UserGuide/latest-Table/Deployment-and-Maintenance/Cluster-Deployment_apache.md @@ -1,4 +1,4 @@ - -# 集群维护 - -## 1. 集群扩容 - -当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 - -### 1.1 核心概念 - -在执行扩容操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 - -#### 1.1.1 名词汇总 - -| **名词** | **类型** | **解释** | -| ------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------ | -| ConfigNode | 节点角色 | 管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。 | -| DataNode | 节点角色 | 数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。 | -| Database | 元数据 | 数据库,不同数据库的数据物理隔离 | -| DeviceId | 设备名 | 元数据树中从 root 到倒数第二级的全路径表示一个设备名 | -| SeriesSlot | 序列分区槽 | 每个 Database会对应固定个数的序列槽,包含其中序列的元数据。 | -| SeriesTimeSlot | 一个序列槽的一个时间分区槽 | 对应一个 SeriesSlot 内所有序列一个时间分区的数据 | -| SchemaRegion | 一组元数据分区 | 多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。 | -| DataRegion | 一组数据分区 | 多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。 | -| ConfigNodeGroup | 逻辑概念(共识组) | 由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。 | -| SchemaRegionGroup | 逻辑概念(共识组) | 元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份 | -| DataRegionGroup | 逻辑概念(共识组) | 数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。 | - -#### 1.1.2 集群架构 - -IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 - -![](/img/cluster-extention-1.png) - -#### 1.1.3 分区管理 -##### 集群共识组 - -在IoTDB中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 - -![](/img/cluster-extention-2.png) - -##### 分区槽机制 - -在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 - -第一类是​**序列分区槽(SeriesPartitionSlot)**​,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 - -![](/img/cluster-extention-3.png) - -第二类是​**时间分区槽(TimePartitionSlot)**​,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 - -![](/img/cluster-extention-4.png) - -通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 - -### 1.2 实现原理 - -IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 - -默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 - -![](/img/cluster-extention-5.png) - -扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 - -![](/img/cluster-extention-6.png) - -如果希望在扩容后对所有新老数据进行重新均衡,则需要使用数据分区手动迁移功能(简称Region 迁移)。 - -Region迁移语法参考: - -```SQL --- 解释:将哪个RegionId节点的数据从哪个DataNodeId节点迁移到哪个目标DataNodeId节点 - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; -``` - -在迁移过程中,ConfigNode负责整体调度,原 region 和原 DataNode 提供被移除的数据,新 region 和新 DataNode 承担新增数据。 - -![](/img/cluster-extention-7.png) - -如上图由3个DataNode组成的集群中,region 1副本组分布在DataNode 1和DataNode 2中,假设此时想将DataNode 1中的region 1副本迁移至DataNode 3中,其运转流程如下: - -1. 在CLI命令行中执行以下命令: - -```SQL -migrate region 1 from 1 to 3 -``` - -2. 此时Region迁移进入到复制阶段,复制阶段的核心工作是在目标节点中创建新的region副本,将同步全量region 1的数据,此时region状态为Adding。 -3. 此时Region迁移进入到移除阶段,当目标节点中的数据已经全量同步完毕,旧region节点的数据则可以安全删除了,所以此步骤的核心工作是移除旧节点的所有数据,以释放磁盘空间,此时region状态为Removing。 -4. 当2和3步骤执行完毕后,Region迁移工作整体完成。 - -### 1.3 操作步骤 -#### 1.3.1 前置准备 - -1. 服务器环境检查,建议操作系统版本与原集群保持一致。 -2. 数据库版本检查,建议版本与原集群版本保持一致。 -3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 - - ```Shell - #如果命令有输出,则表示该端口已被占用。 - lsof -i:6667 或 netstat -tunp | grep 6667 - lsof -i:10710 或 netstat -tunp | grep 10710 - lsof -i:10720 或 netstat -tunp | grep 10720 - ``` -4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 -5. 软件依赖:安装 Java 运行环境 ,Java 版本 >= 1.8,请确保已设置 jdk 环境变量。 -6. 域名配置:部署时推荐优先使用hostname进行IP配置,可避免后期修改主机ip导致数据库无法启动的问题。设置hostname需要在目标服务器上配置/etc/hosts,如本机ip是192.168.1.3,hostname是iotdb-1,则可以使用以下命令设置服务器的 hostname,并使用hostname配置IoTDB的cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 - -```Shell -# 注意:本机和原集群节点的域名都需要配置 -echo "192.168.1.3 iotdb-1" >> /etc/hosts -``` - -#### 1.3.2 扩容操作 -1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 -2. 解压安装包并进入安装目录 - -```Shell -unzip apache-iotdb-{version}-bin.zip -cd apache-iotdb-{version}-bin -``` - -3. 修改相应配置 - -```Shell -cd apache-iotdb-{version}-bin/conf -vim iotdb-system.properies -``` - -| 配置项 | 说明 | 默认 | 备注 | -| ------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------- | --------------------------------------------------------------------------- | -| **dn\_seed\_config\_node** | **节点注册加入集群时连接的ConfigNode地址,即cn\_internal\_address:cn\_internal\_port** | **127.0.0.1:10710** | **\* 非常重要,强制修改此项,将其改为原集群ConfigNode主节点的地址** | -| dn\_rpc\_address | 客户端 RPC 服务的地址 | 0.0.0.0 | 按需修改,重启服务生效 | -| dn\_rpc\_port | 客户端 RPC 服务的端口 | 6667 | 按需修改,重启服务生效 | -| dn\_internal\_address | DataNode在集群内部通讯使用的地址 | 127.0.0.1 | 按需修改,首次启动后不能修改 | -| dn\_internal\_port | DataNode在集群内部通信使用的端口 | 10730 | 按需修改,首次启动后不能修改 | -| dn\_mpp\_data\_exchange\_port | DataNode用于接收数据流使用的端口 | 10740 | 按需修改,首次启动后不能修改 | -| dn\_data\_region\_consensus\_port | DataNode用于数据副本共识协议通信使用的端口 | 10750 | 按需修改,首次启动后不能修改 | -| dn\_schema\_region\_consensus\_port | DataNode用于元数据副本共识协议通信使用的端口 | 10760 | 按需修改,首次启动后不能修改 | - -4. 启动DataNode节点 - -进入iotdb的sbin目录下,启动datanode: - -```Shell -# Unix/OS X -./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 - -# Windows -# V2.0.4.x 版本之前 -.\sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -.\sbin\windows\start-datanode.bat -``` - -5. 通过CLI命令连接原集群,进行扩容后验证 - -```Shell -# Linux或MACOS系统 - ./apache-iotdb-{version}-bin/sbin/start-cli.sh - - # Windows - # V2.0.4.x 版本之前 - .\apache-iotdb-{version}-bin\sbin\start-cli.bat - - # V2.0.4.x 版本及之后 - .\apache-iotdb-{version}-bin\sbin\windows\start-cli.bat -``` - -6. 执行命令进行验证 - -执行show datanodes命令进行验证,预期结果列表中出现新加入的节点,且节点状态为Running - -```Shell -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -7. 其它节点重复以上操作,值得注意的是,新节点能够成功加入原集群需保证原集群允许加入的DataNode节点数量是足够的。 - -#### 1.3.3 手动负载均衡(按需选择) - -默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,需手动迁移 Region。迁移耗时可估算为:Region 数据量 ÷ 实际数据传输速度。如下图所示,假设将旧节点80TB的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为100 MB/s,迁移约需 3 小时完成。 - -![](/img/cluster-extention-8.png) - -具体操作如下: - -```SQL --- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 -migrate region 1 from 2 to 4 - --- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 -migrate region 2 from 3 to 5 - --- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 -migrate region 3 from 1 to 6 -``` - -迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 - -![](/img/cluster-extention-9.png) - -## 2. 节点管理 - -节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 - -### 2.1 ConfigNode 节点维护 - -ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: - -* 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加2个 ConfigNode,使得集群中有3个 ConfigNode。 -* 集群故障恢复:1个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 - -> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有1或者3个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过3个 ConfigNode 会导致性能损失。 - -#### 2.1.1 添加 ConfigNode 节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-confignode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-confignode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-confignode.bat -``` - -参数介绍: - -| 参数 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -#### 2.1.2 移除 ConfigNode 节点 - -首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: - -```SQL -IoTDB> show confignodes -+------+-------+---------------+------------+--------+ -|NodeID| Status|InternalAddress|InternalPort| Role| -+------+-------+---------------+------------+--------+ -| 0|Running| 127.0.0.1| 10710| Leader| -| 1|Running| 127.0.0.1| 10711|Follower| -| 2|Running| 127.0.0.1| 10712|Follower| -+------+-------+---------------+------------+--------+ -Total line number = 3 -It costs 0.030s -``` - -然后使用 SQL 将 ConfigNode 移除,SQL 命令: - -```Bash -remove confignode [confignode_id] -``` - -### 2.2 DataNode 节点维护 - -DataNode 节点维护有两个常见场景: - -* 集群扩容:出于集群能力扩容等目的,添加新的DataNode进入集群 -* 集群故障恢复:一个DataNode所在机器出现故障,使得该DataNode无法正常运行,此时可以移除该DataNode,并添加新的DataNode进入集群 - -> ❗️注意,为了使集群能正常工作,在DataNode节点维护过程中以及维护完成后,正常运行的DataNode总数不得少于数据副本数(通常为2),也不得少于元数据副本数(通常为3)。 - -#### 2.2.1 添加DataNode节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-datanode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-datanode.bat -``` - -参数介绍: - -| 缩写 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -说明:在添加DataNode后,随着新的写入到来(以及旧数据过期,如果设置了TTL),集群负载会逐渐向新的DataNode均衡,最终在所有节点上达到存算资源的均衡。 - -#### 2.2.2 移除DataNode节点 - -首先通过CLI连接集群,通过`show datanodes`确认想要移除的DataNode的NodeID: - -```SQL -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -然后使用SQL将DataNode移除,SQL命令: - -```Bash -remove datanode [datanode_id] -``` - - -## 3. 负载均衡 - -Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 - -### 3.1 功能介绍 - -IoTDB 是一个分布式数据库,数据的均衡分布对集群的磁盘空间、写入压力的负载均衡有着重要作用,region 是数据在 IoTDB 集群中进行分布式存储的基本单元,具体概念可见[region](../Background-knowledge/Cluster-Concept.md)。 - -集群正常运行情况下,IoTDB 将会自动对数据进行负载均衡,但在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,可通过手动 Region 迁移精细化调整集群负载和运维。 - -下面是一次region迁移过程的示意图: - - -![](/img/region%E8%BF%81%E7%A7%BB%E7%A4%BA%E6%84%8F%E5%9B%BE20241210.png) - -### 3.2 注意事项 - -1. 推荐仅在 IoTDB 1.3.3 以及更高版本使用 Region 迁移功能。 -2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(iotdb-system.properties中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 -3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 -4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 - -### 3.3 使用说明 - -- **语法定义**: - - 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 - - ```SQL - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; - ``` - -- **示例**: - - 将 region 1 从 DataNode 2 迁移至 DataNode 3: - - ```SQL - IoTDB> migrate region 1 from 2 to 3 - Msg: The statement is executed successfully. - ``` - - “The statement is executed successfully” 仅代表region迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 - -- **相关配置项**: - - - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 region 迁移速度。 - -- **耗时估算**: - - 如果迁移过程无并发写入,那么耗时可以简单通过 region 数据量除以数据传输速度来估算。例如对于 1TB 的 region,硬盘网络带宽和限速参数共同决定数据传输速度是 100MB/s,那么需要约 3 小时完成迁移。 - - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1.5来估算。 - -- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,region 所在共识组的状态会经历如下过程: - - 迁移开始前:`Running`,`Running`。 - - - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 - - - 缩容阶段:`Removing`,`Running`,`Running`。 - - - 迁移完成:`Running`,`Running`。 - - 以扩容阶段为例,`show regions`的结果可能为: - - ```Plain - IoTDB> show regions - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| - | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - Total line number = 3 - It costs 0.003s - ``` - -- **阻塞写入**: - - IoTConsensus 的 region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 - - 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: - ```plain - IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" - Msg: The statement is executed successfully. - ``` diff --git a/src/zh/UserGuide/latest-Table/User-Manual/Load-Balance_apache.md b/src/zh/UserGuide/latest-Table/User-Manual/Load-Balance_apache.md new file mode 100644 index 000000000..0580404da --- /dev/null +++ b/src/zh/UserGuide/latest-Table/User-Manual/Load-Balance_apache.md @@ -0,0 +1,703 @@ + + +# 集群维护 + +## 1. 核心概念 + +在进行集群维护操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 + +### 1.1 名词汇总 + +|**名词**|**类型**|**解释**| +|---|---|---| +|ConfigNode|节点角色|管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。| +|DataNode|节点角色|数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。| +|Database|元数据|数据库,不同数据库的数据物理隔离。| +|DeviceId|设备名|元数据树中从 root 到倒数第二级的全路径表示一个设备名。| +|SeriesSlot|序列分区槽|每个 Database 会对应固定个数的序列槽,包含其中序列的元数据。| +|TimeSlot|一个序列槽的一个时间分区槽|对应一个 SeriesSlot 内所有序列一个时间分区的数据。| +|DataPartition|数据分区槽|一个 SeriesSlot 加 一个 TimeSlot 对应一个 DataPartition| +|SchemaRegion|一组元数据分区|多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。| +|DataRegion|一组数据分区|多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。| +|ConfigNodeGroup|逻辑概念(共识组)|由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。| +|SchemaRegionGroup|逻辑概念(共识组)|元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份。| +|DataRegionGroup|逻辑概念(共识组)|数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。| + +### 1.2 集群架构 + +IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 + +![](/img/cluster-extention-1.png) + +### 1.3 分区管理 + +#### 1.3.1 集群共识组 + +在 IoTDB 中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 + +![](/img/cluster-extention-2.png) + +#### 1.3.2 分区槽机制 + +在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 + +第一类是**序列分区槽(SeriesPartitionSlot)**,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 + +![](/img/cluster-extention-3.png) + +第二类是**时间分区槽(TimePartitionSlot)**,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 + +![](/img/cluster-extention-4.png) + +通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 + +## 2. 集群扩容 + +当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 + +### 2.1 实现原理 + +IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 + +默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 + +![](/img/cluster-extention-5.png) + +扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 + +![](/img/cluster-extention-6.png) + +如果希望在扩容后进一步均衡历史数据,可按需执行 Region 迁移或 Region 重均衡:当需要精确指定 Region、源 DataNode 和目标 DataNode 时,可参考【4\. 手动 Region 迁移】;当希望系统自动计算迁移方案并完成整体均衡时,可参考【5\. 自动 Region 重均衡】。 + +### 2.2 操作步骤 + +#### 2.2.1 前置准备 + +1. 服务器环境检查,建议操作系统版本与原集群保持一致。 + +2. 数据库版本检查,建议版本与原集群版本保持一致。 + +3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 + + ```Shell + #如果命令有输出,则表示该端口已被占用。 + lsof -i:6667 或 netstat -tunp | grep 6667 + lsof -i:10710 或 netstat -tunp | grep 10710 + lsof -i:10720 或 netstat -tunp | grep 10720 + ``` + +4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 + +5. 软件依赖:安装 Java 运行环境 ,Java 版本 \>= 1\.8,请确保已设置 jdk 环境变量。 + +6. 域名配置:部署时推荐优先使用 hostname 进行 IP 配置,可避免后期修改主机 IP 导致数据库无法启动的问题。设置 hostname 需要在目标服务器上配置`/etc/hosts`,如本机 IP 是192\.168\.1\.3,hostname 是 iotdb\-1,则可以使用以下命令设置服务器的 hostname,并使用 hostname 配置 IoTDB 的 cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 + +```Shell +# 注意:本机和原集群节点的域名都需要配置 +echo "192.168.1.3 iotdb-1" >> /etc/hosts +``` + +#### 2.2.2 扩容操作 + +1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 + +2. 解压安装包并进入安装目录 + +```Shell +unzip iotdb-{version}-bin.zip +cd iotdb-{version}-bin +``` + +3. 修改相应配置 + +```Shell +cd iotdb-{version}-bin/conf +vim iotdb-system.properies +``` + +|配置项|说明|默认|备注| +|---|---|---|---| +|dn\_seed\_config\_node|节点注册加入集群时连接的 ConfigNode 地址,即 cn\_internal\_address:cn\_internal\_port|127\.0\.0\.1:10710
|非常重要,强制修改此项,将其改为原集群 ConfigNode 主节点的地址
| +|dn\_rpc\_address|客户端 RPC 服务的地址|0\.0\.0\.0|按需修改,重启服务生效| +|dn\_rpc\_port|客户端 RPC 服务的端口|6667|按需修改,重启服务生效| +|dn\_internal\_address|DataNode 在集群内部通讯使用的地址|127\.0\.0\.1|按需修改,首次启动后不能修改| +|dn\_internal\_port|DataNode 在集群内部通信使用的端口|10730|按需修改,首次启动后不能修改| +|dn\_mpp\_data\_exchange\_port|DataNode 用于接收数据流使用的端口|10740|按需修改,首次启动后不能修改| +|dn\_data\_region\_consensus\_port|DataNode 用于数据副本共识协议通信使用的端口|10750|按需修改,首次启动后不能修改| +|dn\_schema\_region\_consensus\_port|DataNode 用于元数据副本共识协议通信使用的端口|10760|按需修改,首次启动后不能修改| + +4. 启动 DataNode 节点 + +进入 IoTDB 的 sbin 目录下,启动 Datanode: + +```Shell +./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 +``` + +5. 通过 CLI 命令连接原集群,进行扩容后验证 + +```Shell +# Linux 或 macOS系统 + ./iotdb-{version}-bin/sbin/start-cli.sh + + # Windows 系统 + ./iotdb-{version}-bin/sbin/start-cli.bat +``` + +6. 执行命令进行验证 + +执行`show datanodes`命令进行验证,预期结果列表中出现新加入的节点,且节点状态为 Running。 + +```Shell +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| +| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 ++------+-------+----------+-------+-------------+---------------+ +Total line number = 4 +It costs 0.110s +``` + +7. 其他节点重复以上操作。新节点能够成功加入原集群的前提是原集群允许加入的 DataNode 节点数量足够,否则需要联系工作人员重新申请激活码信息。 + +#### 2.2.3 手动负载均衡(按需选择) + +默认情况下,扩容后历史数据不会自动迁移。若需进一步均衡各节点的数据分布,可选择以下方式: + +- 手动 Region 迁移:适用于已明确需要迁移的 Region、源 DataNode 和目标 DataNode 的场景,详见【4\. 手动 Region 迁移】。 + +- 自动 Region 重均衡:适用于扩容后希望系统自动选择迁移方案、整体均衡历史数据的场景,详见【5\. 自动 Region 重均衡】。 + +## 3. 节点管理 + +节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 + +### 3.1 ConfigNode 节点维护 + +ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: + +- 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加 2 个 ConfigNode,使得集群中有 3 个 ConfigNode。 + +- 集群故障恢复:1 个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 + +> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有 1 或者 3 个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过 3 个 ConfigNode 会导致性能损失。 +> +> + +#### 3.1.1 添加 ConfigNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-confignode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-confignode.bat + +# V2.0.4.x 版本及之后 +sbin\windows\start-confignode.bat +``` + +参数介绍: + +|参数|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +#### 3.1.2 移除 ConfigNode 节点 + +首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: + +```SQL +IoTDB> show confignodes ++------+-------+---------------+------------+--------+ +|NodeID| Status|InternalAddress|InternalPort| Role| ++------+-------+---------------+------------+--------+ +| 0|Running| 127.0.0.1| 10710| Leader| +| 1|Running| 127.0.0.1| 10711|Follower| +| 2|Running| 127.0.0.1| 10712|Follower| ++------+-------+---------------+------------+--------+ +Total line number = 3 +It costs 0.030s +``` + +然后使用 SQL 将 ConfigNode 移除,SQL 命令: + +```Bash +remove confignode [confignode_id] +``` + +### 3.2 DataNode 节点维护 + +DataNode 节点维护有两个常见场景: + +- 集群扩容:出于集群能力扩容等目的,添加新的 DataNode 进入集群。 + +- 集群故障恢复:一个 DataNode 所在机器出现故障,使得该 DataNode 无法正常运行,此时可以移除该 DataNode,并添加新的 DataNode 进入集群 + +> ❗️注意,为了使集群能正常工作,在 DataNode 节点维护过程中以及维护完成后,正常运行的 DataNode 总数不得少于数据副本数(通常为 2),也不得少于元数据副本数(通常为 3)。 +> +> + +#### 3.2.1 添加 DataNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-datanode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-datanode.bat + +# V2.0.4.x 版本及之后 +tools\windows\start-datanode.bat +``` + +参数介绍: + +|缩写|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +说明:在添加 DataNode 后,随着新的写入到来(以及旧数据过期,如果设置了 TTL),集群负载会逐渐向新的 DataNode 均衡,最终在所有节点上达到存算资源的均衡。 + +#### 3.2.2 移除DataNode节点 + +首先通过 CLI 连接集群,通过`show datanodes`确认想要移除的 DataNode 的 NodeID: + +```SQL +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| ++------+-------+----------+-------+-------------+---------------+ +Total line number = 3 +It costs 0.110s +``` + +然后使用 SQL 将 DataNode 移除,SQL 命令: + +```Bash +remove datanode [datanode_id] +``` + +## 4. 手动 Region 迁移 + +Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +### 4.1 功能介绍 + +IoTDB 是一个分布式数据库,Region 是数据在 IoTDB 集群中进行分布式存储的基本单元。集群正常运行情况下,IoTDB 会自动对新增数据进行负载均衡;在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,支持通过手动 Region 迁移精细化调整集群负载和运维。 + +### 4.2 注意事项 + +1. 推荐仅在 IoTDB 1\.3\.3 以及更高版本使用 Region 迁移功能。 + +2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(`iotdb-system.properties`中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 + +3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 + +4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 + +### 4.3 使用说明 + +- **语法定义**: + + 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 + + ```SQL + migrateRegion + : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL + ; + ``` + +- **语法示例**: + + 将 region 1 从 DataNode 2 迁移至 DataNode 3: + + ```SQL + IoTDB> migrate region 1 from 2 to 3 + Msg: The statement is executed successfully. + ``` + + “The statement is executed successfully” 仅代表 Region 迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 + +- **相关配置项**: + + - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 Region 迁移速度。 + +- **耗时估算**: + + - 如果迁移过程无并发写入,那么耗时可以简单通过 Region 数据量除以数据传输速度来估算。实际数据传输速度由硬盘、网络带宽和迁移限速参数共同决定。 + + - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1\.5来估算。 + +- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,Region 所在共识组的状态会经历如下过程: + + - 迁移开始前:`Running`,`Running`。 + + - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 + + - 缩容阶段:`Removing`,`Running`,`Running`。 + + - 迁移完成:`Running`,`Running`。 + + 以扩容阶段为例,`show regions`的结果可能为: + + ```Plain Text + IoTDB> show regions + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| + | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + Total line number = 6 + It costs 0.003s + ``` + +- **阻塞写入**: + + IoTConsensus 的 Region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 + + 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: + + ```Plain Text + IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" + Msg: The statement is executed successfully. + ``` + +- + +### 4.4 场景示例 + +默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,可手动迁移 Region。如下图所示,假设将旧节点 80 TB 的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为 100 MB/s,迁移约需 3 小时完成。 + +![](/img/cluster-extention-8.png) + +具体操作如下: + +```SQL +-- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 +migrate region 1 from 2 to 4 + +-- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 +migrate region 2 from 3 to 5 + +-- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 +migrate region 3 from 1 to 6 +``` + +迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 + +![](/img/cluster-extention-9.png) + +### 4.5 补充语法(不推荐) + +> **注意:** `EXTEND REGION` 和 `REMOVE REGION` 属于 **高危** 运维指令,不推荐常规使用,生产环境请慎用。一般情况下,Region 迁移应使用 `MIGRATE REGION`;Region 重建应使用 `RECONSTRUCT Region`。 +> +> + +#### 4.5.1 Extend Region + +将一个或多个 Region 扩容到指定 DataNode。 + +- 语法定义: + + ```SQL + extendRegion + : EXTEND REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* TO targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 将 Region 1 扩容到 DataNode 3: + + ```SQL + IoTDB> extend region 1 to 3 + Msg: The statement is executed successfully. + ``` + +#### 4.5.2 Remove Region + +从指定 DataNode 上移除一个或多个 Region 副本。 + +- 语法定义: + + ```SQL + removeRegion + : REMOVE REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* FROM targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 从 DataNode 2 上移除 Region 1: + + ```SQL + IoTDB> remove region 1 from 2 + Msg: The statement is executed successfully. + ``` + +## 5. 自动 Region 重均衡 + +Region 重均衡属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +> V2\.0\.10 起支持 +> +> + +### 5.1 功能介绍 + +Region 重均衡功能支持通过一条 SQL 提交重均衡任务,系统后台使用扩容均衡算法计算 Region 迁移方案,并由 ConfigNode 调度执行。该功能不局限于扩容场景,在未出现扩缩容的情况下,如果存在 Region 大小不均衡、节点间磁盘使用不均衡或写入负载集中在少部分 Region 等情况,也可以使用此功能。 + +`LOAD BALANCE` 本质上是由系统自动生成并执行一组 Region 迁移任务,适合进行整体重均衡;`migrate region` 则适合用户已经明确 RegionId、源 DataNode 和目标 DataNode 的精细化迁移场景。自动重均衡任务提交后,可通过 `SHOW MIGRATIONS` 观察实际生成的迁移任务和执行进度。 + +- 适用场景:扩容后希望历史 Region 自动迁移到新节点;节点间磁盘使用明显不均;部分 DataNode 写入压力较高,需要整体调整 Region 分布。 + +- 谨慎使用场景:业务高峰期、网络或磁盘 I/O 资源紧张时,建议先评估迁移带来的资源占用;如果需要精确控制某个 Region 的迁移路径,建议使用手动 Region 迁移。 + +### 5.2 LOAD BALANCE + +```SQL +-- 触发系统负载均衡(由系统自动选择目标节点) +LOAD BALANCE; + +-- 指定目标 DataNode 节点 ID,并执行负载均衡 +LOAD BALANCE TO DATANODES(*DataNodeId,DataNodeId*); +``` + +- **功能机制** + +向 ConfigNode 提交一个异步执行的全局或局部分布式均衡任务。任务触发后,集群 DataNode 会被划分为两类角色池,且数据物理迁移具备严格单向约束: + +- From 节点(源节点池):提供待迁移 Region 数据的节点 + +- To 节点(目标节点池):接收迁移数据的节点 + +- 单向迁移规则:数据仅允许从 From 节点单向迁移至 To 节点 + +- **参数说明** + +|参数|必填|说明| +|---|---|---| +|TO DATANODES|否|显式传入一个或多个 DataNodeId 列表(逗号分隔),传入的节点被划定为接收数据的 To 节点池,其余节点自动归属为提供数据的 From 节点池| + +- **默认行为** + +|执行方式|行为说明| +|---|---| +|不带参数 \(`LOAD BALANCE`\)|系统默认选择当前磁盘占用量最小的一个节点作为唯一的 To 节点| +|带参数 \(`LOAD BALANCE TO DATANODES(...)`\)|指定的节点被强行划定为接收数据的 To 节点池,其余节点为 From 节点池| + +- **预期结果** + +命令执行后,控制台将立即返回 `Msg: The statement is executed successfully.`。这仅表示 ConfigNode 成功受理了负载均衡任务并将测算生成的子任务编排入列,底层的海量物理迁移随即在后台异步展开。 + +- **配置项说明** + +在配置文件 `iotdb-system.properties` 中,可通过 `region_migration_speed_limit_bytes_per_second` 控制每个 DataNode 的 Region 迁移传输上限,单位为 byte/s,默认值为 `50331648`,约 48 MiB/s。业务繁忙时可适当降低该值,业务低峰期可适当调高;但不建议设置过低,否则迁移耗时会明显增加,甚至可能发生迁移阻塞。配置值小于等于 0 表示不限速;该参数仅对 IoTConsensus 协议生效,支持热加载。 + +### 5.3 SHOW MIGRATIONS + +由于平衡任务涉及数百 GB 级别的大文件跨节点流转,系统提供如下核心观测 SQL 获取具有细粒度状态指示的全局视图。该语句会返回当前集群内部正在执行的后台迁移任务清单,并以结构化列表展示任务状态、耗时和迁移进度。 + +```SQL +SHOW MIGRATIONS +``` + +- **结果集说明** + +|字段名|说明| +|---|---| +|ProcedureId|Procedure 唯一标识| +|RegionId|Region ID| +|Type|Region 类型| +|FromNodeId|源节点 DataNode ID| +|ToNodeId|目标节点 DataNode ID| +|CurrentState|当前状态(如 `REGION_MIGRATE_PREPARE`, `ADD_REGION_PEER`, `REMOVE_REGION_PEER` 等)| +|ProcedureStatus|Procedure 状态(如 RUNNING、FINISHED、FAILED 等)| +|SubmittedTime|任务提交时间| +|LastUpdateTime|最近更新时间| +|Duration|已耗时| +|Progress|迁移进度(已迁移文件数/总文件数)| + +例如: + +```SQL +IoTDB> show migrations ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 11| 5|DataRegion| 2| 3|CHECK_ADD_REGION_PEER| WAITING|2026-06-03T15:47:35.840|2026-06-03T15:47:35.966|31 second 169 ms|files 1/3, size 15.52 KB/15.61 KB| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +Total line number = 1 +It costs 0.004s +``` + +- Show Regions 联动状态观测 + +迁移过程中,相关 Region 的状态也会发生变化。以 2 副本集群为例,在 `SHOW MIGRATIONS` 显示某个任务正在执行时,执行 `show regions` 可观察到该 Region 经历如下状态变化: + +1. 稳态(迁移前): `Running`, `Running`。 + +2. 复制扩容过渡态: `Running`, `Running`, `Adding`(目标 To 节点新建 Region 副本并接收快照,处于 `Adding `状态,该状态不对外提供服务)。 + +3. 安全移除过渡态: `Removing`, `Running`, `Running`(目标节点追平数据变为 `Running`,原 From 节点变为 `Removing`进行删除回收)。 + +4. 新稳态(迁移后): 旧 Region 删除成功,重回 `Running` , `Running` 状态。 + +### 5.4 场景示例 + +以下示例模拟某个真实工业场景:随着业务数据持续增长,系统原有的“两台核心数据节点”配置需要扩展为具有更高吞吐量与存储余量的“三数据节点”架构,并使用双副本冗余(即 1C2D \-\> 1C3D 的平滑扩容)。集群初始为 1 个 ConfigNode 和 2 个 DataNode,新增 DataNode 3 后,通过自动 Region 重均衡让新节点承载部分历史 Region,从而缓解原有节点的存储压力。 + +![](/img/load-balance.png) + +以下 SQL 返回结果仅用于说明关键流程,部分输出为节选展示;实际返回结果会受集群规模、Region 数量、数据库名称、时间分区和节点地址等因素影响,请以实际运行结果为准。 + +1. 扩容前,通过 `show cluster` 查看集群节点,集群中只有 DataNode 1 和 DataNode 2。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +2. 扩容后,通过 `show cluster` 确认 DataNode 3 已加入集群,且状态为 Running。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| +| 3| DataNode|Running| datanode-3| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +3. 执行 `LOAD BALANCE` 提交重均衡任务。该命令提交成功仅表示 ConfigNode 已受理任务。如果希望明确指定新节点作为迁移目标,可使用 `TO DATANODES` 指定目标 DataNodeId。 + +```SQL +IoTDB> LOAD BALANCE; + +-- 或者指定 DataNode 3 作为目标节点 +IoTDB> LOAD BALANCE TO DATANODE 3; +``` + +4. 通过 `show migrations` 观察后台迁移任务。此时控制台可看到正在排队与流转的子任务,例如多个 Region 副本正从 DataNode 1、DataNode 2 迁移至 DataNode 3。 + +```SQL +IoTDB> show migrations ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 101| 3| DataRegion| 1| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.051|2026-06-03T16:29:25.159| 2 second 897 ms|files 8/96, size 24 GB/280 GB | +| 102| 5| DataRegion| 2| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.059|2026-06-03T16:29:25.163| 2 second 889 ms|files 5/72, size 18 GB/210 GB | +| 103| 4|SchemaRegion| 1| 3|CHECK_REMOVE_REGION_PEER| WAITING|2026-06-03T16:29:25.067|2026-06-03T16:29:26.807| 2 second 876 ms| | ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +``` + +4. 迁移过程中,通过 `show regions` 可观察到目标节点上的 Region 进入 `Adding` 状态。此时,DataNode 3 会在本机文件系统中创建对应 Region 的目录;源 DataNode 会将本地持久化 TsFile 打包为快照,并通过跨网络 RPC 投递到 DataNode 3。以下仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion| Adding|root.industry| 8| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.691| Unknown| NaN| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` + +5. 当 DataNode 3 接收完快照,并回放迁移期间产生的 WAL 数据后,新副本进入 `Running` 状态;同时,原节点上的对应 Region 副本会被标记为 `Removing` 并进行删除回收。当 `show migrations` 返回空结果时,表示迁移任务已结束,当前没有正在执行的迁移任务。 + +```SQL +IoTDB> show migrations ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +|ProcedureId|RegionId|Type|FromNodeId|ToNodeId|CurrentState|ProcedureStatus|SubmittedTime|LastUpdateTime|Duration|Progress| ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +``` + +6. 再次查询 `show regions`,确认相关 Region 已迁移至目标节点,并回到 `Running` 状态。如下所示,部分 Region 副本迁移到 DataNode 3 后,DataNode 1、DataNode 2 和 DataNode 3 都继续承载历史 DataRegion。以下仍仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 3| host3| 6667| datanode-3| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 5|DataRegion|Running|root.industry| 6| 1| 1| host1| 6667| datanode-1| Leader|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 5|DataRegion|Running|root.industry| 6| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 7|DataRegion|Running|root.industry| 7| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.717| 240 GB| 3.10| +| 7|DataRegion|Running|root.industry| 7| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.717| 240 GB| 3.10| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` diff --git a/src/zh/UserGuide/latest/Deployment-and-Maintenance/Cluster-Deployment_apache.md b/src/zh/UserGuide/latest/Deployment-and-Maintenance/Cluster-Deployment_apache.md index 5070a3620..84a555776 100644 --- a/src/zh/UserGuide/latest/Deployment-and-Maintenance/Cluster-Deployment_apache.md +++ b/src/zh/UserGuide/latest/Deployment-and-Maintenance/Cluster-Deployment_apache.md @@ -1,4 +1,4 @@ - -# 集群维护 - -## 1. 集群扩容 - -当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 - -### 1.1 核心概念 - -在执行扩容操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 - -#### 1.1.1 名词汇总 - -| **名词** | **类型** | **解释** | -| ------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------ | -| ConfigNode | 节点角色 | 管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。 | -| DataNode | 节点角色 | 数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。 | -| Database | 元数据 | 数据库,不同数据库的数据物理隔离 | -| DeviceId | 设备名 | 元数据树中从 root 到倒数第二级的全路径表示一个设备名 | -| SeriesSlot | 序列分区槽 | 每个 Database会对应固定个数的序列槽,包含其中序列的元数据。 | -| SeriesTimeSlot | 一个序列槽的一个时间分区槽 | 对应一个 SeriesSlot 内所有序列一个时间分区的数据 | -| SchemaRegion | 一组元数据分区 | 多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。 | -| DataRegion | 一组数据分区 | 多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。 | -| ConfigNodeGroup | 逻辑概念(共识组) | 由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。 | -| SchemaRegionGroup | 逻辑概念(共识组) | 元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份 | -| DataRegionGroup | 逻辑概念(共识组) | 数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。 | - -#### 1.1.2 集群架构 - -IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 - -![](/img/cluster-extention-1.png) - -#### 1.1.3 分区管理 -##### 集群共识组 - -在IoTDB中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 - -![](/img/cluster-extention-2.png) - -##### 分区槽机制 - -在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 - -第一类是​**序列分区槽(SeriesPartitionSlot)**​,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 - -![](/img/cluster-extention-3.png) - -第二类是​**时间分区槽(TimePartitionSlot)**​,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 - -![](/img/cluster-extention-4.png) - -通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 - -### 1.2 实现原理 - -IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 - -默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 - -![](/img/cluster-extention-5.png) - -扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 - -![](/img/cluster-extention-6.png) - -如果希望在扩容后对所有新老数据进行重新均衡,则需要使用数据分区手动迁移功能(简称Region 迁移)。 - -Region迁移语法参考: - -```SQL --- 解释:将哪个RegionId节点的数据从哪个DataNodeId节点迁移到哪个目标DataNodeId节点 - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; -``` - -在迁移过程中,ConfigNode负责整体调度,原 region 和原 DataNode 提供被移除的数据,新 region 和新 DataNode 承担新增数据。 - -![](/img/cluster-extention-7.png) - -如上图由3个DataNode组成的集群中,region 1副本组分布在DataNode 1和DataNode 2中,假设此时想将DataNode 1中的region 1副本迁移至DataNode 3中,其运转流程如下: - -1. 在CLI命令行中执行以下命令: - -```SQL -migrate region 1 from 1 to 3 -``` - -2. 此时Region迁移进入到复制阶段,复制阶段的核心工作是在目标节点中创建新的region副本,将同步全量region 1的数据,此时region状态为Adding。 -3. 此时Region迁移进入到移除阶段,当目标节点中的数据已经全量同步完毕,旧region节点的数据则可以安全删除了,所以此步骤的核心工作是移除旧节点的所有数据,以释放磁盘空间,此时region状态为Removing。 -4. 当2和3步骤执行完毕后,Region迁移工作整体完成。 - -### 1.3 操作步骤 -#### 1.3.1 前置准备 - -1. 服务器环境检查,建议操作系统版本与原集群保持一致。 -2. 数据库版本检查,建议版本与原集群版本保持一致。 -3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 - - ```Shell - #如果命令有输出,则表示该端口已被占用。 - lsof -i:6667 或 netstat -tunp | grep 6667 - lsof -i:10710 或 netstat -tunp | grep 10710 - lsof -i:10720 或 netstat -tunp | grep 10720 - ``` -4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 -5. 软件依赖:安装 Java 运行环境 ,Java 版本 >= 1.8,请确保已设置 jdk 环境变量。 -6. 域名配置:部署时推荐优先使用hostname进行IP配置,可避免后期修改主机ip导致数据库无法启动的问题。设置hostname需要在目标服务器上配置/etc/hosts,如本机ip是192.168.1.3,hostname是iotdb-1,则可以使用以下命令设置服务器的 hostname,并使用hostname配置IoTDB的cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 - -```Shell -# 注意:本机和原集群节点的域名都需要配置 -echo "192.168.1.3 iotdb-1" >> /etc/hosts -``` - -#### 1.3.2 扩容操作 -1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 -2. 解压安装包并进入安装目录 - -```Shell -unzip apache-iotdb-{version}-bin.zip -cd apache-iotdb-{version}-bin -``` - -3. 修改相应配置 - -```Shell -cd apache-iotdb-{version}-bin/conf -vim iotdb-system.properies -``` - -| 配置项 | 说明 | 默认 | 备注 | -| ------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------- | --------------------------------------------------------------------------- | -| **dn\_seed\_config\_node** | **节点注册加入集群时连接的ConfigNode地址,即cn\_internal\_address:cn\_internal\_port** | **127.0.0.1:10710** | **\* 非常重要,强制修改此项,将其改为原集群ConfigNode主节点的地址** | -| dn\_rpc\_address | 客户端 RPC 服务的地址 | 0.0.0.0 | 按需修改,重启服务生效 | -| dn\_rpc\_port | 客户端 RPC 服务的端口 | 6667 | 按需修改,重启服务生效 | -| dn\_internal\_address | DataNode在集群内部通讯使用的地址 | 127.0.0.1 | 按需修改,首次启动后不能修改 | -| dn\_internal\_port | DataNode在集群内部通信使用的端口 | 10730 | 按需修改,首次启动后不能修改 | -| dn\_mpp\_data\_exchange\_port | DataNode用于接收数据流使用的端口 | 10740 | 按需修改,首次启动后不能修改 | -| dn\_data\_region\_consensus\_port | DataNode用于数据副本共识协议通信使用的端口 | 10750 | 按需修改,首次启动后不能修改 | -| dn\_schema\_region\_consensus\_port | DataNode用于元数据副本共识协议通信使用的端口 | 10760 | 按需修改,首次启动后不能修改 | - -4. 启动DataNode节点 - -进入iotdb的sbin目录下,启动datanode: - -```Shell -# Unix/OS X -./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 - -# Windows -# V2.0.4.x 版本之前 -.\sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -.\sbin\windows\start-datanode.bat -``` - -5. 通过CLI命令连接原集群,进行扩容后验证 - -```Shell -# Linux或MACOS系统 - ./apache-iotdb-{version}-bin/sbin/start-cli.sh - - # Windows - # V2.0.4.x 版本之前 - .\apache-iotdb-{version}-bin\sbin\start-cli.bat - - # V2.0.4.x 版本及之后 - .\apache-iotdb-{version}-bin\sbin\windows\start-cli.bat -``` - -6. 执行命令进行验证 - -执行show datanodes命令进行验证,预期结果列表中出现新加入的节点,且节点状态为Running - -```Shell -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -7. 其它节点重复以上操作,值得注意的是,新节点能够成功加入原集群需保证原集群允许加入的DataNode节点数量是足够的。 - -#### 1.3.3 手动负载均衡(按需选择) - -默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,需手动迁移 Region。迁移耗时可估算为:Region 数据量 ÷ 实际数据传输速度。如下图所示,假设将旧节点80TB的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为100 MB/s,迁移约需 3 小时完成。 - -![](/img/cluster-extention-8.png) - -具体操作如下: - -```SQL --- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 -migrate region 1 from 2 to 4 - --- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 -migrate region 2 from 3 to 5 - --- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 -migrate region 3 from 1 to 6 -``` - -迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 - -![](/img/cluster-extention-9.png) - - -## 2. 节点管理 - -节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 - -### 2.1 ConfigNode 节点维护 - -ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: - -* 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加2个 ConfigNode,使得集群中有3个 ConfigNode。 -* 集群故障恢复:1个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 - -> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有1或者3个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过3个 ConfigNode 会导致性能损失。 - -#### 2.1.1 添加 ConfigNode 节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-confignode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-confignode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-confignode.bat -``` - -参数介绍: - -| 参数 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -#### 2.1.2 移除 ConfigNode 节点 - -首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: - -```SQL -IoTDB> show confignodes -+------+-------+---------------+------------+--------+ -|NodeID| Status|InternalAddress|InternalPort| Role| -+------+-------+---------------+------------+--------+ -| 0|Running| 127.0.0.1| 10710| Leader| -| 1|Running| 127.0.0.1| 10711|Follower| -| 2|Running| 127.0.0.1| 10712|Follower| -+------+-------+---------------+------------+--------+ -Total line number = 3 -It costs 0.030s -``` - -然后使用 SQL 将 ConfigNode 移除,SQL 命令: - -```Bash -remove confignode [confignode_id] -``` - -### 2.2 DataNode 节点维护 - -DataNode 节点维护有两个常见场景: - -* 集群扩容:出于集群能力扩容等目的,添加新的DataNode进入集群 -* 集群故障恢复:一个DataNode所在机器出现故障,使得该DataNode无法正常运行,此时可以移除该DataNode,并添加新的DataNode进入集群 - -> ❗️注意,为了使集群能正常工作,在DataNode节点维护过程中以及维护完成后,正常运行的DataNode总数不得少于数据副本数(通常为2),也不得少于元数据副本数(通常为3)。 - -#### 2.2.1 添加DataNode节点 - -脚本命令: - -```Bash -# Linux / MacOS -# 首先切换到IoTDB根目录 -sbin/start-datanode.sh - -# Windows -# 首先切换到IoTDB根目录 -# V2.0.4.x 版本之前 -sbin\start-datanode.bat - -# V2.0.4.x 版本及之后 -sbin\windows\start-datanode.bat -``` - -参数介绍: - -| 缩写 | 描述 | 是否为必填项 | -| ------ | ------------------------------------------------ | -------------- | -| -v | 显示版本信息 | 否 | -| -f | 在前台运行脚本,不将其放到后台 | 否 | -| -d | 以守护进程模式启动,即在后台运行 | 否 | -| -p | 指定一个文件来存放进程ID,用于进程管理 | 否 | -| -c | 指定配置文件夹的路径,脚本会从这里加载配置文件 | 否 | -| -g | 打印垃圾回收(GC)的详细信息 | 否 | -| -H | 指定Java堆转储文件的路径,当JVM内存溢出时使用 | 否 | -| -E | 指定JVM错误日志文件的路径 | 否 | -| -D | 定义系统属性,格式为 key=value | 否 | -| -X | 直接传递 -XX 参数给 JVM | 否 | -| -h | 帮助指令 | 否 | - -说明:在添加DataNode后,随着新的写入到来(以及旧数据过期,如果设置了TTL),集群负载会逐渐向新的DataNode均衡,最终在所有节点上达到存算资源的均衡。 - -#### 2.2.2 移除DataNode节点 - -首先通过CLI连接集群,通过`show datanodes`确认想要移除的DataNode的NodeID: - -```SQL -IoTDB> show datanodes -+------+-------+----------+-------+-------------+---------------+ -|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| -+------+-------+----------+-------+-------------+---------------+ -| 1|Running| 0.0.0.0| 6667| 0| 0| -| 2|Running| 0.0.0.0| 6668| 1| 1| -| 3|Running| 0.0.0.0| 6669| 1| 0| -+------+-------+----------+-------+-------------+---------------+ -Total line number = 3 -It costs 0.110s -``` - -然后使用SQL将DataNode移除,SQL命令: - -```Bash -remove datanode [datanode_id] -``` - - -## 3. 负载均衡 - -Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 - -### 3.1 功能介绍 - -IoTDB 是一个分布式数据库,数据的均衡分布对集群的磁盘空间、写入压力的负载均衡有着重要作用,region 是数据在 IoTDB 集群中进行分布式存储的基本单元,具体概念可见[region](../Background-knowledge/Cluster-Concept.md)。 - -集群正常运行情况下,IoTDB 将会自动对数据进行负载均衡,但在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,可通过手动 Region 迁移精细化调整集群负载和运维。 - -下面是一次region迁移过程的示意图: - - -![](/img/region%E8%BF%81%E7%A7%BB%E7%A4%BA%E6%84%8F%E5%9B%BE20241210.png) - -### 3.2 注意事项 - -1. 推荐仅在 IoTDB 1.3.3 以及更高版本使用 Region 迁移功能。 -2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(iotdb-system.properties中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 -3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 -4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 - -### 3.3 使用说明 - -- **语法定义**: - - 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 - - ```SQL - migrateRegion - : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL - ; - ``` - -- **示例**: - - 将 region 1 从 DataNode 2 迁移至 DataNode 3: - - ```SQL - IoTDB> migrate region 1 from 2 to 3 - Msg: The statement is executed successfully. - ``` - - “The statement is executed successfully” 仅代表region迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 - -- **相关配置项**: - - - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 region 迁移速度。 - -- **耗时估算**: - - 如果迁移过程无并发写入,那么耗时可以简单通过 region 数据量除以数据传输速度来估算。例如对于 1TB 的 region,硬盘网络带宽和限速参数共同决定数据传输速度是 100MB/s,那么需要约 3 小时完成迁移。 - - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1.5来估算。 - -- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,region 所在共识组的状态会经历如下过程: - - 迁移开始前:`Running`,`Running`。 - - - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 - - - 缩容阶段:`Removing`,`Running`,`Running`。 - - - 迁移完成:`Running`,`Running`。 - - 以扩容阶段为例,`show regions`的结果可能为: - - ```Plain - IoTDB> show regions - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| - | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| - | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| - +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ - Total line number = 3 - It costs 0.003s - ``` - -- **阻塞写入**: - - IoTConsensus 的 region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 - - 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: - ```plain - IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" - Msg: The statement is executed successfully. - ``` diff --git a/src/zh/UserGuide/latest/User-Manual/Load-Balance_apache.md b/src/zh/UserGuide/latest/User-Manual/Load-Balance_apache.md new file mode 100644 index 000000000..0580404da --- /dev/null +++ b/src/zh/UserGuide/latest/User-Manual/Load-Balance_apache.md @@ -0,0 +1,703 @@ + + +# 集群维护 + +## 1. 核心概念 + +在进行集群维护操作前,需要理解 IoTDB 集群架构、序列分区、时间分区等相关概念。 + +### 1.1 名词汇总 + +|**名词**|**类型**|**解释**| +|---|---|---| +|ConfigNode|节点角色|管理节点,负责管理集群信息,包括分区信息的记录、负载均衡和操作调度与节点管理等功能。| +|DataNode|节点角色|数据节点,负责提供客户端的数据读写,全面管理数据和元数据,各个数据节点形成不同的副本组。| +|Database|元数据|数据库,不同数据库的数据物理隔离。| +|DeviceId|设备名|元数据树中从 root 到倒数第二级的全路径表示一个设备名。| +|SeriesSlot|序列分区槽|每个 Database 会对应固定个数的序列槽,包含其中序列的元数据。| +|TimeSlot|一个序列槽的一个时间分区槽|对应一个 SeriesSlot 内所有序列一个时间分区的数据。| +|DataPartition|数据分区槽|一个 SeriesSlot 加 一个 TimeSlot 对应一个 DataPartition| +|SchemaRegion|一组元数据分区|多个 SeriesSlot 的集合,DataNode 上的元数据管理引擎,提供对元数据的读写操作。| +|DataRegion|一组数据分区|多个 SeriesTimeSlot 的集合,DataNode 上的数据管理引擎,提供数据的读写操作。| +|ConfigNodeGroup|逻辑概念(共识组)|由集群中所有 ConfigNode 节点组成,通过共识协议维护一致的分区表信息。| +|SchemaRegionGroup|逻辑概念(共识组)|元数据副本组,包含元数据副本数个 SchemaRegion,管理相同的元数据,互为备份。| +|DataRegionGroup|逻辑概念(共识组)|数据副本组,包含数据副本数个 DataRegion,管理相同的数据,互为备份。是 IoTDB 集群吞吐能力的基础单元。| + +### 1.2 集群架构 + +IoTDB 集群由管理节点(ConfigNode)与数据节点(DataNode)构成,采用 MPP 架构实现大规模并行处理。其核心特性在于对元数据进行设备级分区,对数据则进行设备与时间的二维分区,从而保障了全面的可扩展性。 + +![](/img/cluster-extention-1.png) + +### 1.3 分区管理 + +#### 1.3.1 集群共识组 + +在 IoTDB 中,数据分区组(DataRegionGroup)和元数据分区组(SchemaRegionGroup)是读写负载的最小单元,通过**共识组**机制保证数据一致性。因此,集群扩容的本质即是增加数据分区,以提升并发能力与吞吐量。 + +![](/img/cluster-extention-2.png) + +#### 1.3.2 分区槽机制 + +在分区和负载调度上,IoTDB 引入了两类核心槽机制来支持扩容和高效分布式管理。 + +第一类是**序列分区槽(SeriesPartitionSlot)**,它是对时间序列进行纵向管理的机制。每个数据库持有固定数量的序列分区槽(默认 1000 个),每个时间序列通过序列分区算法被分配到唯一的序列分区槽进行管理。使用序列分区槽可以避免直接记录设备或时间序列级别的分区信息,从而显著降低 ConfigNode 内存开销。 + +![](/img/cluster-extention-3.png) + +第二类是**时间分区槽(TimePartitionSlot)**,它用于对时间序列数据进行横向切分。每个数据分区由一个序列分区槽和一个时间分区槽组合而成。当某个序列分区槽在特定时间分区槽下有数据时,就会生成对应的数据分区。 + +![](/img/cluster-extention-4.png) + +通过序列分区槽与时间分区槽的组合,IoTDB 能够在扩容时灵活增加数据分区组,实现数据的均衡分布和高效读写,从而提升整个集群的吞吐能力与可扩展性。 + +## 2. 集群扩容 + +当 IoTDB 集群因数据量或访问压力激增,出现 CPU、内存、磁盘或网络等资源瓶颈时,可通过本指南进行横向扩容,以提升集群整体性能与承载力。 + +### 2.1 实现原理 + +IoTDB 集群扩容的核心是增加 DataNode 节点,因为 DataNode 是处理读写请求的主要节点。其内部的数据分区(DataRegion)是承载负载的关键单元,扩容的本质即通过增加数据分区组来提升集群并发能力与吞吐量。 + +默认情况下,假设集群的元数据副本数为三,数据副本数为二,初次初始化时会创建集群总核数除以二的数据分区。如下图一个由3台2核服务器组成的集群,假设每个数据副本组的处理能力为1,那么该集群(包含3个数据副本组)的总吞吐能力为3。因此,将服务器数量由三台扩展为六台,集群由原来的三数据分区组扩容为六数据分区组,总吞吐能力也相应实现翻倍。 + +![](/img/cluster-extention-5.png) + +扩容后,客户端读写负载的均衡规则是旧节点可能同时处理老设备(集群中已存在的 DeviceId 的数据)和新设备(集群中不存在的 DeviceId 的数据)的数据读写,而新节点仅接收新增数据的读写,旧节点不会对原有副本组进行自动重均衡。数据负载均衡通常在每个新时间分区创建时进行,默认时间为每周四上午八点。其核心原理是通过序列分区槽和时间分区槽进行负载均衡算法运算,从而决定数据由哪个节点的哪个分区处理。 + +![](/img/cluster-extention-6.png) + +如果希望在扩容后进一步均衡历史数据,可按需执行 Region 迁移或 Region 重均衡:当需要精确指定 Region、源 DataNode 和目标 DataNode 时,可参考【4\. 手动 Region 迁移】;当希望系统自动计算迁移方案并完成整体均衡时,可参考【5\. 自动 Region 重均衡】。 + +### 2.2 操作步骤 + +#### 2.2.1 前置准备 + +1. 服务器环境检查,建议操作系统版本与原集群保持一致。 + +2. 数据库版本检查,建议版本与原集群版本保持一致。 + +3. 操作系统环境检查,保证所需端口不被占用,DataNode 会占用端口 6667、10730、10740、10750 、10760、9090、9190、3000请确保这些端口未被占用。 + + ```Shell + #如果命令有输出,则表示该端口已被占用。 + lsof -i:6667 或 netstat -tunp | grep 6667 + lsof -i:10710 或 netstat -tunp | grep 10710 + lsof -i:10720 或 netstat -tunp | grep 10720 + ``` + +4. 数据目录检查,确认服务器已挂载数据盘,建议将安装包放在数据盘目录下。 + +5. 软件依赖:安装 Java 运行环境 ,Java 版本 \>= 1\.8,请确保已设置 jdk 环境变量。 + +6. 域名配置:部署时推荐优先使用 hostname 进行 IP 配置,可避免后期修改主机 IP 导致数据库无法启动的问题。设置 hostname 需要在目标服务器上配置`/etc/hosts`,如本机 IP 是192\.168\.1\.3,hostname 是 iotdb\-1,则可以使用以下命令设置服务器的 hostname,并使用 hostname 配置 IoTDB 的 cn\_internal\_address、dn\_internal\_address、dn\_rpc\_address。 + +```Shell +# 注意:本机和原集群节点的域名都需要配置 +echo "192.168.1.3 iotdb-1" >> /etc/hosts +``` + +#### 2.2.2 扩容操作 + +1. 为确保您获取的 IoTDB 安装包完整且正确,在执行安装部署前建议您进行 SHA512 校验。 + +2. 解压安装包并进入安装目录 + +```Shell +unzip iotdb-{version}-bin.zip +cd iotdb-{version}-bin +``` + +3. 修改相应配置 + +```Shell +cd iotdb-{version}-bin/conf +vim iotdb-system.properies +``` + +|配置项|说明|默认|备注| +|---|---|---|---| +|dn\_seed\_config\_node|节点注册加入集群时连接的 ConfigNode 地址,即 cn\_internal\_address:cn\_internal\_port|127\.0\.0\.1:10710
|非常重要,强制修改此项,将其改为原集群 ConfigNode 主节点的地址
| +|dn\_rpc\_address|客户端 RPC 服务的地址|0\.0\.0\.0|按需修改,重启服务生效| +|dn\_rpc\_port|客户端 RPC 服务的端口|6667|按需修改,重启服务生效| +|dn\_internal\_address|DataNode 在集群内部通讯使用的地址|127\.0\.0\.1|按需修改,首次启动后不能修改| +|dn\_internal\_port|DataNode 在集群内部通信使用的端口|10730|按需修改,首次启动后不能修改| +|dn\_mpp\_data\_exchange\_port|DataNode 用于接收数据流使用的端口|10740|按需修改,首次启动后不能修改| +|dn\_data\_region\_consensus\_port|DataNode 用于数据副本共识协议通信使用的端口|10750|按需修改,首次启动后不能修改| +|dn\_schema\_region\_consensus\_port|DataNode 用于元数据副本共识协议通信使用的端口|10760|按需修改,首次启动后不能修改| + +4. 启动 DataNode 节点 + +进入 IoTDB 的 sbin 目录下,启动 Datanode: + +```Shell +./sbin/start-datanode.sh -d #“-d”参数将在后台进行启动 +``` + +5. 通过 CLI 命令连接原集群,进行扩容后验证 + +```Shell +# Linux 或 macOS系统 + ./iotdb-{version}-bin/sbin/start-cli.sh + + # Windows 系统 + ./iotdb-{version}-bin/sbin/start-cli.bat +``` + +6. 执行命令进行验证 + +执行`show datanodes`命令进行验证,预期结果列表中出现新加入的节点,且节点状态为 Running。 + +```Shell +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| +| 4|Running| 0.0.0.0| 6669| 1| 0| # 新加入节点 ++------+-------+----------+-------+-------------+---------------+ +Total line number = 4 +It costs 0.110s +``` + +7. 其他节点重复以上操作。新节点能够成功加入原集群的前提是原集群允许加入的 DataNode 节点数量足够,否则需要联系工作人员重新申请激活码信息。 + +#### 2.2.3 手动负载均衡(按需选择) + +默认情况下,扩容后历史数据不会自动迁移。若需进一步均衡各节点的数据分布,可选择以下方式: + +- 手动 Region 迁移:适用于已明确需要迁移的 Region、源 DataNode 和目标 DataNode 的场景,详见【4\. 手动 Region 迁移】。 + +- 自动 Region 重均衡:适用于扩容后希望系统自动选择迁移方案、整体均衡历史数据的场景,详见【5\. 自动 Region 重均衡】。 + +## 3. 节点管理 + +节点管理主要用于对集群中的 ConfigNode 和 DataNode 进行移除和添加,是保障集群高可用、实现负载均衡的基础运维操作。 + +### 3.1 ConfigNode 节点维护 + +ConfigNode 节点维护分为 ConfigNode 添加和移除两种操作,有两个常见使用场景: + +- 集群扩展:如集群中只有1个 ConfigNode 时,希望增加 ConfigNode 以提升 ConfigNode 节点高可用性,则可以添加 2 个 ConfigNode,使得集群中有 3 个 ConfigNode。 + +- 集群故障恢复:1 个 ConfigNode 所在机器发生故障,使得该 ConfigNode 无法正常运行,此时可以移除该 ConfigNode,然后添加一个新的 ConfigNode 进入集群。 + +> ❗️注意,在完成 ConfigNode 节点维护后,需要保证集群中有 1 或者 3 个正常运行的 ConfigNode。2个 ConfigNode 不具备高可用性,超过 3 个 ConfigNode 会导致性能损失。 +> +> + +#### 3.1.1 添加 ConfigNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-confignode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-confignode.bat + +# V2.0.4.x 版本及之后 +sbin\windows\start-confignode.bat +``` + +参数介绍: + +|参数|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +#### 3.1.2 移除 ConfigNode 节点 + +首先通过 CLI 连接集群,通过 show confignodes 确认想要移除 ConfigNode 的 NodeID: + +```SQL +IoTDB> show confignodes ++------+-------+---------------+------------+--------+ +|NodeID| Status|InternalAddress|InternalPort| Role| ++------+-------+---------------+------------+--------+ +| 0|Running| 127.0.0.1| 10710| Leader| +| 1|Running| 127.0.0.1| 10711|Follower| +| 2|Running| 127.0.0.1| 10712|Follower| ++------+-------+---------------+------------+--------+ +Total line number = 3 +It costs 0.030s +``` + +然后使用 SQL 将 ConfigNode 移除,SQL 命令: + +```Bash +remove confignode [confignode_id] +``` + +### 3.2 DataNode 节点维护 + +DataNode 节点维护有两个常见场景: + +- 集群扩容:出于集群能力扩容等目的,添加新的 DataNode 进入集群。 + +- 集群故障恢复:一个 DataNode 所在机器出现故障,使得该 DataNode 无法正常运行,此时可以移除该 DataNode,并添加新的 DataNode 进入集群 + +> ❗️注意,为了使集群能正常工作,在 DataNode 节点维护过程中以及维护完成后,正常运行的 DataNode 总数不得少于数据副本数(通常为 2),也不得少于元数据副本数(通常为 3)。 +> +> + +#### 3.2.1 添加 DataNode 节点 + +脚本命令: + +```Bash +# Linux / macOS +# 首先切换到 IoTDB 根目录 +sbin/start-datanode.sh + +# Windows +# 首先切换到 IoTDB 根目录 +# V2.0.4.x 版本之前 +sbin\start-datanode.bat + +# V2.0.4.x 版本及之后 +tools\windows\start-datanode.bat +``` + +参数介绍: + +|缩写|描述|是否为必填项| +|---|---|---| +|\-v|显示版本信息|否| +|\-f|在前台运行脚本,不将其放到后台|否| +|\-d|以守护进程模式启动,即在后台运行|否| +|\-p|指定一个文件来存放进程ID,用于进程管理|否| +|\-c|指定配置文件夹的路径,脚本会从这里加载配置文件|否| +|\-g|打印垃圾回收(GC)的详细信息|否| +|\-H|指定Java堆转储文件的路径,当JVM内存溢出时使用|否| +|\-E|指定JVM错误日志文件的路径|否| +|\-D|定义系统属性,格式为 key=value|否| +|\-X|直接传递 \-XX 参数给 JVM|否| +|\-h|帮助指令|否| + +说明:在添加 DataNode 后,随着新的写入到来(以及旧数据过期,如果设置了 TTL),集群负载会逐渐向新的 DataNode 均衡,最终在所有节点上达到存算资源的均衡。 + +#### 3.2.2 移除DataNode节点 + +首先通过 CLI 连接集群,通过`show datanodes`确认想要移除的 DataNode 的 NodeID: + +```SQL +IoTDB> show datanodes ++------+-------+----------+-------+-------------+---------------+ +|NodeID| Status|RpcAddress|RpcPort|DataRegionNum|SchemaRegionNum| ++------+-------+----------+-------+-------------+---------------+ +| 1|Running| 0.0.0.0| 6667| 0| 0| +| 2|Running| 0.0.0.0| 6668| 1| 1| +| 3|Running| 0.0.0.0| 6669| 1| 0| ++------+-------+----------+-------+-------------+---------------+ +Total line number = 3 +It costs 0.110s +``` + +然后使用 SQL 将 DataNode 移除,SQL 命令: + +```Bash +remove datanode [datanode_id] +``` + +## 4. 手动 Region 迁移 + +Region 迁移属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +### 4.1 功能介绍 + +IoTDB 是一个分布式数据库,Region 是数据在 IoTDB 集群中进行分布式存储的基本单元。集群正常运行情况下,IoTDB 会自动对新增数据进行负载均衡;在集群新加入 DataNode 节点、DataNode 所在机器硬盘损坏需要恢复数据等场景下,支持通过手动 Region 迁移精细化调整集群负载和运维。 + +### 4.2 注意事项 + +1. 推荐仅在 IoTDB 1\.3\.3 以及更高版本使用 Region 迁移功能。 + +2. 仅在共识协议为 IoTConsensus、Ratis 时支持 Region 迁移(`iotdb-system.properties`中的`schema_region_consensus_protocol_class` 和 `data_region_consensus_protocol_class`)。 + +3. Region 迁移会占用硬盘和网络带宽等系统资源,推荐在低业务负载时进行。 + +4. 在理想情况下,Region 迁移不影响用户侧读写。特殊情况下,Region 迁移可能阻塞写入,这种情况的具体鉴别与处理方式见使用说明。 + +### 4.3 使用说明 + +- **语法定义**: + + 提交一个异步任务,将 region 从一个 DataNode 迁移到另一个 DataNode。 + + ```SQL + migrateRegion + : MIGRATE REGION regionId=INTEGER_LITERAL FROM fromId=INTEGER_LITERAL TO toId=INTEGER_LITERAL + ; + ``` + +- **语法示例**: + + 将 region 1 从 DataNode 2 迁移至 DataNode 3: + + ```SQL + IoTDB> migrate region 1 from 2 to 3 + Msg: The statement is executed successfully. + ``` + + “The statement is executed successfully” 仅代表 Region 迁移任务提交成功,不代表执行完毕。任务执行情况通过 CLI 指令`show regions`查看。 + +- **相关配置项**: + + - 迁移速度控制:修改`iotdb-system.properties`参数 `region_migration_speed_limit_bytes_per_second`控制 Region 迁移速度。 + +- **耗时估算**: + + - 如果迁移过程无并发写入,那么耗时可以简单通过 Region 数据量除以数据传输速度来估算。实际数据传输速度由硬盘、网络带宽和迁移限速参数共同决定。 + + - 如果迁移过程有并发写入,那么耗时会有所上升,具体耗时取决于写入压力、系统资源等多方面因素,可简单按无并发写入耗时×1\.5来估算。 + +- **迁移进度观察**:迁移过程中可通过 CLI 指令`show regions`观察状态变化,以 2 副本为例,Region 所在共识组的状态会经历如下过程: + + - 迁移开始前:`Running`,`Running`。 + + - 扩容阶段:`Running`,`Running`,`Adding`。由于涉及到大量文件传输,可能耗时较长,具体进度在 DataNode 日志中搜索`[SNAPSHOT TRANSMISSION]`。 + + - 缩容阶段:`Removing`,`Running`,`Running`。 + + - 迁移完成:`Running`,`Running`。 + + 以扩容阶段为例,`show regions`的结果可能为: + + ```Plain Text + IoTDB> show regions + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + |RegionId| Type| Status|Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + | 0|SchemaRegion|Running| root.ln| 1| 0| 1| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 2| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 0|SchemaRegion|Running| root.ln| 1| 0| 3| 0.0.0.0| 6668| 127.0.0.1| Leader|2024-04-15T18:55:17.691| + | 1| DataRegion|Running| root.ln| 1| 1| 1| 0.0.0.0| 6667| 127.0.0.1| Leader|2024-04-15T18:55:19.457| + | 1| DataRegion|Running| root.ln| 1| 1| 2| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + | 1| DataRegion| Adding| root.ln| 1| 1| 3| 0.0.0.0| 6668| 127.0.0.1|Follower|2024-04-15T18:55:19.457| + +--------+------------+-------+--------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+ + Total line number = 6 + It costs 0.003s + ``` + +- **阻塞写入**: + + IoTConsensus 的 Region 迁移不直接阻塞写入,但由于过程中需要阻塞 WAL 文件的清理,如果 WAL 文件堆积达到阈值`wal_throttle_threshold_in_byte`,那么当前 DataNode 会暂停写入,直到 WAL 文件恢复到阈值以下。 + + 如果迁移过程中由于 WAL 达到阈值造成写入报错(例如报错信息为 The write is rejected because the wal directory size has reached the threshold),可以将`wal_throttle_threshold_in_byte`调大到 500GB 或更大以允许继续写入。使用 SQL 语句: + + ```Plain Text + IoTDB> set configuration "wal_throttle_threshold_in_byte"="536870912000" + Msg: The statement is executed successfully. + ``` + +- + +### 4.4 场景示例 + +默认情况下,扩容后历史数据不会自动迁移。若需均衡各节点的数据分布,可手动迁移 Region。如下图所示,假设将旧节点 80 TB 的数据负载均衡至新节点,当单个 Region 的数据量为 1 TB,传输速度为 100 MB/s,迁移约需 3 小时完成。 + +![](/img/cluster-extention-8.png) + +具体操作如下: + +```SQL +-- 1. 将 Region-1 的副本数据从 DataNode-2 中迁移至 DataNode-4 中 +migrate region 1 from 2 to 4 + +-- 2. 将 Region-2 的副本数据从 DataNode-3 中迁移至 DataNode-5 中 +migrate region 2 from 3 to 5 + +-- 3. 将 Region-3 的副本数据从 DataNode-1 中迁移至 DataNode-6 中 +migrate region 3 from 1 to 6 +``` + +迁移完成后,系统中的 Region 数据将在旧节点与新节点之间重新分布,实现磁盘空间的均衡化与资源利用最优化。 + +![](/img/cluster-extention-9.png) + +### 4.5 补充语法(不推荐) + +> **注意:** `EXTEND REGION` 和 `REMOVE REGION` 属于 **高危** 运维指令,不推荐常规使用,生产环境请慎用。一般情况下,Region 迁移应使用 `MIGRATE REGION`;Region 重建应使用 `RECONSTRUCT Region`。 +> +> + +#### 4.5.1 Extend Region + +将一个或多个 Region 扩容到指定 DataNode。 + +- 语法定义: + + ```SQL + extendRegion + : EXTEND REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* TO targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 将 Region 1 扩容到 DataNode 3: + + ```SQL + IoTDB> extend region 1 to 3 + Msg: The statement is executed successfully. + ``` + +#### 4.5.2 Remove Region + +从指定 DataNode 上移除一个或多个 Region 副本。 + +- 语法定义: + + ```SQL + removeRegion + : REMOVE REGION regionIds+=INTEGER_LITERAL (COMMA regionIds+=INTEGER_LITERAL)* FROM targetDataNodeId=INTEGER_LITERAL + ; + ``` + +- 语法示例: + + 从 DataNode 2 上移除 Region 1: + + ```SQL + IoTDB> remove region 1 from 2 + Msg: The statement is executed successfully. + ``` + +## 5. 自动 Region 重均衡 + +Region 重均衡属于高级运维功能,具有一定操作成本,建议完整阅读后再使用该功能。如有疑问请联系 IoTDB 团队寻求技术支持。 + +> V2\.0\.10 起支持 +> +> + +### 5.1 功能介绍 + +Region 重均衡功能支持通过一条 SQL 提交重均衡任务,系统后台使用扩容均衡算法计算 Region 迁移方案,并由 ConfigNode 调度执行。该功能不局限于扩容场景,在未出现扩缩容的情况下,如果存在 Region 大小不均衡、节点间磁盘使用不均衡或写入负载集中在少部分 Region 等情况,也可以使用此功能。 + +`LOAD BALANCE` 本质上是由系统自动生成并执行一组 Region 迁移任务,适合进行整体重均衡;`migrate region` 则适合用户已经明确 RegionId、源 DataNode 和目标 DataNode 的精细化迁移场景。自动重均衡任务提交后,可通过 `SHOW MIGRATIONS` 观察实际生成的迁移任务和执行进度。 + +- 适用场景:扩容后希望历史 Region 自动迁移到新节点;节点间磁盘使用明显不均;部分 DataNode 写入压力较高,需要整体调整 Region 分布。 + +- 谨慎使用场景:业务高峰期、网络或磁盘 I/O 资源紧张时,建议先评估迁移带来的资源占用;如果需要精确控制某个 Region 的迁移路径,建议使用手动 Region 迁移。 + +### 5.2 LOAD BALANCE + +```SQL +-- 触发系统负载均衡(由系统自动选择目标节点) +LOAD BALANCE; + +-- 指定目标 DataNode 节点 ID,并执行负载均衡 +LOAD BALANCE TO DATANODES(*DataNodeId,DataNodeId*); +``` + +- **功能机制** + +向 ConfigNode 提交一个异步执行的全局或局部分布式均衡任务。任务触发后,集群 DataNode 会被划分为两类角色池,且数据物理迁移具备严格单向约束: + +- From 节点(源节点池):提供待迁移 Region 数据的节点 + +- To 节点(目标节点池):接收迁移数据的节点 + +- 单向迁移规则:数据仅允许从 From 节点单向迁移至 To 节点 + +- **参数说明** + +|参数|必填|说明| +|---|---|---| +|TO DATANODES|否|显式传入一个或多个 DataNodeId 列表(逗号分隔),传入的节点被划定为接收数据的 To 节点池,其余节点自动归属为提供数据的 From 节点池| + +- **默认行为** + +|执行方式|行为说明| +|---|---| +|不带参数 \(`LOAD BALANCE`\)|系统默认选择当前磁盘占用量最小的一个节点作为唯一的 To 节点| +|带参数 \(`LOAD BALANCE TO DATANODES(...)`\)|指定的节点被强行划定为接收数据的 To 节点池,其余节点为 From 节点池| + +- **预期结果** + +命令执行后,控制台将立即返回 `Msg: The statement is executed successfully.`。这仅表示 ConfigNode 成功受理了负载均衡任务并将测算生成的子任务编排入列,底层的海量物理迁移随即在后台异步展开。 + +- **配置项说明** + +在配置文件 `iotdb-system.properties` 中,可通过 `region_migration_speed_limit_bytes_per_second` 控制每个 DataNode 的 Region 迁移传输上限,单位为 byte/s,默认值为 `50331648`,约 48 MiB/s。业务繁忙时可适当降低该值,业务低峰期可适当调高;但不建议设置过低,否则迁移耗时会明显增加,甚至可能发生迁移阻塞。配置值小于等于 0 表示不限速;该参数仅对 IoTConsensus 协议生效,支持热加载。 + +### 5.3 SHOW MIGRATIONS + +由于平衡任务涉及数百 GB 级别的大文件跨节点流转,系统提供如下核心观测 SQL 获取具有细粒度状态指示的全局视图。该语句会返回当前集群内部正在执行的后台迁移任务清单,并以结构化列表展示任务状态、耗时和迁移进度。 + +```SQL +SHOW MIGRATIONS +``` + +- **结果集说明** + +|字段名|说明| +|---|---| +|ProcedureId|Procedure 唯一标识| +|RegionId|Region ID| +|Type|Region 类型| +|FromNodeId|源节点 DataNode ID| +|ToNodeId|目标节点 DataNode ID| +|CurrentState|当前状态(如 `REGION_MIGRATE_PREPARE`, `ADD_REGION_PEER`, `REMOVE_REGION_PEER` 等)| +|ProcedureStatus|Procedure 状态(如 RUNNING、FINISHED、FAILED 等)| +|SubmittedTime|任务提交时间| +|LastUpdateTime|最近更新时间| +|Duration|已耗时| +|Progress|迁移进度(已迁移文件数/总文件数)| + +例如: + +```SQL +IoTDB> show migrations ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 11| 5|DataRegion| 2| 3|CHECK_ADD_REGION_PEER| WAITING|2026-06-03T15:47:35.840|2026-06-03T15:47:35.966|31 second 169 ms|files 1/3, size 15.52 KB/15.61 KB| ++-----------+--------+----------+----------+--------+---------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +Total line number = 1 +It costs 0.004s +``` + +- Show Regions 联动状态观测 + +迁移过程中,相关 Region 的状态也会发生变化。以 2 副本集群为例,在 `SHOW MIGRATIONS` 显示某个任务正在执行时,执行 `show regions` 可观察到该 Region 经历如下状态变化: + +1. 稳态(迁移前): `Running`, `Running`。 + +2. 复制扩容过渡态: `Running`, `Running`, `Adding`(目标 To 节点新建 Region 副本并接收快照,处于 `Adding `状态,该状态不对外提供服务)。 + +3. 安全移除过渡态: `Removing`, `Running`, `Running`(目标节点追平数据变为 `Running`,原 From 节点变为 `Removing`进行删除回收)。 + +4. 新稳态(迁移后): 旧 Region 删除成功,重回 `Running` , `Running` 状态。 + +### 5.4 场景示例 + +以下示例模拟某个真实工业场景:随着业务数据持续增长,系统原有的“两台核心数据节点”配置需要扩展为具有更高吞吐量与存储余量的“三数据节点”架构,并使用双副本冗余(即 1C2D \-\> 1C3D 的平滑扩容)。集群初始为 1 个 ConfigNode 和 2 个 DataNode,新增 DataNode 3 后,通过自动 Region 重均衡让新节点承载部分历史 Region,从而缓解原有节点的存储压力。 + +![](/img/load-balance.png) + +以下 SQL 返回结果仅用于说明关键流程,部分输出为节选展示;实际返回结果会受集群规模、Region 数量、数据库名称、时间分区和节点地址等因素影响,请以实际运行结果为准。 + +1. 扩容前,通过 `show cluster` 查看集群节点,集群中只有 DataNode 1 和 DataNode 2。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +2. 扩容后,通过 `show cluster` 确认 DataNode 3 已加入集群,且状态为 Running。 + +```SQL +IoTDB> show cluster ++------+----------+-------+---------------+------------+--------+---------+ +|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo| ++------+----------+-------+---------------+------------+--------+---------+ +| 0|ConfigNode|Running| confignode-1| 10710| 2.0.10| 53e***| +| 1| DataNode|Running| datanode-1| 10730| 2.0.10| 53e***| +| 2| DataNode|Running| datanode-2| 10730| 2.0.10| 53e***| +| 3| DataNode|Running| datanode-3| 10730| 2.0.10| 53e***| ++------+----------+-------+---------------+------------+--------+---------+ +``` + +3. 执行 `LOAD BALANCE` 提交重均衡任务。该命令提交成功仅表示 ConfigNode 已受理任务。如果希望明确指定新节点作为迁移目标,可使用 `TO DATANODES` 指定目标 DataNodeId。 + +```SQL +IoTDB> LOAD BALANCE; + +-- 或者指定 DataNode 3 作为目标节点 +IoTDB> LOAD BALANCE TO DATANODE 3; +``` + +4. 通过 `show migrations` 观察后台迁移任务。此时控制台可看到正在排队与流转的子任务,例如多个 Region 副本正从 DataNode 1、DataNode 2 迁移至 DataNode 3。 + +```SQL +IoTDB> show migrations ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +|ProcedureId|RegionId| Type|FromNodeId|ToNodeId| CurrentState|ProcedureStatus| SubmittedTime| LastUpdateTime| Duration| Progress| ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +| 101| 3| DataRegion| 1| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.051|2026-06-03T16:29:25.159| 2 second 897 ms|files 8/96, size 24 GB/280 GB | +| 102| 5| DataRegion| 2| 3| CHECK_ADD_REGION_PEER| WAITING|2026-06-03T16:29:25.059|2026-06-03T16:29:25.163| 2 second 889 ms|files 5/72, size 18 GB/210 GB | +| 103| 4|SchemaRegion| 1| 3|CHECK_REMOVE_REGION_PEER| WAITING|2026-06-03T16:29:25.067|2026-06-03T16:29:26.807| 2 second 876 ms| | ++-----------+--------+------------+----------+--------+------------------------+---------------+-----------------------+-----------------------+----------------+---------------------------------+ +``` + +4. 迁移过程中,通过 `show regions` 可观察到目标节点上的 Region 进入 `Adding` 状态。此时,DataNode 3 会在本机文件系统中创建对应 Region 的目录;源 DataNode 会将本地持久化 TsFile 打包为快照,并通过跨网络 RPC 投递到 DataNode 3。以下仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion| Adding|root.industry| 8| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.691| Unknown| NaN| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +``` + +5. 当 DataNode 3 接收完快照,并回放迁移期间产生的 WAL 数据后,新副本进入 `Running` 状态;同时,原节点上的对应 Region 副本会被标记为 `Removing` 并进行删除回收。当 `show migrations` 返回空结果时,表示迁移任务已结束,当前没有正在执行的迁移任务。 + +```SQL +IoTDB> show migrations ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +|ProcedureId|RegionId|Type|FromNodeId|ToNodeId|CurrentState|ProcedureStatus|SubmittedTime|LastUpdateTime|Duration|Progress| ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ ++-----------+--------+----+----------+--------+------------+---------------+-------------+--------------+--------+--------+ +``` + +6. 再次查询 `show regions`,确认相关 Region 已迁移至目标节点,并回到 `Running` 状态。如下所示,部分 Region 副本迁移到 DataNode 3 后,DataNode 1、DataNode 2 和 DataNode 3 都继续承载历史 DataRegion。以下仍仅节选与本次重均衡相关的 DataRegion 行。 + +```SQL +IoTDB> show regions ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +|RegionId| Type| Status| Database|SeriesSlotNum|TimeSlotNum|DataNodeId|RpcAddress|RpcPort|InternalAddress| Role| CreateTime|TsFileSize|CompressionRatio| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +| 3|DataRegion|Running|root.industry| 8| 1| 2| host2| 6667| datanode-2|Follower|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 3|DataRegion|Running|root.industry| 8| 1| 3| host3| 6667| datanode-3| Leader|2026-06-03T16:26:45.691| 280 GB| 3.24| +| 5|DataRegion|Running|root.industry| 6| 1| 1| host1| 6667| datanode-1| Leader|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 5|DataRegion|Running|root.industry| 6| 1| 3| host3| 6667| datanode-3|Follower|2026-06-03T16:26:45.698| 210 GB| 2.86| +| 7|DataRegion|Running|root.industry| 7| 1| 1| host1| 6667| datanode-1|Follower|2026-06-03T16:26:45.717| 240 GB| 3.10| +| 7|DataRegion|Running|root.industry| 7| 1| 2| host2| 6667| datanode-2| Leader|2026-06-03T16:26:45.717| 240 GB| 3.10| ++--------+----------+-------+--------------+-------------+-----------+----------+----------+-------+---------------+--------+-----------------------+----------+----------------+ +```