kairosdb最初是从opentsdb 1.x版本fork出来的一个分支,目的是在opentsdb的代码基础上进行二次开发来满足新的功能需求。其改造之一就是支持可插拔式的存储引擎,例如支持h2可以方便本地开发和测试,而不是像opentsdb一样与hbase强耦合。在其最初的几个版本中,hbase也是作为其主要的存储引擎。但是在之后的存储优化中,慢慢使用cassandra替换了hbase,它也是第一个基于cassandra开发的时序数据库。在最新的几个版本中,已不再支持hbase,因为其存储优化使用了cassandra所特有而hbase没有的一些特性。
在整体架构上,和opentsdb比较类似,都是采用了一个比较成熟的数据库来作为底层存储引擎。自己的主要逻辑仅仅是在存储引擎层之上很薄的一个逻辑层,这层逻辑层的部署架构是一个无状态的组件,可以很容易的水平扩展。
在功能差异性上,它在opentsdb 1.x上做二次开发,也是为了对opentsdb的一些功能做优化,或做出一些opentsdb所没有的功能。我大概罗列下我看到的主要的功能差异:
可插拔式的存储引擎:opentsdb在早期与hbase强耦合,为了追求极致的性能,甚至自研了一个异步的hbase client(现在作为独立的一个开源项目输出:asynchbase)。这样也导致其整个代码都是采用异步驱动的模式编写,不光增加了代码的复杂度和降低可阅读性,也加大了支持多种存储引擎的难度。kairosdb严格定义了存储层的api interface,整体逻辑与存储层耦合度较低,能比较容易的扩展多种存储引擎。当然现在最新版的opentsdb也能够额外支持cassandra和bigtable,但是从整体的架构上,还不能说是一个支持可插拔式存储引擎的架构。
支持多种数据类型及自定义类型的值:opentsdb只支持numeric的值,而kairosdb支持numeric、string类型的值,也支持自定义数值类型。在某些场景下,metric value不是一个简单的数值,例如你要统计这个时间点的topn,对应的metric value可能是一组string值。可扩展的类型,让未来的需求扩展会变得容易。从第一第二点差异可以看出,kairosdb基于opentsdb的第一大改造就是将opentsdb的功能模型和代码架构变得更加灵活。
支持auto-rollup:目前大部分tsdb都在朝着支持pre-aggregation和auto-rollup的方向发展,opentsdb是少数的不支持该feature的tsdb,在最新发布的opentsdb版本中,甚至都不支持多精度数据的存储。不过现在kairosdb支持的auto-rollup功能,采取的还是一个比较原始的实现方式,在下面的章节会详细讲解。
不同的存储模型:存储是tsdb核心中的核心,opentsdb在存储模型上使用了uid的压缩优化,来优化查询和存储。kairosdb采取了一个不同的思路,利用了cassandra宽表的特性,这也是它从hbase转向cassandra的一个最重要的原因,在下面的章节会详细讲解。
本质上,opentsdb存储模型采用的uid编码优化,主要解决的就两个问题:
存储空间优化:uid编码解决重复的row key存储造成的冗余的存储空间问题。
查询优化:利用uid编码后tagkey和tagvalue固定字节长度的特性,利用hbase的fuzzyrowfilter做特定场景的查询优化。
kairosdb在解决这两个问题上,采取了另外一种不同的方式,使其不需要使用uid编码,也不存在使用uid编码后遗留的问题。先看下kairosdb的存储模型是怎样的,它主要由以下三张表构成:
datapoints: 存储所有原始数据点,每个数据点也是由metric、tags、timestamp和value构成。该表中一行数据的时间跨度是三周,也就是说三周内的所有数据点都存储在同一行,而opentsdb内的行的时间跨度只有一个小时。rowkey的组成与opentsdb类似,结构为<code><metric><timestamp><tagk1><tagv1><tagk2>tagv2>...<tagkn><tagvn></code>,不同的是metric, tag key和tag value都存储原始值,而不是uid。
rowkeyindex: 该表存储所有metric对应datapoints表内所有row key的映射,也就是说同一个metric上写入的所有的row key,都会存储在同一行内,并且按时间排序。该表主要被用于查询,在根据tag key或者tag value做过滤时,会先从这张表过滤出要查询的时间段内所有符合条件的row key,后在datapoints表内查询数据。
stringindex: 该表就三行数据,每一行分别存储所有的metric、tag key和tag value。
利用cassandra的宽表特性,即使不采用uid编码,存储空间上相比采用uid编码的opentsdb,也不会差太多。可以看下官方的解释:
在查询优化上,采取的也是和opentsdb不一样的优化方式。先看下kairosdb内查询的整个流程:
根据查询条件,找出所有datapoints表里的row key
如果有自定义的plugin,则从plugin中获取要查询的所有row key。(通过plugin可以扩展使用外部索引系统来对row key进行索引,例如使用elasticsearch)
如果没有自定义的plugin,则在rowkeyindex表里根据metric和时间范围,找出所有的row key。(根据列名的范围来缩小查询范围,列名的范围是(metric+starttime, metric+endtime))
根据row key,从datapoints表里找出所有的数据
相比opentsdb直接在数据表上进行扫描来过滤row key的方式,kairosdb利用索引表无疑会大大减少扫描的数据量。在metric下tagkey和tagvalue组合有限的情况下,会大大的提高查询效率。并且kairosdb还提供了queryplugin的方式,能够扩展利用外部组件来对row key进行索引,例如可以利用elasticsearch,或者其他的索引系统,毕竟通过索引的方式,才是最优的查询方案,这也是heroic相比kairosdb最大的一个改进的地方。
kairosdb的官方文档中有关于auto-rollup如何配置的章节,但是在讨论组内,其关于auto-rollup的说明如下:
总结来说,目前kairosdb提供的auto-rollup方案,还是比较简单的实现。就是一个可配置的单机组件,能够定时启动,把已经写入的数据读出后进行aggregation后再次写入,确实非常的原始,可用性和性能都比较低。
但是有总比没有好,支持auto-rollup一定是所有tsdb的趋势,也是能拉开功能差异和提高核心竞争力的关键功能。
上面主要分析了kairosdb,第一个基于cassandra构建的tsdb,那干脆继续分析下其他基于cassandra构建的tsdb。
ingest module: 处理数据写入。
rollup module: 做自动的预聚合和降精度。
query module: 处理数据查询。
相比kairosdb,其在数据模型上与其他的tsdb有略微差异,主要在:
引入了租户的维度:这是一个创新,如果你是做一个服务化的tsdb,那租户这个维度是必需的。
不支持tag:这一点上,是比较让我差异的地方。在大多数tsdb都基本上把tag作为模型的不可缺少部分的情况下,blueflood在模型上居然不支持tag。不过这有可能是其没有想好如何优化tag维度查询的一种取舍,既然没想好怎么优化,那干脆就先不支持,反正未来再去扩展tag是可以完全兼容的。blueflood当前已经利用elasticsearch去构建metric的索引,我相信它未来的方案,应该也是基于elasticsearch去构建tag的索引,在这个方案完全支持好后,应该才会去引入tag。
模型上的不足,blueflood不需要去考虑tag查询如何优化,把精力都投入到了其他功能的优化上,例如auto-rollup。它在auto-rollup的功能支持上,甩了kairosdb和opentsdb几条街。来看看它的auto-rollup功能的特点:
仅支持固定的interval:5min,20min,60min,4hour,1day。
提供分布式的rollup service:rollup任务可以分布式的调度,rollup的数据是通过离线的批量扫描获取。
从它14年的介绍ppt上,还可以看到它在未来规划的几个功能点:
elasticsearch indexer and discovery: 目前这个已经实现,但是仅支持metric的索引,未来引入tag后,可能也会用于tag的索引。
cloud files exporter for rollups: 这种方式对离线计算更加优化,rollup的大批量历史数据读取就不会影响在线的业务。
apache kafka exporter for rollups: 这种方式相比离线计算更进一步,rollup可以用流计算来做,实时性更加高。
总结来说,如果你不需要tag的支持,并且对rollup有强需求,那blueflood相比kairosdb会是一个更好的选择,反之还是选择kairosdb。
spotify在决定研发heroic之前,在opentsdb、influxdb、kairosdb等tsdb中选用kairosdb来替换他们老的监控系统的底层。但是很快就遇到了kairosdb在查询方面的问题,最主要还是kairosdb对metric和tag没有索引,在metric和tag基数达到一定数量级后,查询会变的很慢。所以spotify研发heroic的最大动机就是解决kairosdb的查询问题,采用的解决方案是使用elasticsearch来作为索引优化查询引擎,而数据的写入和数据表的schema则完全与kairosdb一致。
简单总结下它的特点:
数据存储模型与kairosdb一致,使用elasticsearch优化查询引擎。(这是除了influxdb外,其他tsdb如kairosdb、opentsdb、blueflood等现存最大的问题,是其核心竞争力之一)
不支持auto-rollup,这是它的缺陷之一。
如果你需要tsdb支持完整的数据模型,且希望得到高效的索引查询,那heroic会是你的选择。
欢迎扫码加入钉钉群与我交流!
