在上一篇文章中,我们介绍了运维监控场景下,如何从OpenTSDB迁移到TDengine。
如果应用特别复杂,或者应用领域并不是运维监控场景,本文将更加全面深入地介绍将OpenTSDB应用迁移到TDengine的高级话题。
其他场景的迁移评估与策略
1、TDengine 与 OpenTSDB 的差异
本节将详细介绍OpenTSDB与TDengine在系统功能层面上存在的差异。
读完本节之后,你可以全面地评估是否能将某些基于OpenTSDB的复杂应用迁移到TDengine上,以及迁移之后应该注意的问题。
TDengine Database当前只支持Grafana的可视化看板呈现,所以如果应用中使用的是其他看板(例如TSDash、Status Wolf等),那么暂时无法直接迁移到TDengine,需要将其重新适配到Grafana才可以正常运行。
截止到2.3.0.x 版本,TDengine Database只能够支持collectd和StatsD作为数据收集汇聚软件,当然后面会陆续提供更多的数据收集聚合软件的接入支持。如果收集端使用了其他类型的数据汇聚器,则需要适配到这两个数据汇聚端系统,才能正常写入。除了上述两个数据汇聚端软件协议以外,TDengine还支持通过 InfluxDB的行协议和OpenTSDB的数据写入协议、Json格式将数据直接写入,可以重写数据推送端的逻辑,使用TDengine支持的行协议来写入数据。
此外,如果应用中使用了OpenTSDB的以下特性,在迁移之前还需要了解以下注意事项:
/api/stats
:如果应用中使用了该项特性来监控OpenTSDB的服务状态,并在应用中建立了相关的逻辑来联动处理,那么这部分状态读取和获取的逻辑需要重新适配到TDengine。TDengine提供了全新的处理集群状态监控机制,来满足应用对其进行的监控和维护的需求。-
/api/tree
:如果依赖于OpenTSDB的该项特性来进行时间线的层级化组织和维护,那么便无法将其直接迁移至TDengine。TDengine采用了数据库->超级表->子表这样的层级来组织和维护时间线,归属于同一个超级表的所有的时间线在系统中同一个层级,但是可以通过不同标签值的特殊构造来模拟应用逻辑上的多级结构。 Rollup And PreAggregates
:采用了Rollup和PreAggregates,需要应用来决定在合适的地方访问Rollup的结果,在某些场景下又要访问原始的结果,这种结构的不透明性让应用处理逻辑变得极为复杂而且完全不具有移植性。我们认为这种策略是时序数据库无法提供高性能聚合情况下的妥协与折中。TDengine暂不支持多个时间线的自动降采样和(时间段范围的)预聚合,由于 其拥有的高性能查询处理逻辑,即使不依赖于Rollup 和 (时间段)预聚合计算结果,也能够提供很高性能的查询响应,而且让你的应用查询处理逻辑更加简单。Rate
: TDengine提供了两个计算数值变化率的函数,分别是Derivative(其计算结果与InfluxDB的Derivative行为一致)和IRate(其计算结果与Prometheus中的IRate函数计算结果一致)。但是这两个函数的计算结果与 Rate 有细微的差别,但整体上功能更强大。此外,OpenTSDB提供的所有计算函数,TDengine 均有对应的查询函数支持,并且TDengine的查询函数功能远超过OpenTSDB支持的查询函数,可以极大地简化应用处理逻辑。
通过上面的介绍,相信你应该能够了解OpenTSDB迁移到TDengine带来的变化,这些信息也有助于你正确地判断是否可以接受将应用迁移到TDengine之上,体验TDengine提供的强大的时序数据处理能力。
2、迁移策略
首先将基于OpenTSDB的系统进行迁移涉及到的数据模式设计、系统规模估算、数据写入端改造,进行数据分流、应用适配工作;之后将两个系统并行运行一段时间,再将历史数据迁移到 TDengine 中。当然如果你的应用中有部分功能强依赖于上述OpenTSDB特性,同时又不希望停止使用,可以考虑保持原有的OpenTSDB系统运行,同时启动 TDengine来提供主要的服务。
数据模型设计
一方面,TDengine 要求其入库的数据具有严格的模式定义。另一方面,TDengine 的数据模型相对于 OpenTSDB 来说又更加丰富,多值模型能够兼容全部的单值模型的建立需求。 现在让我们假设一个运维监控场景,我们使用了collectd收集设备的基础度量(metrics),包含了 memory、swap和disk 等几个度量,其在 OpenTSDB 中的模式如下:
序号 | 测量(metric) | 值名称 | 类型 | tag1 | tag2 | tag3 | tag4 | tag5 |
1 | memory | value | double | host | memory_type | memory_type_instance | source | |
2 | swap | value | double | host | swap_type | swap_type_instance | source | |
3 | disk | value | double | host | disk_point | disk_instance | disk_type | source |
TDengine要求存储的数据具有数据模式,即写入数据之前需创建超级表并指定超级表的模式。对于数据模式的建立,有两种方式来完成此项工作:
1)充分利用TDengine对OpenTSDB的数据原生写入的支持,调用TDengine提供的API将(文本行或 JSON 格式)数据写入,并自动化地建立单值模型。采用这种方式不需要对数据写入应用进行较大的调整,也不需要对写入的数据格式进行转换。 在C语言层面,TDengine提供了taos_insert_lines来直接写入OpenTSDB格式的数据(在2.3.x 版本中该函数对应的是 taos_schemaless_insert )。其代码参考示例请参见安装包目录下示例代码 schemaless.c。
2)在充分理解TDengine数据模型的基础上,结合生成数据的特点,手动建立OpenTSDB到TDengine的数据模型调整的映射关系。TDengine能够支持多值模型和单值模型,考虑到OpenTSDB均为单值映射模型,这里推荐使用单值模型在TDengine中进行建模。
- 单值模型
具体步骤如下:将度量(metrics)的名称作为 TDengine 超级表的名称,该超级表建成后具有两个基础的数据列—时间戳(timestamp)和值(value),超级表的标签等效于 度量 的标签信息,标签数量等同于度量 的标签的数量。子表的表名采用具有固定规则的方式进行命名:metric + '_' + tags1_value + '_' + tag2_value + '_' + tag3_value ...
作为子表名称。
在TDengine中建立3个超级表:
create stable memory(ts timestamp, val float) tags(host binary(12),memory_type binary(20), memory_type_instance binary(20), source binary(20));
create stable swap(ts timestamp, val double) tags(host binary(12), swap_type binary(20), swap_type_binary binary(20), source binary(20));
create stable disk(ts timestamp, val double) tags(host binary(12), disk_point binary(20), disk_instance binary(20), disk_type binary(20), source binary(20));
对于子表使用动态建表的方式创建如下所示:
insert into memory_vm130_memory_bufferred_collectd using memory tags(‘vm130’, ‘memory’, 'buffer', 'collectd') values(1632979445, 3.0656);
最终系统中会建立 340 个左右的子表,3个超级表。需要注意的是,如果采用串联标签值的方式导致子表名称超过系统限制(191字节),那么需要采用一定的编码方式(例如 MD5)将其转化为可接受的长度。
- 多值模型
如果想利用TDengine的多值模型能力,需要首先满足以下要求:不同的采集量具有相同的采集频率,且能够通过消息队列同时到达数据写入端,从而确保使用SQL语句将多个指标一次性写入。将度量的名称作为超级表的名称,建立具有相同采集频率且能够同时到达的数据多列模型。子表的表名采用具有固定规则的方式进行命名。上述每个度量均只包含一个测量值,因此无法将其转化为多值模型。
数据分流与应用适配
从消息队列中订阅数据,并启动调整后的写入程序写入数据。
数据开始写入持续一段时间后,可以采用SQL语句检查写入的数据量是否符合预计的写入要求。
统计数据量使用如下SQL语句:
select count(*) from memory
完成查询后,如果写入的数据与预期的相比没有差别,同时写入程序本身没有异常的报错信息,那么可用确认数据写入是完整有效的。
TDengine不支持采用OpenTSDB的查询语法进行查询或数据获取处理,但是针对OpenTSDB的每种查询都提供了对应的支持。具体可以参考相关文档。
TDengine支持以标准的JDBC 3.0接口来操纵数据库,也可以使用其他类型的高级语言的连接器来查询读取数据,以适配应用。具体的操作和使用帮助也请参阅用户手册。
历史数据迁移
1、使用工具自动迁移数据
为了方便历史数据的迁移工作,我们为数据同步工具DataX提供了插件,能够将数据自动写入到TDengine中,需要注意的是DataX的自动化数据迁移只能够支持单值模型的数据迁移过程。 DataX 具体的使用方式及如何使用DataX将数据写入TDengine请参见其使用帮助手册 github.com/taosdata/datax。
2、手动迁移数据
如果需要使用多值模型写入数据,就需要自行开发一个将数据从OpenTSDB导出的工具,然后确认哪些时间线能够合并导入到同一个时间线,再将可以同时导入的时间通过SQL语句写入数据库中。
手动迁移数据需要注意以下两个问题:
1)在磁盘中存储导出数据时,磁盘需要有足够的存储空间以便能够充分容纳导出的数据文件。为了避免全量数据导出后导致磁盘文件存储紧张,可以采用部分导入的模式,对于归属于同一个超级表的时间线优先导出,然后将导出部分的数据文件导入到TDengine系统中。
2)在系统全负载运行下,如果有足够的剩余计算和IO资源,可以建立多线程的导入机制,最大限度地提升数据迁移效率。考虑到数据解析对于CPU带来的巨大负载,需要控制最大的并行任务数量,以避免因导入历史数据而触发的系统整体过载。
由于TDegnine本身操作简易性,所以不需要在整个过程中进行索引维护、数据格式的变化处理等工作,整个过程只需要顺序执行即可。
当历史数据完全导入到TDengine以后,此时两个系统处于同时运行的状态,之后便可以将查询请求切换到TDengine上,从而实现无缝的应用切换。