从 Hadoop 到 TDengine,我们走过的路和展望

小T导读:本文作者是一名来自广州某企业的架构师,主攻大数据和云原生方向。今天在这篇文章里,他想结合近些年的工作经验,讲讲为何以及如何在物联网大数据项目中落地 TDengine Database,希望能给大家一些启示和有意义的参考。

一次调侃

在认识 TDengine 之前,我一直都在做工业互联网项目,其中的一些工作,包含数据从应用层到大数据库的汇总、分析计算,以及反馈应用层需要的业务报表数据。

例如计算平均每分钟的功率曲线、统计每分钟的用电量、对比不同设备乃至厂区的耗能情况,这里面既有实时流计算也有批处理。

如果把大数据系统作为一个中台型服务,它对应用层暴露的仅仅是 HTTP 形式的查询接口,背后需要涵盖很多技术组件,例如将 Hadoop 的 HDFS/Hive 做原始数据保留、使用 HBase 保存计算后的数据、利用消息中间件 Kafka 同步各类数据库,计算框架是使用 Flink 还是 Spark、分布式协调上选择 ZooKeeper。

因此,整个框架技术组件看起来非常的”重”,一方面体现在你需要对 Hadoop 的技术组件非常熟悉:例如数据均衡备份冗余策略、Hive 分区策略、HBase 的 key 设计规则;另一方面则体现在业务规则的不好把控和适应:以每分钟的功率计算为例,开始是取该分钟间隔内的最后一个数值,后来改成取该分钟内的平均数值,凡此种种需要大数据系统从 ods 层面重新进行计算,会带来非常大的开发工作量。

项目经理经常调侃,”就是展示几条曲线,几个数据而已,为什么要那么复杂?”

一篇文章

在调侃之余,我们开发人员也在思考,其实工业互联网以设备为主线,统计的都是一段时间内单个设备的数据,难道就没有一个能够很好地强调物联网时序场景的大数据软件吗?

一次偶然机会,我在朋友圈看到了这篇文章——《比 Hadoop 快至少 10 倍的物联网大数据平台,我把它开源了》,再结合搜索引擎的这几个关键字——”秒杀 Hadoop””分布式集群””开源”,马上就吸引了我的注意,点进去一看,真的大有相见恨晚的感觉。

因为 TDengine Database 的优势完全可以解决我们的痛点——以设备数据模型创建超级表,以设备为单个子表,按时间先后顺序连续存储数据。在查询的时候,可以提供预计算的统计数据,可以基于设备单个子表的 tag 做聚合的功能,结合流计算中的滑动窗口、滚动窗口概念,还可以快速地基于原始数据得到聚合统计结果。

此外,TDengine 还支持分布式集群部署,避免单点故障,提升存储计算能力。更重要的是,这个集群功能也是开源的!开源核心功能意味着不用担心以后给人卡脖子,也意味着会有一个优秀的开源社区伴你同行。

启航扬帆

心动不如行动,接下来我们团队立马着手在新的物联网项目上,按照”安装->应用集成(读写)->应用部署”的三部曲,正式使用上了 TDengine Database。


它的安装包十分小巧,只有 10M 左右,借助于官方文档,Linux 系统下的集群部署也很简单。接下来,配置好主机名、域名解析、暴露的端口、运行程序,过程非常顺滑,立马就能使用了。对比之前的 Hadoop 技术栈,这对运维团队来说简直就是福音!


在和应用集成方面,TDengine 支持 JDBC-JNI 和 HTTP RESTful 两种方式读写数据,我们采取 JDBC-JNI 结合 Mybatis 的方式,本地开发的时候,需要安装对应版本的 TDengine-client。另外,设计好超级表后,子表在首次写入的时候同时创建。


对应于我们三节点(24 核,62G)的集群,程序轻轻松松就达到 qps 每秒 1 万记录的写入性能。至于查询性能,以当天的功率曲线为例,按照 1 分钟 1 个记录,总共 1440 个计算数据计算,可以轻松地在 1 秒钟内通过 1 句 SQL 聚合当天 1 万条记录而得到;还有每月的日温度曲线,总共 30 个计算数据,当月的 30 万条记录,也可以通过 avg 函数结合 Interval 在秒级查询的时间间隔内返回!


