官术网_书友最值得收藏!

2.4 數據存儲

Prometheus 的數據存儲分為本地存儲和遠程存儲兩種方式,下面針對這兩種方式進行詳細講解。

2.4.1 本地存儲

Prometheus的本地存儲經歷了兩個版本的重要演進,從 Prometheus V1版本升級到V2版本,又升級為現在的V3版本。從V2版本開始,Prometheus的本地存儲便充分借鑒了Facebook Gorilla的設計思想及Facebook內部的長期經驗,總結了時序數據的以下特點:

◎ 相鄰數據點時間戳的差值相對固定,即使有變化,也僅在一個很小的范圍內浮動;

◎ 相鄰數據點的值的變化幅度很小,甚至無變化;

◎ 對熱數據的查詢頻率遠遠超出對非熱點數據的查詢頻率,并且數據距離現在越近,熱度越高。

在 Facebook 上發表的關于 Gorilla 的文章(http://www.vldb.org/pvldb/vol8/p1816-teller.pdf)中提出了一種壓縮算法,可以將16字節的樣本數據壓縮到1.37字節,并且通過塊(chunk)保存,如圖2-8所示。

圖2-8

其原理非常簡單,首先是對時間戳采用兩次去差值的方式,加入 t0=10:00:00、t1=10:01:02和 t2=10:02:02三個時間點。在第1次壓縮時,t1?t0=62,t2?t1=60;在第2次壓縮時,60?62=?2。采用保存差值的方式來大幅度降低存儲空間,采樣的頻率通常也是固定的,這樣的差值幾乎都是 0。對于指標值,則對相鄰指標進行異或(XOR)操作,如果前后兩個采樣值相等,二者異或的結果為0,則只需保存一個0,而且監控數據通常都變化不大,異或的結果將會很小,便于保存。

但Prometheus V2的存儲設計存在很大的問題,如下所述。

(1)每個序列都有一個文件,這樣會耗盡文件系統的Inode,并且同時隨機讀寫了這么多的文件,磁盤的性能會大大降低,對于SSD還會存在寫放大的問題。

(2)被監控對象不停更新。例如,在Kubernetes容器監控方面,容器的生命周期比較短暫,指標不停變化,會形成“時序流失”。隨著時間的推移,雖然有LevelDB負責時序的索引,但這些時間序列會形成線性增長,導致內存積壓過多,如圖2-9所示。

圖2-9

(3)無法預測容量。數據首先在內存中緩慢構建,在被保存到磁盤中后,內存中的數據會被回收,這樣發生時序流失時,內存的消耗就會增加。如果要查詢已經存儲到磁盤的歷史數據,則會再次將相關數據全部加載到內存中,此時很容易發生內存溢出(OOM),導致Prometheus被“殺掉”,給運維人員造成很大的壓力。

經過一些系列的參數調整后,Prometheus 內存溢出的問題仍然沒有得到解決。在2017年,Prometheus的存儲迎來了 V3版本。Prometheus V3保留了高壓縮比的塊保存,將多個塊保存到一個文件中,并通過一個 index 文件去索引,從而避免產生大量的文件;并且為了防止數據丟失,引入了WAL。

如圖2-10所示,Prometheus V3將整個存儲空間按照時間水平拆分成很多獨立區間,每個區間就相當于一個獨立的數據庫。

圖2-10

V3版本的優點如下:

◎ 從 V2版本的每個時序一個文件改進到 V3版本的一段時間一個文件,可以有效避免時序流失的問題,還可以任意組織多個塊的數據到一個文件中;

◎ 每個文件塊最大支持512MB,可避免SSD寫放大;

◎ 在刪除數據的時候更簡單,直接刪除分區即可;

◎ 在查詢歷史數據時,由于已經按照時間排序,所以可以將內存數據和此磁盤數據合并,通過懶加載的方式載入數據,而不需要將所有磁盤數據加載內存,避免發生OOM。

如圖2-11所示為V3版本的存儲結構。其中wal目錄記錄的是監控數據的WAL;每個block是一個目錄,該目錄下的chunks用來保存具體的監控數據,meta.json用來記錄元數據,index則記錄索引。具體內容會在有關存儲的章節中詳細介紹。

圖2-11

2.4.2 遠程存儲

為了提高對大量歷史數據持久化存儲的能力,Prometheus 在1.6版本后支持遠程存儲,Adapter需要實現Prometheus的read接口和write接口,并且將read和write轉化為每種數據庫各自的協議,如圖2-12所示。

圖2-12

在用戶查詢數據時,Prometheus會通過配置的查詢接口發送 HTTP請求,查詢開始時間、結束時間及指標屬性等,Adapter會返回相應的時序數據;相應地,在用戶寫入數據時,HTTP請求Adapter的消息體會包含時序數組(樣本數據)。

主站蜘蛛池模板: 仁寿县| 井冈山市| 宜川县| 城口县| 丘北县| 米林县| 黎川县| 泰宁县| 抚州市| 碌曲县| 论坛| 涞水县| 舒兰市| 柳江县| 同德县| 玉门市| 盐城市| 潢川县| 广灵县| 衡阳市| 孝昌县| 始兴县| 丹棱县| 郑州市| 镶黄旗| 吕梁市| 阜南县| 夏津县| 潼南县| 左云县| 调兵山市| 盱眙县| 云阳县| 杨浦区| 衡山县| 旺苍县| 灵山县| 全椒县| 长治市| 巴彦县| 张家川|