百度時序資料庫——儲存的省錢之道
作者簡介:任傑 百度高階研發工程師
負責百度智慧運維產品(Noah)的分散式時序資料儲存設計研發工作,在大規模分散式儲存、NoSQL資料庫方面有大量實踐經驗。
乾貨概覽
百度Noah平臺的TSDB,是百度最大規模的時序資料庫,它為Noah監控系統提供時序資料儲存與查詢服務,每天承接多達數萬億次的資料點寫入請求,以及數十億次的查詢請求。作為監控系統的後端服務,在如此大規模的寫入情況下,保證快速的查詢響應非常重要,這對系統提出了巨大挑戰。透過對使用者日常查詢行為進行分析,使用者的查詢需求與資料的時間軸有強關聯,使用者更加關心最近產生的資料。因此Noah的TSDB在架構上,利用百度BDRP(百度的Redis平臺)構建快取層,快取最近幾小時的資料,極大提升查詢效能,有效降低查詢平響。
同樣Facebook為了提高其ODS TSDB讀寫效能,設計了基於記憶體的Gorilla時序資料庫,用作ODS的write-through cache方案快取資料。可以看出在快取這層,我們都採用基於記憶體的方式做資料快取。採用記憶體最大的優勢是其資料讀寫速度遠快於磁碟速度,然而缺點是需要佔用較大的記憶體空間資源。為了有效節約記憶體空間,Gorilla設計了時序資料壓縮演算法對時序資料進行實時壓縮。在Gorilla論文[1]中表明,利用其壓縮演算法,在Facebook的生產環境下平均壓縮資料10倍。
我們在對快取層資料儲存設計的時候,結合Noah TSDB的具體情況,借鑑了Gorilla資料壓縮演算法對資料進行壓縮,儲存空間資源佔用降低了70%,有效降低資源成本。因此本文簡單和大家分享一下該壓縮演算法的基本原理,沒準兒也能節約下不少錢呢。
基礎介紹
典型的時序資料,是由Key-Value組成的二元組, Key中可能包含如Cluster、Tag、Metric、Timestamp等資訊。為了便於理解,這裡將時序資料簡單理解為Key是時間戳(Timestamp),Value是在該時間戳時的具體資料值。
假設這是某CPU在不同時間的利用率:
以這份資料為例,在後續介紹中我們一邊介紹演算法,一邊採用Gorilla的壓縮方法對這個測試資料進行壓縮,觀察該演算法壓縮效果。
壓縮思想
1基本原則
Gorilla壓縮演算法,其核心思想建立在時序資料場景下,相鄰的時序資料相似度很大這一特點之上。基於這個基本的原則,儘量只保留資料差異的部分,去除相同的部分,來達到壓縮資料的目的。
2資料結構
Gorilla將資料組織成一個個資料塊(Block),一個Block儲存連續一段時間且經過壓縮的時序資料。每次查詢的時候會直接讀取目標資料所屬的Block,對Block解壓後返回查詢結果。Facebook經驗表明,如果一個Block的時間跨度超過2小時,由於解壓Block所消耗的資源增加,其壓縮收益會逐漸降低,因此將單個Block的時間跨度設定為2小時。
每個Block的Header儲存其起始時間戳(Timebase),例如如果某時序資料產生時間點是2019/2/24 14:30,則以2小時為單位向上取整,該資料所屬的Block的Timebase為2019/2/24 14:00,時間戳為1550944800如下圖所示。然後以KV的形式依次儲存屬於該Block的時序資料。
接下來分別介紹對Key和Value的壓縮方法。
時間戳壓縮
時序資料的產生,大部分都有固定的產生時間間隔,如間隔10s、15s、60s等。即使由於各種因素造成時序資料產生有一定延遲或者提前,但是大部分資料的時間戳間隔都是在非常接近的範圍內。因此對時間戳壓縮的思想就是不需要儲存完整的時間戳,只儲存時間戳差值的差值(delta of delta)。具體以本文測試資料的時間戳Key為例介紹時間戳壓縮演算法。
壓縮前
每個秒級的時間戳用Long型儲存(8Bytes),本文測試資料中的3條資料時間戳共需要佔用3*8*8 = 192(Bits)。T均為Unix 時間戳。
Gorilla壓縮
對於每個Block:
Block的頭部Header儲存本Block的起始時間戳,不做任何壓縮。
第一個時間戳儲存 與的差值(Delta),佔用14(Bits)。
對於本Block後面的時間戳:
計算差值的差值:
存在Block中時間戳資料由 [標識位+D值] 組成,根據D的不同範圍確定標識位的取值和儲存D值所需佔用的空間。如下表所示:
具體對於本例而言,採用上述對時間戳的壓縮方式後結果如下所示:
利用上述的壓縮編碼方式對本文的測試資料編碼後,其所屬的Block內資料如下所示:
其中只填寫了T的部分,V的部分由下文進行補充。經過壓縮測試資料,總共佔用64+14+9+1=88(Bits),壓縮率為88/192=45.8%。
由於本例的測試資料較少,Header空間佔比較大,導致壓縮收益與實際環境中收益有一定差距。在實際環境中,Header所佔有的空間相對於整個Block來說比例較小,壓縮收益會更大。根據Facebook線上資料統計,如下圖所示,96%的時間戳都被壓縮到1個Bit來儲存,因此在生產環境將會帶來不錯的壓縮收益(結合資料分佈再回過頭看編碼方式,是不是有點Huffman編碼的感覺)。
資料值壓縮
對時間戳Key壓縮後,接下來對Value進行壓縮。與Key類似,透過對歷史資料進行分析,發現大部分相鄰時間的時序資料的Value值比較接近(可以理解為突增/突降的現象比較少)。而如果Value的值比較接近,則在浮點二進位制表示的情況下,相鄰資料的Value會有很多相同的位。整數型資料的相同位會更多。相同位比較多,意味著如果進行XOR運算的話會有很多位都為0。
為了便於說明,這裡首先定義一個XOR運算後的結果由三部分組成:
Leading Zeros(LZ): XOR後第一個非零位前面零的個數
Trailing Zeros(TZ): XOR後最後一個非零位後面零的個數
Meaningful Bits(MB): 中間有效位的個數
上圖是Gorilla論文裡給的示例,可以理解該資料為一系列相鄰時序資料的Value。可以看出對相鄰資料進行XOR運算後,MB、LZ和TZ非常相似。基於此,其壓縮方式參考之前其他工作[2,3]已經提出的資料壓縮方法,將當前值與前序值取XOR(異或)運算,儲存XOR運算結果。具體方式如下:
壓縮前
每個浮點型別資料Double型儲存佔用8Bytes,本文測試資料中的3條資料Value共需要佔用3*8*8 = 192(Bits)。
Gorilla壓縮
在同一個Block內,Value的壓縮規則如下:
第一個Value的值不壓縮。
對於本資料塊後面的Value值:
XOR運算結果:
對結果進行如下處理:
基於上述壓縮編碼規則,對本文測試資料的Value進行壓縮後結果如下所示,壓縮後總共佔用64+1+1+14 = 80(Bits),壓縮率為80/256=31.2%。
此時該Block內的資料如下所示:
以上就是對於Value值的壓縮方法。與Key的壓縮一樣,線上上環境資料量較多的情況下壓縮效果會更好。根據Facebook線上資料統計,59.06%的value值都被壓縮到1個位來儲存。
總的來說,利用上述的壓縮方式,我們的測試資料由384Bits(Key+Value)變為168Bits,壓縮率達到43%,具有不錯的壓縮效率。當然由於資料量的原因,在實際生產環境下壓縮收益會更大。百度Noah的TSDB在應用上述壓縮演算法的實踐中,基於我們的實際情況進行了一定的改造(後續序列文章會另行介紹),儲存空間的資源佔用減少超過70%,表明這個演算法能真實有效對時序資料進行壓縮。
另外一點,我們發現在做壓縮的時候Gorilla對Key和Value分開進行了壓縮處理。將Key和Value分開壓縮的好處在於,可以根據Key、Value不同的資料型別、資料特點,選用更適合自己的壓縮演算法,從而提高壓縮效率。在時序場景下,KV分別處理雖然不是一個新的思想,但是可以將該思想應用在多個地方。比如本文提到的Gorilla是將該思想應用在壓縮方面,FAST2016年的WiscKey[4]利用KV分離思想最佳化LSM的IO放大問題。有興趣的讀者可以針對KV分離方法探索一下。
由於本人水平有限,若理解不到位或者大家有任何想法,歡迎指出交流。
參考文獻
1. Pelkonen T , Franklin S , Teller J , et al. Gorilla: A Fast, Scalable, In-Memory Time Series Database[J]. Proceedings of the Vldb Endowment, 2015, 8(12):1816-1827.
2. P. Lindstrom and M. Isenburg. Fast and Efficient Compression of Floating-Point Data. Visualization and Computer Graphics, IEEE Transactions on, 12(5):1245–1250, 2006.
3. P. Ratanaworabhan, J. Ke, and M. Burtscher. Fast Lossless Compression of Scientific Floating-Point Data. In DCC, pages 133–142. IEEE Computer Society, 2006.
4. Lu L , Pillai T S , Gopalakrishnan H , et al. WiscKey: Separating Keys from Values in SSD-Conscious Storage[J]. ACM Transactions on Storage, 2017, 13(1):1-28.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557835/viewspace-2637499/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 百度大規模時序資料儲存(一)| 監控場景的時序資料
- Prometheus時序資料庫-磁碟中的儲存結構Prometheus資料庫
- 聚焦資料時代新儲存需求,浪潮儲存的新儲存之道
- 【融雲分析】從過剩儲存資源到分散式時序資料庫的長儲存分散式資料庫
- EMQ X + IoTDB:儲存 MQTT 訊息到時序資料庫MQQT資料庫
- 高頻時序資料的儲存與統計方案
- OceanBase時序資料庫CeresDB正式商用 提供安全可靠的資料儲存管理服務資料庫
- 浪潮儲存提出雲存智用、運籌新資料的新儲存之道
- Netflix實戰指南:規模化時序資料儲存
- 時序資料庫資料庫
- 資料成本:雲端儲存成本高嗎如何節省資料儲存成本
- 實時資料庫與時序資料庫資料庫
- 時序資料庫influxdb資料庫UX
- OceanBase 時序資料庫 CeresDB 正式商用 為使用者提供安全可靠的資料儲存管理服務資料庫
- Flutter持久化儲存之資料庫儲存Flutter持久化資料庫
- 杉巖資料:工業視覺的智慧儲存之道視覺
- 【資料庫】資料庫儲存過程(一)資料庫儲存過程
- java讀取倒序儲存的int型資料Java
- Prometheus時序資料庫-資料的查詢Prometheus資料庫
- gitlab資料庫儲存位置Gitlab資料庫
- 資料庫儲存過程資料庫儲存過程
- 初識時序資料庫資料庫
- 時序資料庫的叢集方案?資料庫
- 時序資料庫-01-時序資料庫有哪些?為什麼要使用資料庫
- Python 儲存字串時是如何節省空間的?Python字串
- 報表資料分庫儲存
- MySQL資料庫操作、儲存引擎MySql資料庫儲存引擎
- MySql資料庫——儲存過程MySql資料庫儲存過程
- Sqlserver資料庫儲存路徑的修改SQLServer資料庫
- 明解資料庫------資料庫儲存演變史資料庫
- Druid:實時分析資料儲存UI
- QuestDB時序資料庫介紹資料庫
- 時序資料庫之InfluxDB的基本操作資料庫UX
- 時序資料庫InfluxDB的基本語法資料庫UX
- 時序資料庫的秘密 —— 快速檢索資料庫
- 時間序列化資料庫選型?時序資料庫的選擇?資料庫
- MySQL 更改資料庫資料儲存目錄MySql資料庫
- 如何延長儲存伺服器上資料的儲存時間?伺服器