萬億級日志與行為數據存儲查詢技術剖析(續)——Tindex是改造的lucene和druid


五、Tindex

數果智能根據開源的方案自研了一套數據存儲的解決方案,該方案的索引層通過改造Lucene實現,數據查詢和索引寫入框架通過擴展Druid實現。既保證了數據的實時性和指標自由定義的問題,又能滿足大數據量秒級查詢的需求,系統架構如下圖,基本實現了文章開頭提出的幾個目標。

(點擊放大圖像)

Tindex主要涉及的幾個組件

Tindex-Segment,負責文件存儲格式,包括數據的索引和存儲,查詢優化,以及段內數據搜索與實時聚合等。Tindex是基於Lucene的思想重構實現的,由於Lucene索引內容過於復雜,但是其索引的性能在開源方案中比較完善,在數據的壓縮和性能之間做了很好的平衡。我們通過改造,主要保留了其必要的索引信息,比原有的Lucene節省了更多的存儲空間,同時也加快了查詢速度。主要改進有以下幾點:

1、高效壓縮存儲格式

對於海量行為數據的存儲來說,存儲容量無疑是一個不容忽視的問題。對於使用索引的方案來說,索引后的數據容量通常相對原有數據會有一定程度的膨脹。針對這類情況,Tindex針對索引的不同部分,分別使用了不同形式的壓縮技術,保障了能夠支持高效查詢的同時僅僅需要較少的容量。對於數據內容部分,使用字典的方式編碼存儲,每條記錄僅僅存儲文檔編號。對於字典本身的存儲,使用了前綴壓縮的方式,從而降低高基數維度的空間消耗。實際情況下,使用 Tindex 壓縮后的數據占用的存儲容量僅僅為原始數據的1/5左右。

2、列式倒排和正向索引的存儲

由於實際使用中,往往需要同時支持搜索和聚合兩種場景,而這兩種方式對於索引結構的需求是完全相反的。針對這兩種情況,Tindex結合了倒排索引和列正向索引這兩種不同類型的索引。對於倒排索引部分,使用字典和跳表等技術,實現了數據的快速檢索,而對於正向部分,則通過高效的壓縮技術,實現了對於海量行下指定列的快速讀取。同時,根據不同的情況,可以選擇性的只建立其中一種索引(默認情況對於每一列均會同時建兩種索引),從而節省大約一般的存儲空間和索引時間。

Tindex-Druid,負責分布式查詢引擎、指標定義引擎、數據的實時導入、實時數據和元數據管理以及數據緩存。之所以選擇Druid是因為我們發現其框架擴展性、查詢引擎設計的非常好,很多性能細節都考慮在內。例如:

  • 堆外內存的復用,避免GC問題;
  • 根據查詢數據的粒度,以Sequence的方式構建小批量的數據,內存利用率更高;
  • 查詢有bySegment級別的緩存,可以做到大范圍固定模式的查詢;
  • 多種query,最大化提升查詢性能,例如topN、timeSeries等查詢等等。

框架可靈活的擴展,也是我們考慮的一個很重要的元素,在我們重寫了索引后,Druid社區針對高基數維度的查詢上線了groupByV2,我們很快就完成了groupByV2也可見其框架非常靈活。

在我們看來,Druid的查詢引擎很強大,但是索引層還是針對OLAP查詢的場景,這就是我們選擇Druid框架進行索引擴展的根本原因。 另外其充分考慮分布式的穩定性,HA策略,針對不同的機器設備情況和應用場景,靈活的配置最大化利用硬件性能來滿足場景需要也是我們所看重的。

在開源的Druid版本上自研,繼承了Druid所有優點的同時,對查詢部分代碼全部重新實現,從而在以下幾個方面做了較大改進:

1、去掉指標預聚合,指標可以在查詢時自由定義:

對於數據接入來說,不必區分維度和指標,只需要定義數據類型即可,數據使用原始數據的方式進行存儲。當需要聚合時,在查詢時定義指標即可。假設我們要接入一條包含數字的數據,我們現在只需要定義一個float類型的普通維度。

2、支持多種類型:

不同於原生的Druid只支持string類型維度的情況,我們改進后的版本可以支持string, int, long, float、時間等多種維度類型。在原生的Druid中,如果我們需要一個數值型的維度,那么我們只能通過string來實現,這樣會帶來一個很大的問題,即基於范圍的過濾不能利用有序的倒排表,只能通過逐個比較來實現(因為我們不能把字符串大小當成數值大小,這樣會導致這樣的結果‘12’ < ’2’),從而性能會非常差,因為數值類型維度很容易出現高基維。對於改進后的版本,這樣的問題就簡單多了,將維度定義為對應的類型即可。

3、實現數據動態加載:

原有的Druid線上的數據,需要在啟動時,全部加載才可以提供查詢服務。我們通過改造,實現了LRU策略,啟動的時候只需要加載段的元數據信息和少量的段信息即可。一方面提升了服務的啟動時間,另外一方面,由於索引文件的讀取基本都是MMap,當有大量數據段需要加載,在內存不足的情況,會直接使用磁盤swap Cache換頁,嚴重影響查詢性能。數據動態加載的很好的避免了使用磁盤swap Cache換頁,查詢都盡量使用內存,可以通過配置,最大限度的通過硬件環境提供最好的查詢環境。

HDFS,大數據發展這么多年,HDFS已經成為PB級、ZB級甚至更多數據的分布式存儲標准,很成熟了,所以數果也選用HDFS,不必重新造輪子。Tindex與HDFS可以完美結合,可以作為一個高壓縮、自帶索引的文件格式,兼容Hive,Spark的所有操作。

Kafka/MetaQ,消息隊列,目前Tindex支持kafka、MetaQ等消息隊列,由於Tindex對外擴展接口都是基於SPI機制實現,所以如有需要也可以擴展支持更多的消息隊列。

Ecosystem Tools,負責Tindex的生態工具支持,目前主要支持Spark、Hive,計划擴展支持Impala、Drill等大數據查詢引擎。

支持冷數據下線,通過離線方式(spark/Hive)查詢,對於時序數據庫普遍存在的一個問題是,對於失去時效性的數據,我們往往不希望它們繼續占據寶貴的查詢資源。然后我們往往需要在某些時候對他們查詢。對於Tindex而言,可以通過將超過一定時間的數據定義為冷數據,這樣對應的索引數據會從查詢節點下線。當我們需要再次查詢時,只需要調用對應的離線接口進行查詢即可。

SQL Engine,負責SQL語義轉換及表達式定義。

Zookeeper,負責集群狀態管理。

未來還會持續優化改造后的Lucene索引,來得到更高的查詢性能。優化指標聚合方式,包括:小批量的處理數據,充分利用CPU向量化並行計算的能力;利用code compile避免聚合虛函數頻繁調用;與大數據生態對接的持續完善等等。

后續筆者還會深入講解每一部分的詳細實現原理及實踐經驗,敬請關注!如有凝問,可以加筆者微信happyjim2010,一起交流!

作者簡介

王勁,數果智能,創始人&CEO。
曾任酷狗音樂大數據技術負責人、大數據架構師,負責酷狗大數據技術規划、建設、應用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM