集群水平扩展架构:分片策略与元数据管理的工程分析
水平扩展的驱动力与约束
单机存储在三个维度存在扩展天花板。写入吞吐方面,单台服务器的写入TPS受限于磁盘IO带宽和CPU压缩能力,NVMe SSD环境下单机写入上限约100-300万TPS,SAS机械盘环境下约20-50万TPS。存储容量方面,单机磁盘容量受限于机箱槽位(通常8-24块磁盘),24块18TB硬盘的总容量约432TB,扣除RAID冗余后有效容量约300TB。高可用方面,单机存在单点故障风险,磁盘损坏、内存故障、电源中断均导致服务不可用。
水平扩展通过增加节点分散负载,但引入新的工程约束。数据分片导致跨节点查询——原本单机上的全表扫描变为多节点并行扫描后聚合,网络带宽成为新的瓶颈。元数据管理从本地内存查找变为跨节点协调,元数据服务自身的可用性成为新的单点风险。数据重平衡在节点增减时触发,大量数据迁移占用网络和磁盘资源,可能影响在线业务。时序数据库在分布式架构下需要逐一解决这些约束。
分片策略的优劣直接决定扩展性的上限。合理的分片策略使写入负载均匀分布、查询多数在分片内完成、数据迁移量最小化。不合理的分片策略导致写入热点(所有数据涌入同一分片)、查询扇出(每次查询扫描全部分片)、迁移风暴(节点增减触发大规模数据搬移)。
分片策略:时间维度与设备维度
时序数据的分片有两个自然维度:时间维度和设备维度(标签维度)。
按时间分片将数据按时间范围分配到不同节点。2024年1月的数据在节点A,2月在节点B,3月在节点C。优势是历史数据归档简单——按时间维度直接将旧数据节点整体下线或迁移到冷存储。劣势是写入热点:当前时间的数据全部写入同一节点,其他节点空闲。写入负载无法通过增加节点分散。
按设备分片通过对设备ID做哈希将数据分散到不同节点。设备1-1000在节点A,1001-2000在节点B,2001-3000在节点C。优势是写入负载均匀分布——所有节点同时接收不同设备的数据,写入TPS随节点数线性增长。劣势是时间范围查询需要跨所有节点扫描——查询"最近1小时所有设备平均温度"需要每个节点扫描本地数据并聚合,网络聚合开销不可忽略。
混合分片结合两个维度。先按设备哈希分到节点,再在节点内按时间分片。这是多数时序数据库采用策略:设备维度分片解决写入扩展性,时间维度分片解决存储生命周期管理(旧数据按时间分片归档)。
分片策略 | 写入扩展性 | 时间范围查询 | 设备范围查询 | 归档效率 | 热点风险 |
按时间分片 | 差(单节点写入) | 极好(单节点) | 差(全扇出) | 极好 | 高(当前节点) |
按设备分片 | 好(均匀分布) | 中(全扇出+聚合) | 好(单节点) | 差 | 低 |
混合分片 | 好(均匀分布) | 中(全扇出+聚合) | 中(多节点) | 好 | 低 |
按设备+时间 | 好 | 好(时间裁剪) | 好(设备定位) | 好 | 低 |
分片粒度:Vnode与Partition
分片粒度决定数据管理的最小单元。粒度太粗(一个节点管理大量设备数据)导致负载不均衡,单节点过载。粒度太细(一个设备的数据分布在多个节点)导致元数据膨胀和跨节点协调开销。
TDengine采用Vnode(虚拟节点)作为分片粒度。一个Vnode包含一组子表的数据,是数据存储和复制的最小单元。Vnode数量在创建数据库时指定,固定不变。一个物理节点上运行多个Vnode,Vnode到物理节点的映射由Mnode(管理节点)分配。
Vnode的设计优势在于数据本地性——同一Vnode内的子表数据存储在同一物理位置,跨子表聚合查询(同一超级表内多子表的聚合)在Vnode内部完成,不产生跨节点网络开销。当Vnode内的子表属于同一设备组(如同一产线的传感器),聚合查询效率极高。
负载均衡在Vnode层面实现。新节点加入集群后,Mnode将部分Vnode从负载高的节点迁移到新节点。迁移单位是Vnode而非单条数据,迁移过程中Vnode的数据文件整体复制,迁移完成后切换读写路由。Vnode的粒度设计使得数据迁移的单位开销可控——一个Vnode通常包含数GB至数十GB数据,迁移时间在分钟级。
元数据管理:Mnode的角色与瓶颈
集群元数据包括:数据库Schema定义、超级表和子表的注册信息、Vnode到物理节点的路由映射、用户权限信息。这些元数据需要在集群内一致,是协调写入和查询路由的基础。
TDengine采用Mnode(Management Node)管理元数据。Mnode是逻辑角色,可以部署在任意物理节点上。集群中通常部署3个Mnode(保证Raft协议的多数派可用),元数据通过Raft协议在Mnode间同步。
Mnode的潜在瓶颈在于子表注册的并发量。每个子表创建时需要在Mnode注册(分配Vnode路由),子表创建的TPS受限于Mnode的Raft日志提交速度。在子表数量达到百万级时,元数据的内存占用(每个子表注册信息约200-500字节)达到数百MB,元数据查询(子表路由查找)的延迟开始上升。
缓解策略是客户端缓存路由信息。客户端SDK在首次访问子表时从Mnode获取路由并缓存,后续写入直接发送到对应Vnode所在节点,不再每次查询Mnode。路由变更(Vnode迁移)时Mnode通知客户端更新缓存。这一设计将Mnode的查询压力从每条写入一次降低到首次访问+路由变更时更新。
负载均衡与热点处理
新节点加入集群触发数据重平衡。Mnode评估各节点负载(磁盘使用率、Vnode数量、写入TPS),将部分Vnode迁移到新节点。迁移过程中Vnode保持可读,写入暂时路由到其他副本。迁移完成后切换路由,旧Vnode删除。
热点设备检测是负载均衡的补充机制。当某个设备的写入量远超平均(如某台设备升级后采样频率提高10倍),对应Vnode的写入负载升高。Mnode通过监控各Vnode的写入QPS识别热点,可选策略是将热点Vnode的副本分布到不同物理节点,分散读取压力(写入仍然集中在主副本)。
集群规模分级与实践参考
集群规模 | 节点数 | Vnode数 | 适用场景 | 写入TPS | 存储容量 |
小集群 | 3节点 | 6-12 | 高可用验证、中小工厂 | 50-200万 | 10-50TB |
中集群 | 10-20节点 | 40-100 | 中型工厂、区域监控 | 500-2000万 | 100-500TB |
大集群 | 50+节点 | 200+ | 城市级物联网、大型工业 | 5000万+ | 1PB+ |
小集群(3节点)的核心目标不是扩展性而是高可用。3节点部署保证任一节点故障时集群仍可服务(Raft多数派=2)。Vnode副本数设为3,每个Vnode在3个节点上均有副本。写入TPS和存储容量不是瓶颈,适用中小规模场景。
中集群(10-20节点)是工业场景的主流规模。一座中型工厂(产线20-50条、设备5000-20000台、采样频率秒级),年数据量50-200TB,10节点集群提供500TB以上可用容量。写入TPS在500-2000万之间,满足工业高频采集需求。Mnode部署3个,其余节点专用于Vnode运行,元数据管理压力可控。
大集群(50+节点)面临元数据管理瓶颈和跨节点查询性能退化。50节点以上时,子表数量可能达到数百万,Mnode的元数据内存占用达到GB级。跨节点查询的扇出因子增大,聚合查询的协调节点网络带宽可能饱和。大集群通常采用联邦架构——多个中集群独立部署,通过全局查询层(如Trino)实现跨集群查询,避免单集群规模过大带来的管理复杂度。
弹性扩缩容的工程约束
扩容操作在线进行——新增节点加入集群不中断现有服务。但扩容过程的数据重平衡会占用网络带宽和磁盘IO,可能影响在线查询性能。实践中扩容通常在业务低峰期执行,分批次迁移Vnode(每次迁移10-20%),每批迁移后检查集群状态和查询延迟。
缩容操作风险更高——节点下线意味着该节点上的Vnode需要迁移到其他节点。如果该节点上的Vnode是某些子表的唯一副本(副本数=1),节点下线将导致数据丢失。缩容前必须确认所有Vnode在其他节点上有可用副本,通常做法是先将副本数提高到3,再逐步下线节点。
结语
集群水平扩展的工程复杂度不在分片策略的理论设计——按设备哈希分片+按时间分区是业界共识——而在运维实践的细节中。数据重平衡的带宽控制、元数据管理的扩展性曲线、跨节点查询的聚合优化、扩缩容的在线执行,每一项都需要精细的工程实现。时序数据库的集群规模选择不应追求"越大越好",而应匹配业务实际的数据量和写入吞吐需求。过度扩展引入的管理开销和资源浪费,往往比单机瓶颈更难处理。

























