時序數據庫Influx-IOx源碼學習一(項目背景)

InfluxDB是一個由InfluxData開發的開源時序數據庫,專一於海量時序數據的高性能讀、寫、高效存儲與實時分析等,在DB-Engines Ranking時序型數據庫排行榜上常年排名第一。數據庫

InfluxDB能夠說是當之無愧的佼佼者,但 InfluxDB CTO Paul 在 2020/12/10 號在博客中發表一篇名爲:Announcing InfluxDB IOx – The Future Core of InfluxDB Built with Rust and Arrow的文章,介紹了一個新項目 InfluxDB IOx,InfluxDB 的下一代時序引擎。編程

接下來,我將連載對於InfluxDB IOx的源碼解析過程,歡迎各位批評指正,聯繫方式見文章末尾。服務器


爲何會發起IOx項目

原文請參見: https://www.influxdata.com/blog/announcing-influxdb-iox/微信

1. 下一步的目標

原文中介紹到,過去的7年時間的發展中,InfluxDBmetrics 數據的處理上已經成爲了很是出色的數據庫,而且在 analytics 方面也很不錯。但對於現有的架構來說有一個限制就是不能處理很是大的基數 (significant cardinality),也就是說tags裏不能設置太多的值。好比說:不能處理分佈式追蹤數據 (distributed tracing data) 的這種場景。網絡

另外在開源方面,InfluxDB 僅僅支持單機版本的開源,對於分佈式版本只有企業版本或者雲上纔會提供,這個決定給分佈式時序數據庫留下了很大一塊空白的市場。數據結構

因此在大方向上,InfluxDB 定義了13個要求,你們能夠在原文中找到,總結爲:架構

  • 從設計上減小對於用戶的限制:好比 tag 或者 field.
  • 交給用戶更多的控制權:好比內存分區副本讀寫索引
  • 支持container的運行環境
  • 大數據的倒入倒出
  • 細粒度的訂閱數據
  • 兼容更多的生態,包括數據標準及分析等
  • 能夠運行在邊緣或者數據中心
  • 能夠支持內嵌腳本(我理解爲UDF這類)

2. 更開放的許可

InfluxDB對於分佈式版本是閉源的,這使得它在市場上和其它產品相比存在很大的差距,使得過去的幾年中出現了不少時序數據庫。而且若是開源協議對商業是有限制的,那麼一些大的公司就會再開發本身的數據庫出來,或者是採用其它開源的數據庫,這樣就形成了你們相互之間的不兼容的。併發

若是開源的協議採用有限制的協議,那麼不少開發者除了內部使用外,即使是已經拿到開源的代碼都別無選擇的須要從新再開發。框架

開源創造了一個寒武紀大爆發,會創造出一個很是大的價值。開源不是零和博弈,一個很是大的社區和生態會爲全部人和供應商帶來更多的機會。運維

若是InfluxDB想成爲無數公司的傳感器、監測、數據分析的基礎方案,那麼惟一的方法就是可擴展、可採用、任何人能夠商業化。綜上所述,InfluxDB選擇了 MIT & Apache 2雙重許可。

那麼InfluxDB如何盈利呢?在分佈式的版本中,可能須要一系列的運維、監控等外圍的工具,做爲盈利的點。這樣不管是雲產品仍是開源版都是相同的代碼,不產生fork

3. 更新的設計

在現有的InfluxDB中,數據是這樣:

cpu,host=serverA,region=west user=23.2,system=53.2 1604944036000000000

意思是,存儲的cpu這個measurement;他有兩個tag,分別是hostregion;有兩個field,分別是usersystem;最後是一個納秒的時間戳。數據被存儲和索引爲:

measurement, tag key/value pairs, field name

基於時間排序的(time-value)的鍵值對被存儲爲了一個單獨的時間序列。measurementtag (key-value)field 被保存成了一個倒排索引。因此InfluxDB其實是兩個數據庫,一個倒排索引和一個時間序列。這意味着,只要tag中存在裏新的值,就必須存儲在倒排索引中。好比在分佈式追蹤(distributed tracing ) 的場景裏,每行數據都有一個惟一的id,這意味着二級索引比時序數據還要大,服務器就須要浪費大量的cpu和內存來處理索引數據。

