IoTDB 常见问题 Q&A 第二期
关于 IoTDB 的 Q&A
IoTDB Q&A 第二期来啦~我们将定期汇总社区讨论频繁的问题,并展开进行详细回答,通过积累常见问题“小百科”,方便大家使用 IoTDB。
Q1:集群扩容方法
问题
问题 1:当 IoTDB 集群的存储占用达到多少时,建议增加节点?是等到存储完全满,还是达到一半时就进行扩容?如果集群存储已满,是否需要手动进行数据清理,比如设置 TTL,还是可以直接忽略,只增加节点即可?
问题 2:目前使用三台服务器构建的集群配置了元数据 3 副本和数据 2 副本。现在想要将一年前的数据迁移到其他服务器上以释放空间,这个操作应该如何执行?
方案
(1)数据清理与扩容建议
自动数据清理:可以通过配置 TTL 自动清理过期数据,实现存储空间的自动回收。
扩容时机:建议根据集群存储资源的使用趋势和业务数据增长预期来决定扩容时机。一般而言,当存储利用率接近高水位线(例如 70%-80%)时,应考虑扩容以确保服务稳定性,而不是等到存储完全占满。
存储满时处理:若集群存储空间已满,建议优先通过设置 TTL 或其他方式清理无用数据。在此基础上,可以根据需求增加集群节点以提升存储能力。
(2)存储扩展方法
扩展磁盘:在当前集群负载正常的情况下,可以通过增加磁盘容量来扩展存储资源。IoTDB 支持多盘目录配置,可以灵活扩展存储能力。
(3)历史数据迁移操作
数据迁移步骤:对于需要迁移的历史数据,可以利用 IoTDB 的数据同步功能,将一年前的数据迁移至其他集群或服务器进行备份。
释放存储空间:迁移完成后,在当前集群中通过 TTL 配置清理已迁移的历史数据,从而释放存储空间。
操作注意事项:在进行数据迁移之前,确保目标服务器或集群具备足够的存储资源,并对迁移的关键步骤进行备份和测试,以确保数据安全和完整性。
Q2:GC 时间过长导致集群卡住
问题
我们的业务系统在 IoTDB 执行 GC 时遭遇了查询和写入操作的短暂卡顿。此外,IoTDB 在运行一段时间后,老年代内存占用过高,即使在停止大量写入操作后仅进行查询,内存回收仍然不力。大约 4 至 5 天后,系统会记录此日志,并在此期间变得卡顿。虽然可以通过定时重启来缓解,但我们想寻求避免重启的解决方案。
系统环境:
Java 版本:openjdk version "1.8.0_222-ea";
测点数量:352130;
DataNode MEMORY_SIZE:42G;
部署方式:单机部署
我们观察到 IoTDB 的 GC 时间过长,是否需要增加内存?当前使用的是 JDK 11 版本。
3. 在 IoTDB 1.3.2 版本和 JDK 17 环境下,我们的 130 GB 内存数据节点在处理 1.06 亿条时序数据时,GC 操作导致系统挂起。
问题分析
GC 耗时高: 垃圾回收(GC)过程耗时过长,影响了系统性能。
内存占用高: 系统内存占用过高,导致内存回收不力,影响系统稳定性。
解决方案
增加内存:考虑增加物理内存以缓解内存压力。
更新数据库:将 IoTDB 更新到最新版本,以利用可能的性能改进。
更新 JDK 并更换 GC 算法:
G1:适用于低停顿时间的用户场景。根据当前系统的运行情况收集性能监控信息,动态调整参数,以提供最合适的停顿时间或最大的吞吐量。
PS:适用于需要高吞吐量的用户场景。
优化查询操作:避免执行查询操作的查询范围过大。
关闭最新点缓存:如果没有查询最新点的需求可以关闭最新点缓存(enable_last_cache)以释放内存。
Q3:如何修改测点类型
问题
如果在数据插入时未指定属性值的类型,而后期需要将原本推断为 INT32 类型的数据强制转换为 TEXT 类型,应如何处理?
如果字段类型不支持直接修改,是否有其他方案可以实现字段类型的调整?
如何将设备某个属性的类型从 TEXT 更改为 LONG?
如何修改已存在数据序列的字段类型,例如将原本为 FLOAT 类型的字段修改为 INT 类型?
是否可以更改 timeseries 的数据类型,例如将 FLOAT 类型更改为 DOUBLE?
原因
IoTDB 不支持修改已经创建测点的类型。
方案
(1)如果不需要旧数据:
方案一:删除旧序列重新创建新元数据
删除旧序列,并在创建新元数据时手动指定目标数据类型,然后重新写入数据。
方案二:修改自动推断策略配置
删除旧序列,修改自动推断策略配置并重启服务,以实现自动创建新的目标类型元数据。
自动创建模式配置:
(2)如果需要旧数据:
使用 Select into + Cast:具体支持的转换规则详见官方文档:内置函数与表达式章节。
2. 导入导出工具:将数据导出 CSV 文件,修改类型后再重新导入目标类型一致的序列。
自定义程序:
TsFile 重写:调用 TsFile 写入 API 重写 TsFile。
Session 数据重写:查询旧数据,修改为指定类型后再批量写入到新测点。
Q4:数据备份方案
问题
管理数万设备,若每天为每个设备创建备份,将产生海量备份文件。是否有除了文件导出之外的其他数据备份方案?
想要实现整个 IoTDB 文件的备份,有哪些可行的方案?
IoTDB 是否提供了内置的备份和恢复工具?这些工具的使用文档在哪里可以找到?对于需要 24 小时不间断运行的系统,应如何进行数据备份?
在尝试按天导出数据进行备份时,遇到了内存不足的错误。即使将配置文件中的内存大小从 10G 增加到 12G,问题依旧存在。
如果查询本应返回无数据,却也报告内存不足,那么分批备份是否应该基于时间,还是根据测点数量预估内存?
原因及方案
数据备份方案如下:
物理备份(全量):使用本地升级备份工具(通过硬链接对原有数据进行备份),在执行备份之前,要确保系统已经停止运行。
逻辑备份:利用 pipe 将数据备份到另外的节点。
IoTDB 备份:在 TsFile 文件级别进行备份,备份操作将在 TsFile 刷盘时同步。
TimechoDB 备份:采用实时同步与文件同步相结合的方式进行备份。
恢复过程:通过反向开 pipe 写回数据,这些数据将被放入乱序区,随后系统将自动进行合并处理。
多级存储备份:根据不同的时间范围,采用多级存储策略来备份数据。
元信息和数据周期导出备份:
导出时如果内存不足,则需要调大 DataNode 的内存或者分批导出。
导出时会根据测点的数量来进行内存预估。建议按照设备分批导出,不推荐按照序列分批导出。
Q5:错误 - There are no available SchemaRegionGroup RegionGroups currently
现象
现象 1:
现象 2:系统遇到了一个持续增长的 schema_region 目录问题,导致频繁出现内存溢出(OutOfMemory)错误。在路径 data/datanode/consensus/schema_region 下,系统每分钟都会创建多个以“4747*”为模式的目录。目前有二十多个数据库,每次尝试重启数据库时,Java 虚拟机(JVM)就会报告内存不足的错误。
原因
自动扩展机制:在默认配置下,每个 DataBase 下的 Region 数量是在既定可控范围内的。默认配置下每个数据库将根据其数据量自动扩展 SchemaRegionGroup 和 DataRegionGroup。每个 DataNode 节点上最少会自动创建 1 个 SchemaRegionGroup ,而每个 DataNode 预期管理的 SchemaRegion 的最大数量为 1。每个 DataNode 节点上最少会创建 2 个 DataRegionGroup,预期管理的 DataRegions 的最大数量为 5。
DataBase 数量与 Region 关系:DataBase 的数量直接关系到 Region 的数量。例如,在 1C3D 的集群中,在 1 个 DataBase 下创建 n100 个设备/测点,和在 n100 个 DataBase 下分别创建 1 个测点,所创建的 Region 数量会有显著差异。每个 Region 至少会保留 32 MB 的 WAL Buffer,因此 Region 数量的增加会导致内存开销增大。
合理控制 Region 数量:DataRegion 作为副本组的基本单位,绑定了固定数量的内存和 CPU 线程资源(例如 WAL 的堆外内存、Memtable 的 flush 线程等)。因此,IoTDB 集群需要控制 DataRegion 的数量适中,避免因为 DataRegion 太少导致写入并行度下降、资源利用不充分,或因 DataRegion 太多导致线程数量爆炸、写入性能下降。
方案
降低内存使用量:通过降低各个模块的内存使用量,启动服务删除部分 DataBase 来恢复正常运行。
具体配置参数如下:
配置时可根据系统中的 DataRegion 数、SchemaRegion 数进行计算:wal_buffer_size_in_byte * DataRegion 数 + schema_region_ratis_log_appender_buffer_size_max * SchemaRegion 数 < OFF_HEAP_MEMORY * 0.8。
其中,保留 20% 堆外内存用于各模块中的临时使用。
调整建模:修改建模方案,尽量保证所有的序列建立在一个 DataBase 下,避免 Region 数量过多。
评论