天天看點

時間序列資料的存儲和計算 - 開源時序資料庫解析(二)

  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>&lt;metric&gt;&lt;timestamp&gt;&lt;tagk1&gt;&lt;tagv1&gt;&lt;tagk2&gt;tagv2&gt;...&lt;tagkn&gt;&lt;tagvn&gt;</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會是你的選擇。

歡迎掃碼加入釘釘群與我交流!

時間序列資料的存儲和計算 - 開源時序資料庫解析(二)