整顿 | 尔悦
嘉宾 | 廖浩均
小 T 导读:近年来,随着各种新兴技术的倒退,物联网、工业互联网等行业取得了疾速倒退,由此产生的时序数据量也越来越宏大,通用大数据计划越来越难以为继,各种时序数据库产品应运而生,迁徙也成为企业面临的重难点操作之一。
相比于 TDengine,OpenTSDB 算是入场更早一些的“玩家”,基于 Hbase 的产品模式无利也有弊:为有 Hbase 根底服务的企业升高了门槛的同时,适度依赖 Hbase 也为性能、压缩成果加设了一个瓶颈。随着企业业务规模的不断扩大,监控零碎的部署老本和运行效率都会出现增长的态势,随着工夫的推移,OpenTSDB 的缺点所带来的负面效应将齐全超过侧面成果,顺丰科技的业务案例便印证了这一点。
此前,顺丰科技应用 OpenTSDB 作为全量监控数据存储计划,不仅运维和应用老本很高,性能上也越来越难以满足需要——日常大跨度和高频次查问曾经无奈满足以后业务倒退的需要,查问返回后果甚至须要十几秒。随着用户量的减少,反对较低 QPS 的 OpenTSDB 非常容易解体,一旦解体将导致整个服务都变为不可用状态。随后在调研过市面的时序数据库产品后,顺丰科技便决定向 TDengine 进行迁徙。
为了帮忙和顺丰科技一样有迁徙需要的企业,咱们举办了 TDengine 技术公开课,本文基于涛思数据联结创始人廖浩均主讲的《TDengine 技术底细分享——兼容 OpenTSDB》整顿,从具体的操作层面为大家答疑解惑。
一、从 OpenTSDB 迁徙到 TDengine 的注意事项
在做出迁徙决定之前,一些同学可能比拟关注的是 TDengine 对 OpenTSDB 的兼容度如何?这个问题要从两个维度来看,一是写入协定的全兼容,二是查问性能的全笼罩。前者来看,你无需扭转任何一行代码就能够将数据齐全写入到 TDengine 之中,非常简单不便。后者的话,咱们提供了 OpenTSDB 查问性能的齐全笼罩,然而 有两点须要留神,一是不提供 OpenTSDB 的查问语法反对,二是不提供等效元数据查问反对。
之所以不提供 OpenTSDB 的语法反对,起因总结起来次要在于三点:
首先,围绕上图 OpenTSDB 的一个查问表达式来看,整体语义绝对比较复杂,且查问语法表意能力弱,无奈应用其映射出残缺的查问能力。同时这套语法规定也不太合乎应用 SQL 的习惯,无奈满足一些非常复杂的利用查问,比方对于下方的 SQL 语句的查问:这是一个 from 词句的非相干查问,通过 Json 这种形式是没有方法表达出来的。
SELECT id, SUM(avg_conn)
FROM
(SELECT AVG(connection) as avg_conn, id
FROM t1 INTERVAL(10s)
GROUP BY id
)
GROUP BY id
其次,相比于 OpenTSDB,TDengine 提供的查问性能、聚合函数更加丰盛,还提供如 TWA、TRATE、LEASTSQUARES、TOP、BOTTOM、LAST_ROW 等,如果要匹配其查问语法的话,就不可能残缺地去应用 TDengine 所提供的所有查问性能了。第三,OpenTSDB 还在查问过程中提供了一种特地的插值机制,导致 TDengine 很难提供完全一致的查问后果。
除了语法层面不兼容外,在数据查问性能上,TDengine 对于元数据查问性能和局部其余的性能也并不提供反对,具体起因如下:
- OpenTSDB 应用接口 /api/stats 来监控集群的服务状态。而 TDengine 也有一套针对本身集群状态的监控机制,其与 OpenTSDB 的集群服务状态监测并不相同。
- /api/tree 是 OpenTSDB 特有的一个工夫线 / 工夫序列(time series)的层级化组织构造。TDengine 则采纳了“数据库→超级表→子表”的层级来组织和保护工夫线:即归属于同一个超级表的所有工夫线、所有子表在零碎外部物理上归属于同一个层级,即不同的子表之间并没有层级或者从属关系。如果你的确须要 OpenTSDB 的这种场景,能够通过标签(tags)的逻辑设计,来建设不同子表之间的逻辑层级关系。
除了上述的两点外,还有一个有区别的中央是 OpenTSDB 提供的“Rollup And PreAggregates”的非凡性能,简略来讲就是一个自动化的数据降采样机制,将写入零碎的数据依照预设的工夫窗口主动进行聚合,并将后果从新写入零碎中,该新写入后果对用户可见。这个机制的提出是为了解决原始数据查问性能问题,帮忙用户升高查询处理开销和响应工夫。
利用这个性能,用户能够将利用中相当比例的 standing query(为了周期性取得上报信息或监控面板刷新展现而收回的采样或聚合查问)转向查问降采样后的后果,因此可能取得极大的性能晋升。因为其将查问转化为数据读取操作。然而一个不言而喻的问题是,这种策略对利用具备侵入性,在某些场景下,比如说降采样后果并不满足查问要求的时候,又会要求利用去读取原始数据,再依照需要收回查问申请失去后果。
由此可见,“Rollup And PreAggregates”的毛病是对利用不通明,使利用解决逻辑变得极为简单且不足移植性,是时序数据库无奈提供高性能聚合查问状况下的斗争与折中,TDengine 在零碎性能层面暂不反对这种主动的降采样。
那 TDengine 的查问性能优化策略又是如何实现的?
TDengine 领有内嵌、对用户(利用)通明的块级别预计算模块(SMA),可能提供很高性能的查问响应,而且让利用查询处理逻辑更加简略。
上图为预计算的一个流程,红色和绿色为两个工夫线,数据写入时是两个工夫线混在一起进行的,进入到零碎之后同一个工夫线的数据被归属到了一起,每一个数据块在落盘时都会通过这样一个预计算的过程,这个过程是由落盘的线程负责驱动执行的。预计算的类型很简略,如图所示共有 count/max/min/sum 这四种,每一个 block 后面都有一个小的预计算模块,这个构造对用户和利用来说是通明的。
当咱们要收回一个查问时,举个例子,查问工夫区间从第 3 秒到第 13 秒,即上图中红线框住的局部,因为预计算自身是针对数据块级别来建设的,所以在读取预计算后果时,只有两头两块残缺的数据块是有意义的,这里只会读取预计算的块,而两侧的红框则须要读取实在的数据,计算引擎才会相应计算出一个后果。
然而实在数据绝对于预计算局部来说规模十分大,如果一个数据块中有 4000 条记录,在读取实在数据时要把这 4000 条都读出来,而如果有预计算能够应用的话,可能就只须要一个数字,比如说上图中的 Max,这种形式能够让 I/O 性能取得极大的晋升,从而能够无效升高查问过程中 I/O 压力。
TDengine 以这种内嵌反对机制保障高效的查询处理性能,而非聚焦在应用层、将复杂性留给用户。 总而言之,从 OpenTSDB 迁徙到 TDengine,你只需调整利用的读取局部代码和实现逻辑,就可能取得空谷传声的成果和收益,不仅可能应用更多更高效的查问与计算性能、还能取得更快的响应工夫和更低的存储资源开销,极大地升高软硬件部署老本。
二、你须要理解的两种写入形式
前文中提到,无需扭转任何一行代码就能够将写入 OpenTSDB 的过程调整为写入到 TDengine 之中,那这一点是如何做到的呢?这里有两种形式:一种是高级语言间接应用跨语言计划调用 C 接口写入,一种是间接调用 HTTP 接口采纳 RESTful 形式写入。
如上图所示,如果你的利用是应用 C#、Java、Rust、Python 等高级语言编写并写入数据,那你须要通过 TDengine 提供的库先进行下从新编译,再通过高级语言的连接器(connector)连贯 TDengine 的驱动(driver),将承载的逻辑封装到 driver 中,接下来通过一个名为 taos_schemaless_insert
的 C 语言接口解决所有的 OpenTSDB 的写入协定,采纳结构化的形式将数据间接写入 TDengine 中。
看到这里可能有一些同学会有疑难,为什么逻辑要封装到 driver 中,而不是放到高级语言中? 起因很简略,所有的高级语言都是间接跨语言调用接口,TDengine 并不提供各种高级语言原生的接口,如果在高级语言层面实现了 OpenTSDB 到 TDengine 语法的兼容解析以及转换写入的话,那么针对不同的高级语言都需实现如此简单的一套逻辑。而且思考到在生产环境下的具体利用场景,多线程的环境使问题变得更加简单,由此会产生很多边界状况须要解决。
因而咱们决定把这个逻辑下沉到 C 语言端,让所有的高级语言间接去驱动 C 语言的接口来实现调用,如此一来不仅能够极大地加重高级语言连接器的复杂程度,更有利于简化整个架构,从而放慢演进的速度。
以上就是高级语言采纳本地化接口方式写入数据的实现原理。如果你决定要采纳 RESTful 的形式,那就更简略了,你只须要改一下配置文件、端口和 IP 地址,同时部署一个名为“taosAdapter”的组件。
taosAdapter 是咱们最近开源的、用 Go 语言开发的一套 HTTP 服务,如上图所示,从用户侧角度来讲,当你写入各种 OpenTSDB 协定之后,能够间接 post 到 taosAdapter 凋谢的端口,taosAdapter 再利用底层的 driver 连贯 TDengine,间接实现数据写入的操作过程,无需用户再做任何操作。
三、应用 taosadapter 进行数据写入的具体实现
taosAdapter 架构
用户能够通过 JDBC-RESTful 包来应用 taosAdapter 提供的服务,也能够间接应用其提供的 HTTP 接口。具体的构造如上图所示,最底层是驱动层,顺次向上是 TDengine 的 go connector、connection pool、HTTP 模块。
taosAdapter 有以下的技术特点:
- 可与 TDengine 拆散部署
在介绍这个技术特点前,大家要思考一个问题。咱们都晓得 TDengine 自身是提供 HTTP 服务的,那为什么咱们又要开发出 taosAdapter 这样一个组件来接管 OpenTSDB 的数据?
首先,在数据写入过程中,消耗 CPU 资源最多的是数据的解析与转换(SQL → 二进制数据)操作,当然你能够应用动静绑定在肯定水平上升高 CPU 的耗费,然而这个水平十分无限。当你应用 Native 的形式写入时,SQL 的解析以及二进制的转换操作在客户端上就实现了,以 HTTP 的形式去写入则是将一个 SQL 语句间接 post 到服务器里去。为了升高服务器的累赘,咱们想到把这个操作从 TDengine 服务中分离出来。
这样一来,不仅能够无效地升高服务器的负载压力,还能够按需部署任意多台 taosAdapter 去写入数据 —— 比方你部署了两台 TDengine,采纳内嵌形式的话实际上也只能提供两个 HTTP 服务,然而却可能部署 4 台乃至 5 台 taosAdapter 进行数据写入。结合实际的写入负载,能够不受限于 TDengine 集群节点的数量,弹性地调整 taosAdapter 部署的节点数量,以最大水平满足写入的理论需要。
同时,因为 taosAdapter 自身是一个无状态的协定转换零碎,它是把 HTTP 的服务转换成 TDengine 外部的一个替换协定,并把数据写入到零碎外部的,这种无状态的操作使得它的 scale out 十分不便,可能高效率地进行 taosAdapter 集群弹性部署。 此外,还能极大地升高 TDengine 服务器自身的负载,节约更多的服务资源来撑持更大规模的查询处理。
- 反对 OpenTSDB 写入协定
采纳 HTTP 形式写入,对于写入利用来说是齐全通明的,你甚至不须要去做从新编译之类的任何操作,只须要调整一下写入利用的 IP:PORT,就能够将数据无缝写入到 TDengine。这里提到的 IP:PORT 是 taosAdapter 的服务端口,而非 TDengine 的,TDengine 内嵌的 HTTP 服务不反对 OpenTSDB 协定, 这是很重要的一点,在此跟大家阐明一下。
- 反对 OpenTSDB 数据分库并行写
家喻户晓,OpenTSDB 写入过程是没有数据库抉择概念的,TDengine 须要将数据写入到一个 database 里,这就延长出一个问题——应该往哪个库里写,咱们提出了一个解决方案,通过 taosAdapter 反对 OpenTSDB 数据分库并行写。
图 1
图 2
具体的操作如下面两张图所示。通过端口映射的形式,taosAdapter 让不同的利用将数据写入到不同的数据库。在 taosAdapter 的配置文件中能够配置多个端口,每个端口映射到不同的 TDengine 数据库,能够将利用的数据主动写入到不同的数据库中,匹配上读写权限之后就能够无效管制不同的零碎数据了。
上述的操作中,数据库须要由管理员事后手动建设(对写入利用通明),同时去调整配置文件,这个过程实现当前就能启动起来了,此时你的利用只需调整设置到正确的 IP 端口,数据就能够写入到正确的 DB 中了。
上图为分库并行写的具体流程,首先在 taosAdapter 中建设好端口到 DB 的映射配置表:6046:db1、6047:db2。以 6046 为例,零碎先将通过端口 6046 拿到的数据间接映射到 DB1,之后 taosAdapter 会设置与 TDengine 的连贯,将其所连贯的数据库切换到 DB1 数据库,继而进行数据写入,写入实现之后会对以后连贯关联的 DB 信息革除,即把此连贯复原成没有指定任何 DB 的状态。写入 6047 时是同样的原理,只不过数据是主动写入到 DB2,这就是分库并行写的具体实现。
以上就是对 taosAdapter 几个特点的剖析。接下来咱们看一下 TDengine 的无模式写入与一般 SQL 语句写入性能的差别。
下图是咱们做的一个简略比照,在 1000 万数据写入状况下,taosAdapter 的写入性能大略是一般 SQL 写入性能的 74.97%,也就是说如果你用一般 SQL 写入时能达到每秒 100 万的写入速度,替换成 taosAdapter 大略可能达到每秒 75 万这个级别。有这样一个比照的话,大家就可能评估大略部署哪种规模的零碎来撑持本身业务吞吐量了。
上面这张图展现的是在写入过程中 taosAdapter 的负载状况,黄色线条是 taosd,绿色线条是 taosAdapter。能够看到,taosAdapter 的 CPU 耗费比拟高,这次要是因为在做字符串相干的一些数值格局的转换变换所导致的。
四、写在最初
taosAdapter 以后反对的协定和数据写入格局也很丰盛,不仅反对 OpenTSDB 的 Json 和 telnet 协定,同时还反对 InfluxDB v1、statsd、collectd、tcollect、Icinga2、node exporter。 前面咱们会持续摸索 taosAdapter 对于其余的 exporter 的反对。
此外,将来咱们还会进一步优化 taosAdapter 的性能,目前 taosAdapter 对 CPU 的耗费还较高,前面将在可行的范畴内优化架构设计及性能:首先,通过外部的局部同步接口降级为异步接口调用,以晋升服务的性能,反对更高性能解决;其次,进一步优化它的解决逻辑,升高写入流程中的 CPU 开销。
⬇️点击下方图片查看流动详情,把 iPhone 13 Pro 带回家!