2017云栖大会HBase专场,阿里巴巴高级技术专家悠你带来题为HBase在时间序列数据库中的应用的演讲。本文主要从时序数据和数据库说起,着重分享了HiTSDB针对时序场景的优化,最后分析了HBase作为底层存储的优势。
以下是精彩内容整理:
时序数据和时序数据库
时序数据就是分布在时间上的一系列数值。前一段时间,有一个人投诉,医生上班的时候不好好上班在炒股,其实是心电图,和股票很像,之所以容易造成误会,就是因为它们都是分布在时间上的一系列数值。还有我们现在炒得最火的,比如工业传感器数据、健康数据,把万物连在一起,包括灯、空调、机床设备、船只,都有一系列的传感器,这些东西全都会产生时序数据。
图为较更具体的例子。这是一个风电厂,里面会有很多风力发电机,我们只取最简单的两个参数,一是风力,一是发电功率,实际上一个典型的风机上有300到500个指标,我们只取两个指标,一个风力发电机两个传感器取指标。一个风力发电机有一系列的标签,比如说风场、型号,我们会给每个设备一个ID,当然我们还要标上风厂。
针对这些东西,我们会做很多的分析,可以分析在哪一个发电效率更高一些。还可以分析同一个厂商,哪一个风厂效率更高一些。我们还注意到这些时序数据有一个很强烈的特点,一个风力发电机上的一个传感器构成了一个时间序列,这个时间序列在不同的时间点上会有不同的数字,一个点发电功率是1800瓦,下一个时间点就是1900多瓦,这些发电机随着时间变化是比较小的,因此这一部分时间序列来说是比较稳定的,而这个时间点会不停地往后增加。比如说采样周期是1秒,每一秒钟就可以增加这么多时间点的值,所以膨胀得很快,而前面那部分相对稳定,这也是我们在这个时序场景上做优化的重要前提。
更具体的,实际上一个大型设备的参数会有好几千个,比如说上面有无数个阀门,有无数个泵,有很多个传感器。像车联网汽车,每个车上的传感器不可能像钻井平台那么多,但是车的数量是远远多过钻井平台,最后的时序数据数量是巨大的,再加上定时采样,我们能看到时序数据具有一些强烈的特点。数量巨大的数据源、持续产生大量数据,因为定时采样的情况下这些数据的产生是没有明显的波峰和波谷。大家的优化方式会不太一样,电商有一个典型的波峰和波谷,每年双十一会非常高,到凌晨一般会很低,我们可以利用这些东西来做一些批量的工作或者系统维护的工作,但是这对于时序的场景来说几乎是不存在的,尤其是IOT领域,因为传感器是机器,是24小时不停地工作。
时序序列数据跟时间有关,最近的数据最有价值,还有数据老化的需求,我们收集这些设备的数据首先要监控工作的稳定性,是不是存在故障,刚刚进系统的数据是最有价值的,老一些的数据也有价值,我们希望把老的数据老化掉来提高性能,所以有一个数据老化的需求。我们为了标识一个风力设备会打上很多标签,以及聚合/分析等。
时序数据和传统数据库的对比如图,我们有很多的设备、传感器,产生很多数据。如果规模不是特别大的厂家有几千个风机,每个风机有几百个指标,那么就会有一百万左右的时序数据,如果用采样每一秒会产生一百万个时间点,如果用传统数据库,那么每一秒会产生一百万次,持续地往MQ做一百万次,它会崩裂。
查询慢是因为我们实际上对时序数据查询时候,除了多维查询以外,我们还会额外地增加时间纬度,我们永远不会看一个设备从它装上去到现在的数据,我们会看一段时间的数据,比如说最近一个小时,永远是在一段时间的范围。如果映射到一个SQL模型上,SQL要针对这种多维的场景建一个联合索引,把你要查的东西索引进去,我们建的联合索引可以是风厂+厂商。如果加上时间就麻烦了,我们只能放在后面,放在前面必然不满足前缀时间,把时间按行保存在MYSQL的innoDB引擎里,用SQL语句做聚合/分析。
当我们用SQL来做时序时,我们的辅助索引会膨胀得非常厉害,这就带来了额外的问题,存储成本高,标签会重复存储,再加上索引膨胀的问题,如果直接映射到一个MYSQL的数据库里面,大规模的时序数据存储成本不可以接受,时间也不可以接受,所以我们需要一个专门的时序数据库来解决这个问题。
这是在HBase上的一个很典型的应用,基本上很巧妙地利用HBase的特点来存储和处理时间和序列数据。首先,改成了异步,提高了吞吐率,同时把所有的标签都ID化,所有的标签风机都是有限的,可枚举的,意味着可以存在一个独立的表里,然后转换成一个整形的ID,这样长度会大大缩短;其次,它把这些ID拼成一个Row Key,读数据的时候时间分成了两部分,一部分把你要查的时间段算出来,然后把所有的Row Key变成后缀,当你查询条件和Row key匹配是可以满足前缀条件的,可以把时间放在前面,另一部分,读了一行以后再用具体的时间去把后面的数值筛选出来,这是很好的平衡和读取性能。
我们在HBase里面经常遇到热点问题,我们把Tag直接转换成Row Key,很可能Tag存在非常严重的偏斜问题,这时候就会有严重的热点,实际上给row key加了一个salt,意味着把所有数据均匀打散,然后还利用了OpenTSDB的Row Scan,这也是它的一个很大缺点,因为你并不是永远查询条件满足前缀条件,但是Row Key格式是固定的,而你的查询有可能是不固定的,OpenTSDB是单点聚合,后面的HBase是一个集群。
HiTSDB针对时序场景的优化
HiTSDB核心技术做了三个优化,一是倒排索引,解决多维查询的性能问题,通过ID来查具体的数值,把一级索引变成二级索引;二是高压缩比缓存,针对时间序列场景的压缩算法,所有的时间序列上的数值都有两个元素构成,一是时间点,一是数值,大幅度提升读性能,合并以后写入,提升写性能;三是分布式聚合引擎,解决单点聚合的性能问题,综合来看,基本上能把一个时间点上的数值从两个8字节压缩到不到两个字节,为了解决单点聚合的问题,我们引入了分布式聚合引擎,大家可以想象一下,把流倒过来,这个流已经冰冻,现在解冻,我们依然可以用分布式的方法聚集到用户的反馈里面。
倒排索引
我们使用的是全内存架构,一般的IOT场景里面设备是比较固定的,传感器也是比较固定的,不会膨胀得很厉害,基本上可以在内存里面完全放得下来,而且内存的倒排在性能上比较好。尤其是全内存架构做交集会很快,我们可以快速地评估SET的大小。如果两个SET都很大,一部分结果是可以缓存下来的,如果没有变化则不需要两个SET再算一遍,持久化到Hbase,最后是MetaDate管理,因为所有东西都是有索引的,给用户一个很好的提示。
高压缩比缓存
它的关键在于除了提高了压缩率以外,还很大地提高了写入性能,我们写的时候先写入BinLOG,等一个窗口结束的时候再写HBase。比如说20分钟的窗口或者一小时的窗口,再写HBase,而不像原来来一个点就写一个点。
分布式聚合
并不是所有算法分布式能够聚合,采用流式架构,数据单向流动,一边读取一边计算,降低latency;大部分的简单计算可以分别计算,最后再聚合;只保留最低限度的中间结果,降低内存消耗;针对无法实现分布计算的算法,使用粗略计算来实现算法的分布式。
HBase作为底层存储的优势
HiTSDB的存储需求实际上都能归位树形结构的操作,KEY到value,有序的快速前缀扫描。LSM Tree,顺序写盘、快速写入,临近的ROW KEY往往具有相邻的存储位置,KEY到value比Btree略慢。我们基本的需求就是要一棵LSM Tree。
HiTSDB的进一步需求包括:
- 高可用,可以容忍单点服务器故障,快速故障检测/恢复时间;
- 线性扩容,读/写性能线性扩容,磁盘容量线性扩容;
- 高可靠,多副本;
- 低成本,分级存储。
HBase实际上为HiTSDB提供了高可用性、高写入性能、水平扩展性、数据可靠性、KEY—Value。