上一篇饭前饭后十分钟,入门HBase,我们了解了HBase的概念、适用场景、整体架构、以及工作原理等知识,现在我们来看看基于HBase的新玩意OpenTSDB。
1、OpenTSDB是什么?
OpenTSDB 是一款非常适合存储海量时间序列数据的开源软件,使用 HBase 作为存储让它变的非常容易扩展。
官方文档这样描述:OpenTSDB is a distributed, scalable Time Series Database (TSDB) written on top of HBase;
翻译过来就是,基于Hbase的分布式的,可伸缩的时间序列数据库。
近些年,随着IoT等概念的流行,时序数据库成为数据库一个相对独立的领域逐渐受到重视,广泛应用于物联网、监控系统、金融、医疗和零售等多种场景。
2、OpenTSDB的存储思路?
如上图所示,一条时间线由Metirc + 多个tag唯一确定,时间线上会有源源不断的数据点(Data Point)写入,数据点由时间戳和值组成。OpenTSDB支持秒级,毫秒级别,两种时间精度。
3、OpenTSDB的数据结构?
这个设计有几个特点:
-
metric和tag映射成UID,不存储实际字符串,用来节约空间。
-
每条时间线每一个小时的数据点归在一行,每列是一个数据点,这样每列只需要记录与这行起始时间偏移,以节省空间。
-
每列就是一个KeyValue,如果是毫秒精度,一行最多可以有3600000个KV,这里其实会有些问题,后面会讲到。
上图可以看出,一行由一个RowKey和多个Column构成,其中RowKey的具体格式如下↓
-
salt:打散同一metric不同时间线的热点,让各个存储节点的负载更均匀
-
metric, tagK, tagV:实际存储的是字符串对应的UID,映射关系在tsdb-uid表中
-
timestamp:每小时数据存在一行,记录的是每小时整点秒级时间戳
这是Column(HBase中称为qualifier)的格式,可以看到毫秒级需要多出2个字节。所以如果你的采集间隔不需要精确到毫秒级别,那请一定使用秒级,可以节省存储空间。Value由于只能存储整数或浮点,所以有一个bit存储Float flag。
4、OpenTSDB的整点压缩问题?
可以看到每个整点,都有一个尖峰,对底层的HBase集群会产生较大压力,什么原因呢?
-
为了节省存储空间和提高数据读取速度,OpenTSDB 内部有个数据压缩(即 Compaction)的机制,将设定的某个时间段内某个指标的所有数据压缩成单行,重新写到 HBase;
-
OpenTSDB 运行时默认把收到的数据(原始数据点)每秒1次的速度批量写到 HBase 上,然后会周期性的触发上面提到的数据压缩机制,把原始数据点拿出来,压缩后重新写回HBase,然后把原始数据点删除,这就虽然我们只往 OpenTSDB 写数据但大量的读和删操作还是会发生的原因;
-
OpenTSDB 默认的配置是以 3600 秒为区间压缩,实际运行时就是整点触发,这样整点发生的大量读、删操作,造成HBase的流量冲击就可以解释了。
5、如何解决整点压缩流程冲击问题?
-
禁用 OpenTSDB 的 Compaction 机制,这样 OpenTSDB 就变成了 1 个纯粹的写实例,数据读取速度会有牺牲,因为每次读取需要扫描更多的数据,这个对于业务数据量很大的系统来说可能并不合适;
-
想办法让 OpenTSDB 的数据压缩过程缓慢进行,这样到 HBase 的流量压力就会平缓很多,但是这样做还是有风险,因为如果从业务系统到 OpenTSDB 的流量暴涨仍然有可能会 HBase 压力过大,不过这就是另外1个问题了,HBase 需要扩容;
可以将 OpenTSDB 的源代中 src/core/CompactionQueue.java 中的 FLUSH_SPEED 常量修改为 1,重新编译即可。这样改动的实际影响是:默认压缩速度是 2 倍速,即最多半个小时内完成前 1 个小时数据的压缩,重新写回到 HBase,可以把这个调成 1 倍速,给它 1 个小时的时间来完成前 1 个小时数据的 Compaction,这样到 HBase 的流量会平缓很多。
看完这灵魂5问,大家也会对openTSDB以及HBase有了新的认识和理解了,有利于拓展老铁们的技术视野,增加知识广度,方便做架构设计和技术选型等等~
下篇文章,将会给大家介绍下“零拷贝”技术,看完后,会对操作系统IO、java NIO有新的体会,敬请期待~