時序數據庫連載系列: 時序數據庫一哥InfluxDB之存儲機制解析

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

InfluxDB 的存儲機制解析

本文介紹了InfluxDB對于時序數據的存儲/索引的設計。由于InfluxDB的集群版已在0.12版就不再開源,因此如無特殊說明,本文的介紹對象都是指 InfluxDB?單機版

1. InfluxDB 的存儲引擎演進

盡管InfluxDB自發布以來歷時三年多,其存儲引擎的技術架構已經做過幾次重大的改動, 以下將簡要介紹一下InfluxDB的存儲引擎演進的過程。

1.1 演進簡史

  • 版本0.9.0之前
    **基于 LevelDB的LSMTree方案**
  • 版本0.9.0~0.9.4
    **基于BoltDB的mmap COW B+tree方案**
  • 版本0.9.5~1.2
    **基于自研的 WAL + TSMFile 方案**(TSMFile方案是0.9.6版本正式啟用,0.9.5只是提供了原型)
  • 版本1.3~至今
    **基于自研的 WAL + TSMFile + TSIFile 方案**

1.2 演進的考量

InfluxDB的存儲引擎先后嘗試過包括LevelDB, BoltDB在內的多種方案。但是對于InfluxDB的下述訴求終不能完美地支持:

  • 時序數據在降采樣后會存在大批量的數據刪除
    => *LevelDB的LSMTree刪除代價過高*
  • 單機環境存放大量數據時不能占用過多文件句柄
    => *LevelDB會隨著時間增長產生大量小文件*
  • 數據存儲需要熱備份
    => *LevelDB只能冷備*
  • 大數據場景下寫吞吐量要跟得上
    => *BoltDB的B+tree寫操作吞吐量成瓶頸*
  • 存儲需具備良好的壓縮性能
    => *BoltDB不支持壓縮*

此外,出于技術棧的一致性以及部署的簡易性考慮(面向容器部署),InfluxDB團隊希望存儲引擎 與 其上層的TSDB引擎一樣都是用GO編寫,因此潛在的RocksDB選項被排除

基于上述痛點,InfluxDB團隊決定自己做一個存儲引擎的實現。

2 InfluxDB的數據模型

在解析InfluxDB的存儲引擎之前,先回顧一下InfluxDB中的數據模型。

在InfluxDB中,時序數據支持多值模型,它的一條典型的時間點數據如下所示:

圖 1

v2-e548fef861f430653a866509cd8ce47b_hd.jpg

?

  • measurement:
    指標對象,也即一個數據源對象。每個measurement可以擁有一個或多個指標值,也即下文所述的**field**。在實際運用中,可以把一個現實中被檢測的對象(如:“cpu”)定義為一個measurement
  • tags:
    概念等同于大多數時序數據庫中的tags, 通常通過tags可以唯一標示數據源。每個tag的key和value必須都是字符串。
  • field:
    數據源記錄的具體指標值。每一種指標被稱作一個“field”,指標值就是 “field”對應的“value”
  • timestamp:
    數據的時間戳。在InfluxDB中,理論上時間戳可以精確到 **納秒**(ns)級別

此外,在InfluxDB中,measurement的概念之上還有一個對標傳統DBMS的?Database?的概念,邏輯上每個Database下面可以有多個measurement。在單機版的InfluxDB實現中,每個Database實際對應了一個文件系統的?目錄

2.1 Serieskey的概念

