<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Prometheus 存儲(chǔ)層的演進(jìn)

          共 7300字,需瀏覽 15分鐘

           ·

          2021-07-14 23:01

          Prometheus 是當(dāng)下最流行的監(jiān)控平臺(tái)之一,它的主要職責(zé)是從各個(gè)目標(biāo)節(jié)點(diǎn)中采集監(jiān)控?cái)?shù)據(jù),后持久化到本地的時(shí)序數(shù)據(jù)庫(kù)中,并向外部提供便捷的查詢(xún)接口。本文嘗試探討 Prometheus 存儲(chǔ)層的演進(jìn)過(guò)程,信息源主要來(lái)自于 Prometheus 團(tuán)隊(duì)在歷屆 PromConf 上的分享。

          時(shí)序數(shù)據(jù)庫(kù)是 Promtheus 監(jiān)控平臺(tái)的一部分,在了解其存儲(chǔ)層的演化過(guò)程之前,我們需要先了解時(shí)序數(shù)據(jù)庫(kù)及其要解決的根本問(wèn)題。

          TSDB

          時(shí)序數(shù)據(jù)庫(kù) (Time Series Database, TSDB) 是數(shù)據(jù)庫(kù)大家庭中的一員,專(zhuān)門(mén)存儲(chǔ)隨時(shí)間變化的數(shù)據(jù),如股票價(jià)格、傳感器數(shù)據(jù)、機(jī)器狀態(tài)監(jiān)控等等。時(shí)序 (Time Series) 指的是某個(gè)變量隨時(shí)間變化的所有歷史,而樣本 (Sample) 指的是歷史中該變量的瞬時(shí)值:

          每個(gè)樣本由時(shí)序標(biāo)識(shí)時(shí)間戳數(shù)值 3 部分構(gòu)成,其所屬的時(shí)序就由一系列樣本構(gòu)成。由于時(shí)間是連續(xù)的,我們不可能、也沒(méi)有必要記錄時(shí)序在每個(gè)時(shí)刻的數(shù)值,因此采樣間隔 (Interval) 也是時(shí)序的重要組成部分。采樣間隔越小、樣本總量越大、捕獲細(xì)節(jié)越多;采樣間隔越大、樣本總量越小、遺漏細(xì)節(jié)越多。以服務(wù)器機(jī)器監(jiān)控為例,通常采樣間隔為 15 秒。

          數(shù)據(jù)的高效查詢(xún)離不開(kāi)索引,對(duì)于時(shí)序數(shù)據(jù)而言,唯一的、天然的索引就是時(shí)間 (戳)。因此通常時(shí)序數(shù)據(jù)庫(kù)的存儲(chǔ)層相比于關(guān)系型數(shù)據(jù)庫(kù)要簡(jiǎn)單得多。仔細(xì)思考,你可能會(huì)發(fā)現(xiàn)時(shí)序數(shù)據(jù)在某種程度上就是鍵值數(shù)據(jù)的一個(gè)子集,因此鍵值數(shù)據(jù)庫(kù)天然地可以作為時(shí)序數(shù)據(jù)的載體。通常一個(gè)時(shí)序數(shù)據(jù)庫(kù)能容納百萬(wàn)量級(jí)以上的時(shí)序數(shù)據(jù),要從其中搜索到其中少量的幾個(gè)時(shí)序也非易事,因此對(duì)時(shí)序本身建立高效的索引也很重要。

          The Fundamental Problem of TSDBs

          TSDB 要解決的基本問(wèn)題,可以概括為下圖:

          研究過(guò)存儲(chǔ)引擎結(jié)構(gòu)和性能優(yōu)化的工程師都會(huì)知道:

          許多數(shù)據(jù)庫(kù)的奇技淫巧都是在解決內(nèi)存與磁盤(pán)的讀寫(xiě)模式、性能的不匹配問(wèn)題

          時(shí)序數(shù)據(jù)庫(kù)也是數(shù)據(jù)庫(kù)的一種,只要它想持久化,自然不能例外。但與鍵值數(shù)據(jù)庫(kù)相比,時(shí)序數(shù)據(jù)庫(kù)存儲(chǔ)的數(shù)據(jù)有更特殊的讀寫(xiě)特征,Bj?rn Rabenstein 將稱(chēng)其為:

          Vertical writes, horizontal(-ish) reads 垂直寫(xiě),水平讀

          圖中每條橫線就是一個(gè)時(shí)序,每個(gè)時(shí)序由按照 (準(zhǔn)) 固定間隔采集的樣本數(shù)據(jù)構(gòu)成,通常在時(shí)序數(shù)據(jù)庫(kù)中會(huì)有很多活躍時(shí)序,因此數(shù)據(jù)寫(xiě)入可以用一個(gè)垂直的窄方框表示,即每個(gè)時(shí)序都要寫(xiě)入新的樣本數(shù)據(jù);用戶(hù)在查詢(xún)時(shí),通常會(huì)觀察某個(gè)、某幾個(gè)時(shí)序在某個(gè)時(shí)間段內(nèi)的變化趨勢(shì),或?qū)ζ溥M(jìn)行聚合計(jì)算,因此數(shù)據(jù)讀取可以用一個(gè)水平的方框表示。是謂 “垂直寫(xiě)、水平讀”。

          Storage Layer of Prometheus

          Prometheus 是為云原生環(huán)境中的數(shù)據(jù)監(jiān)控而生,在其設(shè)計(jì)過(guò)程中至少需要考慮以下兩個(gè)方面:

          1、在云原生環(huán)境中,實(shí)例可能隨時(shí)出現(xiàn)、消失,因此時(shí)序也可能隨時(shí)出現(xiàn)或消失,即系統(tǒng)中存在大量時(shí)序,其中部分處于活躍狀態(tài),這會(huì)在多方面帶來(lái)挑戰(zhàn):

          • 如何存儲(chǔ)大量時(shí)序避免資源浪費(fèi)
          • 如何定位被查詢(xún)的少數(shù)幾個(gè)時(shí)序

          2、監(jiān)控系統(tǒng)本身應(yīng)該盡量少地依賴(lài)外部服務(wù),否則外部服務(wù)失效將引發(fā)監(jiān)控系統(tǒng)失效

          對(duì)于第 2 點(diǎn),Prometheus 團(tuán)隊(duì)選擇放棄集群,使用單機(jī)架構(gòu),并且在單機(jī)系統(tǒng)中使用本地 TSDB 做數(shù)據(jù)持久化,完全不依賴(lài)外部服務(wù);第 1 點(diǎn)是需要存儲(chǔ)、索引、查詢(xún)引擎層合作解決的問(wèn)題,在下文中我們將進(jìn)一步分析存儲(chǔ)層在其中的作用。Prometheus 存儲(chǔ)層的演進(jìn)可以分成 3 個(gè)階段:

          • 1st Generation: Prototype
          • 2nd Generation: Prometheus V1
          • 3rd Generation: Prometheus V2

          注意:本節(jié)只關(guān)注 Prometheus 時(shí)序數(shù)據(jù)的存儲(chǔ),不涉及索引、WAL 等其它數(shù)據(jù)的存儲(chǔ)。

          Data Model

          盡管數(shù)據(jù)模型是存儲(chǔ)層之上的抽象,理論上它不應(yīng)該影響存儲(chǔ)層的設(shè)計(jì)。但理解數(shù)據(jù)模型能夠幫助我們更快地理解存儲(chǔ)層。

          在 Prometheus 中,每個(gè)時(shí)序?qū)嶋H上由多個(gè)標(biāo)簽 (labels) 標(biāo)識(shí),如:

          api_http_requests_total{path="/users",status=200,method="GET",instance="10.111.201.26"}

          該時(shí)序的名字為 api_http_requests_total,標(biāo)簽為 path、status、method 和 instance,只有時(shí)序名字和標(biāo)簽鍵值完全相同的時(shí)序才是同一個(gè)時(shí)序。事實(shí)上,時(shí)序名字就是一個(gè)隱藏標(biāo)簽:

          {name="api_http_requests_total",path="/users",status=200,method="GET", instance="10.111.201.26"}

          對(duì)于用戶(hù)來(lái)說(shuō),標(biāo)簽之間不存在先后順序,用戶(hù)可能關(guān)注:

          • 所有 api 調(diào)用的 status
          • 某個(gè) path 調(diào)用的成功率、QPS
          • 某個(gè)實(shí)例、某個(gè) path 調(diào)用的成功率

          1st Generation: Prototype

          在 Prototype 階段,Prometheus 直接利用開(kāi)源的鍵值數(shù)據(jù)庫(kù) (LevelDB) 作為本地持久化存儲(chǔ),并采用與 BigTable 推薦的時(shí)序數(shù)據(jù)方案 類(lèi)似的 schema 設(shè)計(jì):

          時(shí)序名稱(chēng)、標(biāo)簽 (固定順序)、時(shí)間戳拼接成每個(gè)樣本的鍵,于是同一個(gè)時(shí)序的數(shù)據(jù)就能夠連續(xù)存儲(chǔ)在鍵值數(shù)據(jù)庫(kù)中,提高范圍查詢(xún)的效率。但從圖中可以看出,這種方式存儲(chǔ)的鍵很長(zhǎng),盡管鍵值數(shù)據(jù)庫(kù)內(nèi)部會(huì)對(duì)數(shù)據(jù)進(jìn)行壓縮,但是在內(nèi)存中這樣存儲(chǔ)數(shù)據(jù)很浪費(fèi)空間,這無(wú)法滿(mǎn)足項(xiàng)目的設(shè)計(jì)要求。Prometheus 希望在內(nèi)存中壓縮數(shù)據(jù),使得內(nèi)存中可以容納更多活躍的時(shí)序數(shù)據(jù),同時(shí)在磁盤(pán)中也能按類(lèi)似的方式壓縮編碼,提高效率。時(shí)序數(shù)據(jù)比通用鍵值數(shù)據(jù)有更顯著的特征。即使鍵值數(shù)據(jù)庫(kù)能夠壓縮數(shù)據(jù),但針對(duì)時(shí)序數(shù)據(jù)的特征,使用特殊的壓縮算法能夠取得更好的壓縮率。因此在 Prototype 階段,使用三方鍵值數(shù)據(jù)庫(kù)的方案最終流產(chǎn)。

          2nd Generation: Prometheus V1

          Compression

          Why Compression

          假設(shè)監(jiān)控系統(tǒng)的需求如下:

          • 500 萬(wàn)活躍時(shí)序
          • 30 秒采樣間隔
          • 1 個(gè)月數(shù)據(jù)留存

          那么經(jīng)過(guò)計(jì)算可以得到具體的存儲(chǔ)要求:

          • 平均每秒采集 166000 個(gè)樣本
          • 存儲(chǔ)樣本總量為 4320 億個(gè)樣本

          假設(shè)沒(méi)有任何壓縮,不算時(shí)序標(biāo)識(shí),每個(gè)樣本需要 16 個(gè)字節(jié)存儲(chǔ)空間 (時(shí)間戳 8 個(gè)字節(jié)、數(shù)值 8 個(gè)字節(jié)),整個(gè)系統(tǒng)的存儲(chǔ)總量為 7TB,假設(shè)數(shù)據(jù)需要留存 6 個(gè)月,則總量為 42 TB,那么如果能找到一種有效的方式壓縮數(shù)據(jù),就能在單機(jī)的內(nèi)存和磁盤(pán)中存放更多、更長(zhǎng)的時(shí)序數(shù)據(jù)。

          Chunked Storage Abstraction

          上文提到 TSDB 的根本問(wèn)題是 “垂直寫(xiě),水平讀”,每次采樣都會(huì)需要為每個(gè)活躍時(shí)序?qū)懭胍粭l樣本數(shù)據(jù),但如果每次為每個(gè)時(shí)序?qū)懭?16 個(gè)字節(jié)到 HDD/SSD 中,顯然這對(duì)塊存儲(chǔ)設(shè)備十分不友好,效率低下。因此 Prometheus V2 將數(shù)據(jù)按固定長(zhǎng)度切割相同大小的分段 (Chunks),方便壓縮、批量讀寫(xiě)。

          訪問(wèn)時(shí)序數(shù)據(jù)時(shí),Prometheus 使用 3 層抽象,如下圖所示:

          應(yīng)用層使用 Series Iterator 順序訪問(wèn)時(shí)序中的樣本,而 Series Iterator 底下由一個(gè)個(gè) Chunk Iterator 拼接而成,每個(gè) Chunk Iterator 負(fù)責(zé)將壓縮編碼的時(shí)序數(shù)據(jù)解碼返回。這樣做的好處是,每個(gè) Chunk 甚至可以使用完全不同的方式編碼,方便開(kāi)發(fā)團(tuán)隊(duì)嘗試不同的編碼方案。

          Timestamp Compression: Double Delta

          由于通常數(shù)據(jù)采樣間隔是固定值,因此前后時(shí)間戳的差值幾乎固定,如 15s,30s。但如果我們更近一步,只存儲(chǔ)差值的差值,那么幾乎不用再為新的時(shí)間戳花費(fèi)額外的空間,這便是所謂的 “Double Delta“。本質(zhì)上,如果未來(lái)所有的采集時(shí)間戳都可以精準(zhǔn)預(yù)測(cè),那么每個(gè)新時(shí)間戳的信息熵為 0 bit。但現(xiàn)實(shí)并不完美,網(wǎng)絡(luò)可能延遲、中斷,實(shí)例可能遇到 GC、重啟,采樣間隔隨時(shí)有可能波動(dòng):

          但這種波動(dòng)的幅度有限,Prometheus 采用了和 FB 的內(nèi)存時(shí)序數(shù)據(jù)庫(kù) Gorilla 類(lèi)似的方式編碼時(shí)間戳,詳情可以參考 Gorilla) 以及 Bj?rn Rabenstein 在 PromConn 2016 的演講 ppt ,細(xì)節(jié)比較瑣碎,這里不贅述。

          Value Compression

          Prometheus 和 Gorilla 中的每個(gè)樣本值都是 float64 類(lèi)型。Gorilla 利用 float64 的二進(jìn)制表示 (IEEE754) 將前后兩個(gè)樣本值 XOR 來(lái)尋找壓縮的空間,能獲得 1.37 bytes/sample 的壓縮能力。Prometheus V2 采用的方式比較簡(jiǎn)單:

          • 如果可能的話(huà),使用整型 (8/16/32 位) 存儲(chǔ),否則用 float32,最后實(shí)在不行就直接存儲(chǔ) float64
          • 如果數(shù)值增長(zhǎng)得很規(guī)律,則不使用額外的空間存儲(chǔ)

          以上做法給 Prometheus V1 帶來(lái)了 3.3 bytes/sample 的壓縮能力。相比于為完全存儲(chǔ)于內(nèi)存中的 Gorilla 相比,這樣的壓縮能力對(duì)于 Prometheus 已經(jīng)夠用,但在 V2 中,Prometheus 也融合了 Gorilla 采用的壓縮技術(shù)。

          Chunk Encoding

          Prometheus V1 將每個(gè)時(shí)序分割成大小為 1KB 的 chunks,如下圖所示:

          在內(nèi)存中保留著最近寫(xiě)入的 chunk,其中 head chunk 正在接收新的樣本。每當(dāng)一個(gè) head chunk 寫(xiě)滿(mǎn) 1KB 時(shí),會(huì)立即被凍結(jié),我們稱(chēng)之為完整的 chunk,從此刻開(kāi)始該 chunk 中的數(shù)據(jù)就是不可變的 (immutable) ,同時(shí)生成一個(gè)新的 head chunk 負(fù)責(zé)消化新的請(qǐng)求。每個(gè)完整的 chunk 會(huì)被盡快地持久化到磁盤(pán)中。內(nèi)存中保存著每個(gè)時(shí)序最近被寫(xiě)入或被訪問(wèn)的 chunks,當(dāng) chunks 數(shù)量過(guò)多時(shí),存儲(chǔ)引擎會(huì)將超過(guò)的 chunks 通過(guò) LRU 策略清出。

          在 Prometheus V1 中,每個(gè)時(shí)序都會(huì)被存儲(chǔ)到在一個(gè)獨(dú)占的文件中,這也意味著大量的時(shí)序?qū)a(chǎn)生大量的文件。存儲(chǔ)引擎會(huì)定期地去檢查磁盤(pán)中的時(shí)序文件,是否已經(jīng)有 chunk 數(shù)據(jù)超過(guò)保留時(shí)間,如果有則將其刪除 (復(fù)制后刪除)。

          Prometheus 的查詢(xún)引擎的查詢(xún)過(guò)程必須完全在內(nèi)存中進(jìn)行。因此在執(zhí)行之前,存儲(chǔ)引擎需要將不在內(nèi)存中的 chunks 預(yù)加載到內(nèi)存中:

          如果在內(nèi)存中的 chunks 持久化之前系統(tǒng)發(fā)生崩潰,則會(huì)產(chǎn)生數(shù)據(jù)丟失。為了減少數(shù)據(jù)丟失,Prometheus V1 還使用了額外的 checkpoint 文件,用于存儲(chǔ)各個(gè)時(shí)序中尚未寫(xiě)入磁盤(pán)的 chunks:

          Prometheus V1 vs. Gorilla

          正因?yàn)?Prometheus V1 與 Gorilla 的設(shè)計(jì)理念、需求有所不同,我們可以通過(guò)對(duì)比二者來(lái)理解其設(shè)計(jì)過(guò)程中使用不同決策的原因。

          3rd Generation: Prometheus V2

          The Main Problem With 2nd Generation

          Prometheus V1 中,每個(gè)時(shí)序數(shù)據(jù)對(duì)應(yīng)一個(gè)磁盤(pán)文件的方式給系統(tǒng)帶來(lái)了比較大的麻煩:

          • 由于在云原生環(huán)境下,會(huì)不斷產(chǎn)生新的時(shí)序、廢棄舊的時(shí)序 (Series Churn),因此實(shí)際上存儲(chǔ)層需要的文件數(shù)量遠(yuǎn)遠(yuǎn)高于活躍的時(shí)序數(shù)量。任其發(fā)展遲早會(huì)將文件系統(tǒng)的 inodes 消耗殆盡。而且一旦發(fā)生,恢復(fù)系統(tǒng)將異常麻煩。不僅如此,在新舊時(shí)序大量更迭時(shí),由于舊時(shí)序數(shù)據(jù)尚未從內(nèi)存中清出,系統(tǒng)的內(nèi)存消耗量也會(huì)飆升,造成 OOM。
          • 即便使用 chunks 來(lái)批量讀寫(xiě)數(shù)據(jù),從整體上看,系統(tǒng)每秒鐘仍要向磁盤(pán)寫(xiě)入數(shù)千個(gè) chunks,造成 I/O 壓力;如果通過(guò)增大每批寫(xiě)入的量來(lái)減少 I/O 次數(shù),又將造成內(nèi)存的壓力。
          • 同時(shí)將所有時(shí)序文件保持打開(kāi)狀態(tài)很不合理,需要消耗大量的資源。如果在查詢(xún)前后打開(kāi)、關(guān)閉文件,又會(huì)增加查詢(xún)的時(shí)延。
          • 當(dāng)數(shù)據(jù)超過(guò)留存時(shí)間時(shí)需要?jiǎng)h除相關(guān)的 chunks,這意味著每隔一段時(shí)間就要對(duì)數(shù)百萬(wàn)的文件執(zhí)行一次刪除數(shù)據(jù)操作,這個(gè)過(guò)程可能需要持續(xù)數(shù)小時(shí)。
          • 通過(guò)周期性地將未持久化的 chunks 寫(xiě)入 checkpoint 文件理論上確實(shí)可以減少數(shù)據(jù)丟失,但是如果執(zhí)行數(shù)據(jù)恢復(fù)需要很長(zhǎng)時(shí)間,那么實(shí)際上又錯(cuò)過(guò)了新的數(shù)據(jù),還不如不恢復(fù)。

          因此 Prometheus 的第三代存儲(chǔ)引擎,主要改變就是放棄 “一個(gè)時(shí)序?qū)?yīng)一個(gè)文件” 的設(shè)計(jì)理念。

          Macro Design

          第三代存儲(chǔ)引擎在磁盤(pán)中的文件結(jié)構(gòu)如下圖所示:

          根目錄下,順序排列著編了號(hào)的 blocks,每個(gè) block 中包含 index 和 chunk 文件夾,后者里面包含編了號(hào)的 chunks,每個(gè) chunk 包含許多不同時(shí)序的樣本數(shù)據(jù)。其中 index 文件中的信息可以幫我我們快速鎖定時(shí)序的標(biāo)簽及其可能的取值,進(jìn)而找到相關(guān)的時(shí)序和持有該時(shí)序樣本數(shù)據(jù)的 chunks。值得注意的是,最新的 block 文件夾中還包含一個(gè) wal 文件夾,后者將承擔(dān)故障恢復(fù)的職責(zé)。

          Many Little Databases

          第三代存儲(chǔ)引擎將所有時(shí)序數(shù)據(jù)按時(shí)間分片,即在時(shí)間維度上將數(shù)據(jù)劃分成互不重疊的 blocks,如下圖所示:

          每個(gè) block 實(shí)際上就是一個(gè)小型數(shù)據(jù)庫(kù),內(nèi)部存儲(chǔ)著該時(shí)間窗口內(nèi)的所有時(shí)序數(shù)據(jù),因此它需要擁有自己的 index 和 chunks。除了最新的、正在接收新鮮數(shù)據(jù)的 block 之外,其它 blocks 都是不可變的。由于新數(shù)據(jù)的寫(xiě)入都在內(nèi)存中,數(shù)據(jù)的寫(xiě)效率較高:

          為了防止數(shù)據(jù)丟失,所有新采集的數(shù)據(jù)都會(huì)被寫(xiě)入到 WAL 日志中,在系統(tǒng)恢復(fù)時(shí)能快速地將其中的數(shù)據(jù)恢復(fù)到內(nèi)存中。在查詢(xún)時(shí),我們需要將查詢(xún)發(fā)送到不同的 block 中,再將結(jié)果聚合。

          按時(shí)間將數(shù)據(jù)分片賦予了存儲(chǔ)引擎新的能力:

          • 當(dāng)查詢(xún)某個(gè)時(shí)間范圍內(nèi)的數(shù)據(jù),我們可以直接忽略在時(shí)間范圍外的 blocks
          • 寫(xiě)完一個(gè) block 后,我們可以將輕易地其持久化到磁盤(pán)中,因?yàn)橹簧婕暗缴倭繋讉€(gè)文件的寫(xiě)入
          • 新的數(shù)據(jù),也是最常被查詢(xún)的數(shù)據(jù)會(huì)處在內(nèi)存中,提高查詢(xún)效率 (第二代同樣支持)
          • 每個(gè) chunk 不再是固定的 1KB 大小,我們可以選擇任意合適的大小,選擇合適的壓縮方式
          • 刪除超過(guò)留存時(shí)間的數(shù)據(jù)變得異常簡(jiǎn)單,直接刪除整個(gè)文件夾即可

          mmap

          第三代引擎將數(shù)百萬(wàn)的小文件合并成少量大文件,也讓 mmap 成為可能。利用 mmap 將文件 I/O 、緩存管理交給操作系統(tǒng),降低 OOM 發(fā)生的頻率。

          Compaction

          在 Macro Design 中,我們將所有時(shí)序數(shù)據(jù)按時(shí)間切割成許多 blocks,當(dāng)新寫(xiě)滿(mǎn)的 block 持久化到磁盤(pán)后,相應(yīng)的 WAL 文件也會(huì)被清除。寫(xiě)入數(shù)據(jù)時(shí),我們希望每個(gè) block 不要太大,比如 2 小時(shí)左右,來(lái)避免在內(nèi)存中積累過(guò)多的數(shù)據(jù)。讀取數(shù)據(jù)時(shí),若查詢(xún)涉及到多個(gè)時(shí)間段,就需要對(duì)許多個(gè) block 分別執(zhí)行查詢(xún),然后再合并結(jié)果。假如需要查詢(xún)一周的數(shù)據(jù),那么這個(gè)查詢(xún)將涉及到 80 多個(gè) blocks,降低數(shù)據(jù)讀取的效率。

          為了既能寫(xiě)得快,又能讀得快,我們就得引入 compaction,后者將一個(gè)或多個(gè) blocks 中的數(shù)據(jù)合并成一個(gè)更大的 block,在合并的過(guò)程中會(huì)自動(dòng)丟棄被刪除的數(shù)據(jù)、合并多個(gè)版本的數(shù)據(jù)、重新結(jié)構(gòu)化 chunks 來(lái)優(yōu)化查詢(xún)效率,如下圖所示:

          Retention

          當(dāng)數(shù)據(jù)超過(guò)留存時(shí)間時(shí),刪除舊數(shù)據(jù)非常容易:

          直接刪除在邊界之外的 block 文件夾即可。如果邊界在某個(gè) block 之內(nèi),則暫時(shí)將它留存,知道邊界超出為止。當(dāng)然,在 Compaction 中,我們會(huì)將舊的 blocks 合并成更大的 block;在 Retention 時(shí),我們又希望能夠粒度更小。所以 Compaction 與 Retention 的策略之間存在著一定的互斥關(guān)系。Prometheus 的系統(tǒng)參數(shù)可以對(duì)單個(gè) block 的大小作出限制,來(lái)尋找二者之間的平衡。

          看到這里,相信你已經(jīng)發(fā)現(xiàn)了,這不就是 LSM Tree **嗎?**每個(gè) block 就是按時(shí)間排序的 SSTable,內(nèi)存中的 block 就是 MemTable。

          Compression

          第三代存儲(chǔ)引擎融合了 Gorilla 的 XOR float encoding 方案,將壓縮能力提升到 1-2 bytes/sample。具體方案可以概括為:按順序采用以下第一條適用的策略

          1. Zero encoding:如果完全可預(yù)測(cè),則無(wú)需額外空間
          2. Integer double-delta encoding:如果是整型,可以利用 double-delta 原理,將不等的前后間隔分成 6/13/20/33 bits 幾種,來(lái)優(yōu)化空間使用
          3. XOR float encoding:參考 Gorilla
          4. Direct encoding:直接存 float64

          平均下來(lái)能取得 1.28 bytes/sample 的壓縮能力。

          原文鏈接:https://zhuanlan.zhihu.com/p/155719693



          K8S 進(jìn)階訓(xùn)練營(yíng)


           點(diǎn)擊屏末  | 即刻學(xué)習(xí)


          掃描二維碼獲取

          更多云原生知識(shí)





          k8s 技術(shù)圈





          瀏覽 27
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  高清日本大陆欧美 | 91丨九色丨蝌蚪丨对白 | 欧美性爱网站操 | 免费A片国产毛无码A片牛牛 | 国产精品嫩草AV城中村 |