存储空间降为MySQL的1/10,TDengine在货拉拉数据库监控场景的应用

2022-05-26 00:00:00 数据 数据存储 监控 采样 改造

目前DBA团队管理的数据存储包括MySQL、Redis、Elasticsearch、Kafka、MQ、Canal等,为了保证监控采样的实时性,我们自研的监控系统设置的采样间隔为10秒,这样每天都会产生庞大的监控数据,监控指标的数据量达到20亿+。前期由于管理实例少,监控数据量也少,所有数据都被存放到了MySQL中;之后随着管理实例越来越多,使用MySQL来存储规模日益庞大的监控数据越发力不从心,急需进行升级改造。结合实际具体需求,通过对不同时序数据库进行调研,终我们选择了TDengine,顺利完成了数据存储监控的升级改造。


一.

监控系统开发中遇到的问题



从存储路径来看,每种数据存储都分布在多个区域,每个区域将监控采样数据投递上报到消息总线,然后由消费程序统⼀消费,消费程序会将必要的告警数据更新到告警表,同时将监控原始数据存储到MySQL。比如,针对Redis这款数据存储,监控采样间隔设置10秒,那么每天实例采样次数就会达到3000万+,监控指标累计6亿+,数据量之庞大可见一斑。早期为了将数据存储到MySQL中,同时也能很好地支持监控绘图的使用,每⼀次实例监控采样时都会计算出该实例全量监控项采样数据,然后将本次采样的结果作为⼀条记录存储下来。

即使通过这样的优化处理,在做时间跨度大的监控绘图时,前端依然会出现延迟卡顿的问题,后端监控数据存储的MySQL也压力山大,经常满载,天天被吐槽。因此针对这种时间跨度大的查询,我们专门开发了⼀系列的数据聚合调度任务——按照不同的时间跨度,提前将10秒采集间隔的监控数据做好聚合,监控绘图程序再根据不同的时间跨度选取不同的聚合数据表绘图,以此解决长时间跨度监控绘图展示延迟卡顿的问题。


但这仍然治标不治本。为了压缩监控数据存储空间,原始10秒间隔的监控数据表只能归档保留3天时间的监控数据,但存储大小也将近有200GB, 加上与之相关的不同时间段的数据聚合表,存储一下子突破300GB。这还只是Redis监控数据的存储大小,加上其它数据存储的监控数据,至少需要1TB+空间的MySQL存储。


数据集合任务管理复杂、后期监控原数据回溯缺失、MySQL存储空间日益增长带来的隐患,都是亟待解决的问题。


二.

时序数据库选型



为了解决MySQL监控数据存储的问题,我们把注意力转移到了适合存储监控数据的时序数据库上。市面上各种时序数据库产品琳琅满目,有老牌的,也有后起之秀,经过⼀系列调研选型,我们选择了TDengine,主要是因为其具备的如下几大优点:

  • 采用分布式架构,可支持线性扩展
  • 数据存储压缩率超高
  • 集群模式支持多副本,无单点故障
  • 单机模式性能强悍
  • 安装部署维护简单
  • SQL⽀持时间维度聚合查询
  • 客户端支持RESTful API

值得一提的是,TDengine的SQL原生语法支持时间维度聚合查询,同时数据存储压缩率⾼存储空间小, 这两点直接切中了我们的痛点。落地后实测相同数据的存储空间只有MySQL存储空间的十分之⼀甚至更少。还有⼀个惊喜是,在现有监控数据存储(MySQL)顶不住的情况下,⼀台8C16GB的单机版TDengine轻松就抗下目前所有监控流量和存储压力,且运行稳定,基本没有故障。

三.

改造过程



TDengine用于存储监控数据的超级表设计原则就是简单高效,字段⼀般都比较少,每⼀种监控项类型(INT、FLOAT、NCHAR等)的数据存储都需要单独建立⼀个超级表,超级表⼀般都有关键的ts、type、value字段,具体监控项由type字段标识,加上必要的tag及少量其它字段构成。


之前监控数据存储在MySQL的时候,每条数据记录包含了该实例⼀次监控采样的所有监控项(25+)数据。如果采用通用的监控超级表设计原则,就需要改造采样的数据结构,改造方式有两种:

  • 改造监控数据投递的数据结构
  • 改造消费程序消费逻辑重组数据结构

但消费端有时效性要求,改造难度大,生产端涉及范围大阻力也不小。经过综合考量,后我们决定采用类似MySQL数据存储的表结构来设计超级表,这样的改造对原来系统入侵少,改造难度系数低,改造大致过程如下:

  • TDengine,每种数据存储的监控数据单独建库存放

taos> create database redis; 
taos> create database es;
... ... ...
  • TDengine,建超级表,以Redis为例


taos> use redis; 
taos> create table redis_node_meters (created_at TIMESTAMP, qps INT, . ..) TAGS (region NCHAR(10), cluster_name NCHAR(50), ip NCHAR(20), port INT, role NCHAR(15));
  • 监控数据消费,由于新增的实例节点是不确定的,比如Redis的节点资源是由Agent自动发现注册后自动进行监控指标采集,这时写入数据并不确定某个子表是否存在,就需要TDengine的自动建表语法来创建不存在的子表,若该子表已存在则不会建立新表只会写入数据。
 taos > INSERT INTO tablename USING redis_node_meters TAGS ('China', 't est', '127.0.0.3', 9200, 'master') VALUES ('2021-12-02 14:21:14', 6490 , ...)
  • 绘图展示,绘图程序没有安装客户端驱动,直接使用了TDengine提供的RESTful API,采用HTTP的方式进行数据查询。在SQL查询上大量使用了TDengine提供的时间维度聚合函数INTERVAL,长时间跨度的数据查询,只需要合理选择聚合间隔,基本都是毫秒级响应,保障了前端绘图的流畅稳定。


四.

改造后的落地效果



将监控的数据存储由MySQL改造为TDengine后,不仅顶住了监控数据增长所带来的压力,还节约了存储空间,成本压缩到了原来的十分之⼀甚至更低。历史原生监控数据可回溯时间也变得更长,之前存储3天原生数据及聚合数据的空间,现在可供原始数据存储45天。


此外,改造之后不再需要维护复杂的数据聚合调度任务,大幅降低了监控系统、监控数据管理复杂度,同时前端绘图数据查询也变得更加简洁高效。


五.

写在后



随着对TDengine越发深入的了解及经验累积,后续我们也会逐步考虑将货拉拉大监控系统、业务数据(行车轨迹)等时序数据均迁移至TDengine。为了方便有需要的朋友更好地使用TDengine,在此也分享一下我们的一些使用经验:

  • 由于TDengine不支持太复杂的SQL查询语法,在设计超级表tag的时候需要充分考虑清楚,目前只有tag的字段支持函数运算结果的分组(GROUP BY)查询,普通字段是不支持的。
  • 子表tag的值是可以改变的,但是同⼀个子表tag的值是唯⼀的,建议用子表tag的组合值来生成子表名。

在本次项目中,TDengine很好地帮助我们实现了降本增效,是一款值得尝试的时序数据库产品,未来也希望其能够发挥出越来越丰富的功能和特性,也期待我们之后能有更紧密深入的合作。
来源 https://www.modb.pro/db/235667

相关文章