最后是应用部署,因为我们的程序采用容器化的方式运行和管理,所以需要简单基于 Linux 镜像安装对应版本的 TDengine-client 生成基础镜像,再提供给应用程序使用。期间,我们遇到问题都是在GitHub(https://github.com/taosdata/TDengine)上提交 issue,很快就有 TDengine 的官方伙伴回复,在社区群也有技术支持人员以及其他热心开发者帮忙解答。

两篇文章

项目运行一段时间后,我们团队在客户端连接高可用方面也尝试着进行了思考和改进。实际场景下,我们会依据数据需求动态增加节点,但是不希望应用程序也跟着改动连接地址,所以我们希望应用程序的连接域名不变。那么,怎么实现呢?

比如,连接域名 ‘td-prod-service:6030’,通过负载均衡服务进行 udp 转发(TDengine 的连接是走 udp 协议),随机分发连接请求到实际的三节点之一(prod-td-1:6030, prod-td-2:6030, prod-td-3:6030),之后,应用程序根据接收到的节点信息,和实际的节点发生连接。为了解决这个问题,我们曾和 TDengine 社区的官方小伙伴们进行很多互动交流,后来他们把这个做成了经典案例文章——《「GitHub问题精选」TDengine 如何做到客户端高可用?

再接着,我们又接到了应用适应客户时区进行统计的需求,这个需求的背景是因为我们的设备遍布全球,每个客户审阅自己设备的统计数据时,当然期望是以客户自己所在时区为维度进行统计。很幸运,TDegnine 不仅提供了时间窗口函数 interval,还支持偏移 offset(偏移必须小于间隔)。

首先,我们配置taos的系统时区为 “timezone UTC-12″(即地球最早的时区)。然后,当中国时区客户(Asia/Shanghai (CST, +0800))查询以天为间隔时,我们会偏移 4 个小时,例如, interval(1d, 4h);当美国时区客户(America/Los_Angeles(PST, -0800)查询以天为间隔时,我们会偏移 20 个小时,例如, interval(1d, 20h);

后来,TDengine 的社区技术支持人员也基于此做成了经典案例文章——《一文帮你掌握TDengine的降采样查询+跨时区统计》,当时我还没留意,是我的同事和我说“你看这个文章里的示范表叫 daluo(我的微信 ID 名字)”我才发现。当时,我的心情是十分惊喜的。

这两篇文章在解决我们问题的同时,进一步完善了 TDengine 自身与用户交互的技术资料,我们真正做到了在开源社区中合作共赢。

几点希望

未来,我们希望 TDengine 可以继续保持开源的态势,及时友好地解答用户的疑问,为社区繁荣以及中国的开源软件建设充当开路者。

同时,我们也希望 TDengine 的软件部署可以向容器化的方式靠拢。毕竟在当下云原生的时代,容器化已经是团队提升效率必不可少的利器。想象一下未来的场景,基于云计算的强大共享存储计算能力,以及可靠稳定的容器化编排环境 Kubernetes,开发者只需要简单的运行 K8s operator 就能运行 TDengine,然后实现版本的升级以及计算资源的随意调度,将给运维带来极大的便利。

此外,结合传统的数据仓库星形模型,我们也希望 TDengine 可以实现多表的联合查询统计。因为在设备的背后是业务,设备总是会关联具体的车间、客户、厂区,而我们可能无法把所有的业务属性一次性预先作为 tag 写入到子表中(虽然我们现在是这样做的),当有新的业务属性需要关联的时候,我们又需要去增加超级表的tag,然后更新到对应的设备子表数据。而实际上,tag 和设备数据更像是索引关系。所以,如果子表作为事实表可以随意和维度表进行关联统计查询,这又是一个多么美妙的场景!

最后,我们希望结合机器学习等框架,TDengine 可以衍生出自己的 “MapReduce” 作业框架,支持开发者在上面进行人工智能作业分析。

总结一下,就是希望 TDengine 可以在物联网大数据平台方向提供全栈的技术方案,为企业的提效降本提供扎实便利的技术基础,成为整个行业的事实标准。