InfluxDB中的SeriesKey的概念就是通常在時序數據庫領域被稱為?時間線?的概念, 一個SeriesKey在內存中的表示即為下述字符串(逗號和空格被轉義)的?字節數組(http://github.com/influxdata/influxdb/model#MakeKey())

{measurement名}{tagK1}={tagV1},{tagK2}={tagV2},...

其中,SeriesKey的長度不能超過 65535 字節

2.2 支持的Field類型

InfluxDB的Field值支持以下數據類型:

DatatypeSize in MemValue RangeFloat8 bytes1.797693134862315708145274237317043567981e+308 ~ 4.940656458412465441765687928682213723651e-324Integer8 bytes-9223372036854775808 ~ 9223372036854775807String0~64KBString with length less than 64KBBoolean1 bytetrue 或 false

在InfluxDB中,Field的數據類型在以下范圍內必須保持不變,否則寫數據時會報錯?類型沖突

同一Serieskey + 同一field + 同一shard

2.3 Shard的概念

在InfluxDB中,?能且只能?對一個Database指定一個?Retention Policy?(簡稱:RP)。通過RP可以對指定的Database中保存的時序數據的留存時間(duration)進行設置。而?Shard?的概念就是由duration衍生而來。一旦一個Database的duration確定后, 那么在該Database的時序數據將會在這個duration范圍內進一步按時間進行分片從而時數據分成以一個一個的shard為單位進行保存。

shard分片的時間 與 duration之間的關系如下

Duration of RPShard Duration< 2 Hours1 Hour>= 2 Hours 且 <= 6 Months1 Day> 6 Months7 Days

新建的Database在未顯式指定RC的情況下,默認的RC為?數據的Duration為永久,Shard分片時間為7天

注: 在閉源的集群版Influxdb中,用戶可以通過RC規則指定數據在基于時間分片的基礎上再按SeriesKey為單位進行進一步分片

3. InfluxDB的存儲引擎分析

時序數據庫的存儲引擎主要需滿足以下三個主要場景的性能需求

  1. 大批量的時序數據寫入的高性能
  2. 直接根據時間線(即Influxdb中的?Serieskey?)在指定時間戳范圍內掃描數據的高性能
  3. 間接通過measurement和部分tag查詢指定時間戳范圍內所有滿足條件的時序數據的高性能

InfluxDB在結合了1.2所述考量的基礎上推出了他們的解決方案,即下面要介紹的?WAL + TSMFile + TSIFile的方案

3.1 WAL解析

InfluxDB寫入時序數據時為了確保數據完整性和可用性,與大部分數據庫產品一樣,都是會先寫WAL,再寫入緩存,最后刷盤。對于InfluxDB而言,寫入時序數據的主要流程如同下圖所示:

圖 2

v2-0b5a3267808f753a72fb2e881aabc690_hd.jpg

?

InfluxDB對于時間線數據和時序數據本身分開,分別寫入不同的WAL中,其結構如下所示:

索引數據的WAL

由于InfluxDB支持對Measurement,TagKey,TagValue的刪除操作,當然隨著時序數據的不斷寫入,自然也包括?增加新的時間線,因此索引數據的WAL會區分當前所做的操作具體是什么,它的WAL的結構如下圖所示

圖 3

v2-17b453506c0950037eb0b35dcce74d31_hd.jpg

?

時序數據的WAL

由于InfluxDB對于時序數據的寫操作永遠只有單純寫入,因此它的Entry不需要區分操作種類,直接記錄寫入的數據即可

圖 4

v2-fde3f5b663ac6ddbefe9e1b18b241098_hd.jpg

?

3.2 TSMFile解析

TSMFile是InfluxDB對于時序數據的存儲方案。在文件系統層面,每一個TSMFile對應了一個?Shard

TSMFile的存儲結構如下圖所示:

圖 5

v2-de0995706806a6adf0373a2bf054be7d_hd.jpg

?

其特點是在一個TSMFile中將 時序數據(i.e Timestamp + Field value)保存在數據區;將Serieskey 和 Field Name的信息保存在索引區,通過一個基于 Serieskey + Fieldkey構建的形似B+tree的文件內索引快速定位時序數據所在的?數據塊

注: 在當前版本中,單個TSMFile的最大長度為2GB,超過時即使是同一個Shard,也會繼續新開一個TSMFile保存數據。本文的介紹出于簡單化考慮,以下內容不考慮同一個Shard的TSMFile分裂的場景

  • 索引塊的構成
    上文的索引塊的構成,如下所示:?*圖 6*

v2-53c8ddefdd1d6ed2a6966ea92b0fe863_hd.jpg

?

其中 **索引條目** 在InfluxDB的源碼中被稱為`directIndex`。在TSMFile中,索引塊是按照 Serieskey + Fieldkey **排序** 后組織在一起的。明白了TSMFile的索引區的構成,就可以很自然地理解InfluxDB如何高性能地在TSMFile掃描時序數據了:1. 根據用戶指定的時間線(Serieskey)以及Field名 在 **索引區** 利用二分查找找到指定的Serieskey+FieldKey所處的 **索引數據塊**
2. 根據用戶指定的時間戳范圍在 **索引數據塊** 中查找數據落在哪個(*或哪幾個*)**索引條目**
3. 將找到的 **索引條目** 對應的 **時序數據塊** 加載到內存中進行進一步的Scan*注:上述的1,2,3只是簡單化地介紹了查詢機制,實際的實現中還有類似掃描的時間范圍跨索引塊等一系列復雜場景*<br>
  • 時序數據的存儲
    圖 2中介紹了時序數據塊的結構:即同一個 Serieskey + Fieldkey 的 所有時間戳 - Field值對被拆分開,分成兩個區:Timestamps區和Value區分別進行存儲。它的目的是:實際存儲時可以分別對時間戳和Field值按不同的壓縮算法進行存儲以減少時序數據塊的大小
    采用的壓縮算法如下所示:
    • Timestamp:?Delta-of-delta encoding
    • Field Value:由于單個數據塊的Field Value必然數據類型相同,因此可以集中按數據類型采用不同的壓縮算法
      • Float類:?Gorrila's Float Commpression
      • Integer類型: Delta Encoding + Zigzag Conversion + RLE / Simple8b / None
      • String類型:?Snappy Compression
      • Boolean類型: Bit packing

?

做查詢時,當利用TSMFile的索引找到文件中的時序數據塊時,將數據塊載入內存并對Timestamp以及Field Value進行解壓縮后以便繼續后續的查詢操作。

3.3 TSIFile解析

有了TSMFile,第3章開頭所說的三個主要場景中的場景1和場景2都可以得到很好的解決。但是如果查詢時用戶并沒有按預期按照Serieskey來指定查詢條件,而是指定了更加復雜的條件,該如何確保它的查詢性能?通常情況下,這個問題的解決方案是依賴倒排索引(Inverted Index)。

InfluxDB的倒排索引依賴于下述兩個數據結構

  • map<SeriesID, SeriesKey>
  • map<tagkey, map<tagvalue, List<SeriesID>>>

它們在內存中展現如下:

圖 7

?

圖 8

v2-42c0f3be55a586f786812d8b7fb70399_hd.jpg

?

但是在實際生產環境中,由于用戶的時間線規模會變得很大,因此會造成倒排索引使用的內存過多,所以后來InfluxDB又引入了?TSIFile

TSIFile的整體存儲機制與TSMFile相似,也是以?Shard?為單位生成一個TSIFile。具體的存儲格式就在此不贅述了。

4. 總結

以上就是對InfluxDB的存儲機制的粗淺解析,由于目前所見的只有單機版的InfluxDB,所以尚不知道集群版的InfluxDB在存儲方面有哪些不同。但是,即便是這單機版的存儲機制,也對我們設計時序數據庫有著重要的參考意義。

?

#阿里云開年Hi購季#幸運抽好禮!

點此抽獎:【阿里云】開年Hi購季,幸運抽好禮

?

原文鏈接

本文為云棲社區原創內容,未經允許不得轉載。

轉載于:https://my.oschina.net/u/3889140/blog/3015136

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449339.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449339.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449339.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何在Linux上提高文本的搜索效率

本文由 極客范 - minejo 翻譯自 Xmodulo。歡迎加入極客翻譯小組&#xff0c;同我們一道翻譯與分享。轉載請參見文章末尾處的要求。對于系統管理員或程序員來說&#xff0c;當需要在復雜配置的目錄中或者在大型源碼樹中搜尋特定的文本或模式時&#xff0c;grep類型的工具大概是…

Spring Boot 10:處理Json數據中的null值

Jackson版&#xff1a; /*** Jackson 配置類 對Json數據進行特殊處理** Author YangXuyue* Date 2019/04/02 07:12*/ Configuration public class JacksonConfig {/*** 配置Jackson** param builder* return* Author YangXuyue* Date 2019/04/02 07:14*/BeanPrimaryConditional…

國信證券學習系列(4)

機器學習篇章&#xff0c;本章不過時腳本小子&#xff0c;機器學習最核心的是機器&#xff0c;是模型。 學習&#xff0c;無非就是找些有的沒的因子扔進去&#xff0c;但說實話&#xff0c;機器學習&#xff0c;太過容易過擬合&#xff0c;容易無效化。回測好看的一筆&#xf…

JSch - Java Secure Channel : java 代碼實現服務器遠程操作

一、前言 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 JSch是SSH2的純Java實現 。 JSch允許您連接到sshd服務器并使用端口轉發&#xff0c;X11轉發&#xff0c;文件傳輸等&#xff0…

前嗅ForeSpider教程:數據建表

今天&#xff0c;小編為大家帶來的教程是&#xff1a;如何在前嗅ForeSpider中&#xff0c;進行數據建表操作及各注意事項。主要內容包括&#xff1a;快速建表&#xff0c;自由建表&#xff0c;字段參數&#xff0c;數據表的創建&#xff0c;關聯與刪除&#xff0c;以及表單變更…

世紀大爭論:Linux還是GNU/Linux?

本文由 極客范 - 愛開源的貢獻開源社區 翻譯自 Chris Hoffman。歡迎加入極客翻譯小組&#xff0c;同我們一道翻譯與分享。轉載請參見文章末尾處的要求。我們在網上已經習慣用“Linux”來稱呼Linux操作系統了&#xff0c;然而&#xff0c;偶爾也用“GNU/Linux”來稱呼和指代同…

PyTorch Softmax

PyTorch provides 2 kinds of Softmax class. The one is applying softmax along a certain dimension. The other is do softmax on a spatial matrix sized in B, C, H, W. But it seems like some problems existing in Softmax2d. : ( 轉載于:https://www.cnblogs.com/hiz…

國信證券學習系列(5)

網格策略&#xff0c;號稱勝率100%的策略&#xff0c;只要扛得住回撤&#xff0c;怎么說呢&#xff0c;它包含了最簡單的思想&#xff0c;大道至簡&#xff0c;真的是沒有什么復雜的&#xff0c;原理清晰&#xff0c;思路簡單。可以明確知道我掙的是那筆錢&#xff0c;為什么獲…

promise

## 前言 今天來分享下promise的用法&#xff0c;es6偉大發明之一&#xff0c;當初我學習的時候也是蠻頭大的&#xff0c;不知道為啥&#xff0c;整個腦子就是&#xff0c;我在哪&#xff0c;我要干啥的懵圈&#xff0c;后面認真學習之后&#xff0c;覺得真是十分好用&#xff0…

計算機集群 解說

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 計算機集群簡稱集群是一種計算機系統&#xff0c;它通過一組松散集成的計算機軟件和/或硬件連接起來高度緊密地協作完成計算工作。 在某…

同時尋找最大數和最小數的最優算法 第二大數

我們知道&#xff0c;在一個容量為n的數據集合中尋找一個最大數&#xff0c;不管用什么樣的比較算法&#xff0c;至少要比較n-1次&#xff0c;就算是用競標賽排序也得比較n-1次&#xff0c;否則你找到的就不能保證是最大的數。那么&#xff0c;在一個容量為n的數據集合中同時尋…

淺談mpvue項目目錄和文件結構

2019獨角獸企業重金招聘Python工程師標準>>> 在Visual Studio Code里面打開項目文件夾&#xff0c;我們可以看到類似如下的文件結構&#xff1a; 1、package.json文件 package.json是項目的主配置文件&#xff0c;里面包含了mpvue項目的基本描述信息、項目所依賴的各…

[AHOI2009]最小割(最大流+tarjan)

繼續填坑了&#xff0c;啦啦啦 這道題本來是準備枚舉每個邊&#xff0c;暫時去除它&#xff0c;但發現時間會爆炸的 于是決定另辟蹊徑 于是這篇題解就應運而生 首先還是網絡流跑一邊 畢竟題目叫最小割嘛&#xff0c;給個面子 然后跑一邊tarjan對滿流的邊處理掉&#xff0c;即不…

進程間通信---信號

什么是信號&#xff1f; 】 信號處理流程 信號類型 發送信號的函數 參數sig&#xff1a;代表 信號 接收信號的函數 參數 handle 的處理方式有幾種&#xff1f; 實例代碼 實例邏輯 圖中的等待操作使用&#xff1a;pause&#xff08;&#xff09;函數 代碼 在這里插入代碼片…

大白話解說,半分鐘就懂 --- 分布式與集群是什么 ? 區別是什么?

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 PS&#xff1a;這篇文章算是筆記&#xff0c;僅部分文字是原創&#xff0c;相當內容只是收集、整理、提煉、總結別人寫的。 沒有標為原創…

國信證券學習系列(6)

行業輪動策略&#xff1a; 本策略每隔1個月定時觸發計算1000能源&#xff08;399381.SZ&#xff09;、1000材料&#xff08;399382.SZ&#xff09;、1000工業&#xff08;399383.SZ&#xff09;、1000可選&#xff08;399384.SZ&#xff09;、1000消費&#xff08;399385.SZ&a…

用Linux命令行修圖——縮放、編輯、轉換格式——一切皆有可能

本文由 極客范 - 八卦愛好者 翻譯自 How-To Geek。歡迎加入極客翻譯小組&#xff0c;同我們一道翻譯與分享。轉載請參見文章末尾處的要求。ImageMagick是一系列的用于修改、加工圖像的命令行工具。ImageMagick能夠快速地使用命令行對圖片進行操作&#xff0c;對大量的圖片進行…

劍指offer:二維數組中的查找

目錄 題目解題思路具體代碼題目 題目鏈接劍指offer&#xff1a;二維數組中的查找題目描述 在一個二維數組中&#xff08;每個一維數組的長度相同&#xff09;&#xff0c;每一行都按照從左到右遞增的順序排序&#xff0c;每一列都按照從上到下遞增的順序排序。請完成一個函數&a…

函數對象 函數嵌套 名稱空間與作用域

函數對象&#xff1a; 函數是第一類對象&#xff0c;即函數可以當做數據傳遞 1 可以被引用 2 可以當做參數傳遞 3 返回值可以是函數 &#xff08;函數名 不帶&#xff08;&#xff09; 就是函數名的內存地址&#xff0c;帶括號就是執行函數&#xff09; 4 可以當做容器類型的…

國信證券學習系列(7)

跨品種套利策略&#xff1a; 本策略根據計算滾動的.過去的30個bar的均值正負0.5個標準差得到布林線 并在最新價差上穿上軌來做空價差,下穿下軌來做多價差 并在回歸至上下軌水平內的時候平倉 獲取數據&#xff1a; # 獲取兩個品種的收盤價時間序列closesContextInfo.get_ma…