有一個解決的方案就是使用field來存儲,可是這樣限制來用戶的使用,必須考慮何時爲標籤、何時是字段,查詢的時候也須要考慮是否能使用到索引。

若是修改爲爲無限的基數(cardinality),惟一的方式就是合併時序數據和倒排索引,這是數據庫設計的核心。

文章中還提到了嚴格的內存控制,若是想作內存控制,就不能使用MMAP,全部的數據(索引和時序數據)在InfluxDB中使用到的內存都須要被計算。

對象存儲做爲持久性層和批量數據導入導出的需求很難經過InfluxDB構建的底層存儲引擎來實現。現有的設計基本上假定是一個本地SSD,而且不容許將其中的數據導出到對象存儲並在查詢時導入。採用這種索引和時間序列數據分開的存儲結構也難以實現大量數據的導入和導出。

這些潛在的問題致使沒法讓InfluxDB作的更好,因此須要從根本上從新思考數據庫的存儲結構及核心架構是該如何組織。

4. Rust, Arrow, 列式存儲

在決定重構核心的功能時,就必需要考慮使用什麼工具可以讓這個重構的過程變得更快、更可靠、更面向社區。Rust做爲系統級編程語言及Apache Arrow做爲內存分析工具集,這兩款開源工具在過去的幾年中,取得了巨大的進步。

Rust能夠爲咱們提供了運行時行爲和內存管理的更細粒度控制。還有一個額外的好處就是併發編程更容易,消除了數據競爭。在Crates.io中又幾乎包含了全部你須要用到的東西。

Apache Arrow定義了一個內存的列式數據結構而且能夠對接Parquet(列式持久化文件格式)、Flight(一個client/server的通訊協議框架,傳輸大數據集的高性能網絡接口)。使用RustArrow還有一個額外的好處就是DataFusion(爲Apache Arrow提供Rust原生支持的SQL查詢引擎)。使用DataFusion做爲核心,意味着InfluxDB IOx將提供一個開箱即用的SQL子集。固然除了SQL以外,還會繼續支持InfluxQLFlux

基於列式存儲的數據模型:

  • Measurements會變爲Table(每個measurement都是一張表)
  • Tags和Fields會成爲表中的列(這樣就須要經過measurement來鎖定一個範圍)
    • Tag和Field的Key在一個measurement中必須是惟一的
  • 時間也會做爲表中的列

除了scheme的組織,還選擇了Parquet做爲持久化文件格式。每一個Parquet文件都包含了一張表中的部分數據,也就是每一個Parquet文件只包含一個measurement的數據。實驗代表,ParquetInfluxDB本身的TSM引擎具備更好的壓縮比。

另外是用戶必須在建立數據庫的時候指定分區策略(好比基於時間的每2個小時)。對於每一個分區,能夠存儲一些摘要性的數據在內存中,包含分區都擁有哪些表,有什麼列,這些列的最大最小值等。這意味着查詢計劃能夠在執行前經過這個元數據排除大量的分區數據。同時這種分區方案更容易使用對象存儲做爲長期存儲,並管理從內存到對象存儲再到索引的Parquet文件的數據生命週期。

現有的列式數據庫,並無單獨針對於時序數據作優化而且分離計算和存儲,尤爲是具備很是優秀的字典和窗口聚合查詢。

最後文中提到了一點頗有意思的研究方向,他說:咱們須要一個可以在內存中保存壓縮數據並對其執行查詢的系統。因此正在積極擴展DataFusion使其可以處理更多的內存中的時序數據。

5.我的總結

總體看來,InfluxDB想把全部功能開源、分離計算和存儲,支持對象存儲的方式、精細的控制內存、而且能夠在內存中處理壓縮的數據。不是什麼顛覆式創新,只是爲了更好的處理時序數據。


歡迎關注微信公衆號:

或添加微信好友: liutaohua001

相關文章
相關標籤/搜索