摘要:物聯網設備產生的數據是典型的時序數據,而時序數據庫是存儲時序數據的專業數據庫系統,因此數據壓縮對時序數據庫來說是一項必不可少的能力。
本文分享自華為雲社區《華為雲數據庫GaussDB(for Influx)揭秘第二期:解密GaussDB(for Influx)的數據壓縮》,作者: 高斯Influx官方博客。
根據IDC的一份白皮書預測,到2025年全球數據總量將達到175ZB,其中物聯網設備將生成90ZB數據,占比50%以上。以往物聯網數據基本上都是先存儲起來再處理,如今這一處理模式開始向“實時處理”模式轉型。即便如此,數據的總量依然巨大,為降低數據存儲成本,迫切地要求減少數據存儲空間,這對數據壓縮技術提出了更高的要求。物聯網設備產生的數據是典型的時序數據,而時序數據庫是存儲時序數據的專業數據庫系統,因此數據壓縮對時序數據庫來說是一項必不可少的能力。
什么是數據壓縮?
眾所周知,數據在計算機內部是以二進制方式表示和存儲,因此,數據壓縮,通俗地講,就是以最少的比特數表示數據對象。數據壓縮的本質是用計算時間換取存儲空間,不同數據類型對應不同的數據壓縮算法,不存在某個壓縮算法能夠壓縮任意數據。數據壓縮說到底是對數據趨勢性、規律性的總結,這個數據規律性可分為基於內容(比如視頻的幀與幀之間,圖像的像素與像素之間的相似)、基於表示(比如變換編碼,熵編碼)和基於碼流(比如差量壓縮,深度壓縮)等多種級別。
舉一個數據壓縮的簡單例子:給定一個字符串"this is a example",正常情況下,每個字符占用8個比特位,該字符串含有17個字符(包含空格),每一個字符出現的頻率分別是a(2),e(2),h(1),i(2),m(1),p(1), t(1),s(2),x(1),l(1),空格(3). 現在我們按照字母出現的頻率進行編碼,用111表示’ ‘(空格),001表示’a’,110表示’e’,011表示’i’,000表示’s’,0101表示’h’,1011表示’m’,1000表示’p’,0100表示’t’,1010表示’x’,1001表示’l’。最后"this is a example"被編碼成 010001010110001110110001110011101010001101110001001110,共54個比特。相比未壓縮前的136比特,存儲空間縮小了2.5倍。
時序數據是如何被壓縮的?
數據通過編碼、重組或以其他方式修改數據以減少其大小來實現壓縮的目的。前面例子中提到的方法叫Huffman編碼,它是發明最早的一種數據壓縮算法,它在文本壓縮方面具有很優秀的表現。目前,數據壓縮領域發展迅速,新的技術和方法不斷涌現,層出不窮。一般我們將數據壓縮技術分為有損壓縮和無損壓縮兩大類。有損壓縮,顧名思義,數據壓縮導致數據原本攜帶的信息減少,有信息丟失,且丟失的信息無法恢復。無損壓縮則相反,數據壓縮時沒有信息丟失。在時序數據庫中,幾乎都支持無損壓縮,只有極少數支持有損壓縮。時序數據庫中常見的數據編碼和壓縮算法有如下幾種:
游程編碼(英語:run-length encoding,縮寫RLE)
一種與數據性質無關的無損數據壓縮技術,基於“使用變動長度的碼來取代連續重復出現的原始數據”來實現壓縮。舉例來說,一組字符串“AAAABBBCCDEEEE” ,由4個A、3個B、2個C、1個D、4個E組成,經過RLE可將字符串壓縮為4A3B2C1D4E。其優點是簡單、速度快,能將連續重復性高的數據壓縮成小單位。缺點也是明顯的,重復性低的數據壓縮效果不好。
XOR
該算法是結合遵循IEEE754標准的浮點數存儲格式的數據特征設計的特定算法,第一個值不壓縮, 后面的值是跟第一個值計算XOR(異或)的結果,如果結果相同,僅存儲一個0,如果結果不同,存儲XOR后的結果。該算法受數據波動影響,越劇烈壓縮效果越差。
Delta
差分編碼又稱增量編碼,編碼時,第一個數據不變,其他數據轉換為與上一個數據的delta。其原理與XOR類似,都是計算相鄰兩個數據的差異。該算法應用廣泛,如需要查看文件的歷史更改記錄(版本控制、Git等)。在時序數據庫中,很少單獨使用,一般搭配RLE,Simple8b或者Zig-zag一起使用,壓縮效果更好。
Delta-of-Delta
又名二階差分編碼,是在Delta編碼的基礎上再一次使用Delta編碼,比較適合編碼單調遞增或者遞減的序列數據。例如 2,4,4,6,8 , Delta編碼后為2,2,0,2,2 ,再Delta編碼后為2,0,-2,0,0。通常也會搭配RLE,Simple8b或者Zig-zag一起使用。
Zig-zag
Zig-zag的出現是為了解決varint算法對負數編碼效率低的問題,它的原理非常簡單,是將標志位后移至末尾,並去掉編碼中多余的0,從而達到壓縮的效果。對於比較小的數值壓縮效率很高,但是對於大的數據效率不但沒有提升可能還會有所下降。因此,Zig-zag通常和Delta編碼搭配,Delta可以很好的將大數值數據變為較小的數值。
Snappy
Snappy壓縮算法借鑒了LZ77算法的思路,由於LZ77算法中模式匹配過程有較高的時間復雜度,Google對其做了許多優化,並於2011年對外開源。其原理是假設我們有一個序列S=[9,1,2,3,4,5,1,2,3,4],匹配發現子序列S~2,5~=[1,2,3,4]與S~7,10~=[1,2,3,4]是相同的,於是將該序列編碼為S=[9,1,2,3,4,5,6,(2,4)],2表示開始位置,4表示位數。Snappy的優點是速度快,壓縮率合理,在眾多開源項目中使用,比如Cassandra,Hadoop,MongoDB,RocksDB,Spark,InfluxDB等。
LZ4
LZ4數據壓縮算法,它屬於面向字節的LZ77壓縮方案家族,壓縮比並不高,它的特點是解碼速度極快。據官方測試基准lzbench的測試結果,默認配置下,解壓速度高達4970MB/s.
Simple8b
Simple8b是64位算法,實現將多個整形數據(在0和1<<60 -1之間)壓縮到一個64位的存儲結構中。其中前4位表示選擇器,后面60位用於存儲數據。優點是簡單高效,定長編碼保證了解壓效率。但對於大整數或者浮動較大的值,壓縮率較低,適用於范圍較小的無符號整數。
LZO
LZO是塊壓縮算法,同樣屬於LZ77壓縮方案家族,該算法的目標是快速壓縮和解壓縮,並非壓縮比。相比之下,LZ4的解壓速度更快。由於塊中存放的數據類型可能多種多樣,整體的壓縮效果遠沒有針對某一種數據類型進行壓縮的算法好。
DEFLATE
DEFLATE是同時使用了LZ77算法與哈夫曼編碼(Huffman Coding)的一個經典無損數據壓縮算法。實際上deflate只是一種壓縮數據流的算法。該算法是zip文件壓縮的默認算法,在gzip,zlib等算法中都有封裝。
Zstandard
Zstandard(Zstd)的設計目的是提供一個類似於DEFLATE算法的壓縮比,但更快,特別是解壓縮。它的壓縮級別從負5級(最快)到22級(壓縮速度最慢,但是壓縮比最高)可以調節。在文本日志壓縮場景中,壓縮性能與LZ4、Snappy相當甚至更好。Linux內核,HTTP協議,Hadoop,HBase等都已經加入對Zstd的支持,可以預見,Zstd將是未來幾年里被廣泛關注的壓縮算法。
Bit-packing
Bit-packing(位壓縮)壓縮算法基於不是所有的整型都需要32位或者64位來存儲這一前提,從我們要壓縮的數據中刪除不必要的位。比如一個32位的整型數據,其值的范圍在【0,100】之間,則可以用7位就可以表示。
下表列舉了一些常見的開源時序數據庫和對應采用的數據壓縮算法。
GaussDB(for Influx)的數據壓縮
時序數據的業務特征決定了時序數據適合做壓縮,時序數據的數據特征決定了時序數據可以被很好的壓縮。數據壓縮算法的壓縮率和壓縮速度是一對矛盾,壓縮率高,必定壓縮速度就會慢,反之亦然,壓縮算法需要根據業務情況在二者之間找到合適的平衡點。數據壓縮率與數據的存儲方式密切相關,實驗表明,行存的壓縮率相比列存的壓縮率差。為了達到更好的壓縮率,華為雲GaussDB(for Influx)時序數據庫采用列式數據存儲,相同數據類型的數據被存放在一起。在壓縮算法層面,自研自適應壓縮算法,針對不同數據類型和數據分布自動適配合適的數據壓縮算法;在算法設計目標層面,數據的壓縮率、壓縮速度、解壓速度需要滿足每天萬億點寫入和海量數據下絕大部分運維監控與IoT場景典型業務的並發查詢性能要求。
時序數據的業務特征
不變性:時序數據在寫入后,一般不會被修改。這個特征非常適用於壓縮,不因修改某個數據對整個數據塊進行修改。
時效性:時間越近的數據被訪問的概率大,時間越是久遠,數據被訪問的概率越低。因此,對於時序的熱數據,可以采用壓縮和解壓速度比較好,壓縮率合理的壓縮算法,而對於冷數據,非常適合使用更高壓縮比的算法。
數據量龐大:時序數據的采集類型豐富, 隨着采集硬件的普及和采集頻率增加,使得數據量出現暴增,比如自動駕駛中每輛車每天就會采集將近 8T 的數據,帶寬、實時寫入、快速查詢、存儲、耗電以及維護成本都是挑戰。
數據使用冷熱:用戶可能對某些數據源或者時間段的關注遠遠超過其他,因此在海量數據中偏向某些特殊時間段或某些數據源的數據查詢。
時序數據的數據特征
Timestamp:穩定遞增。某些時序數據是固定頻率采樣,例如城市空氣質量檢測儀每分鍾采樣一次pm2.5含量。還有部分時序數據是按照行為變化采樣的,比如股市里的股價、交易數據、用戶使用行為。
Filed的時間屬性:同一數據源產生的時序數據都因有時間屬性而有了先后順序性和時間間隔屬性。
Filed的取值特性:不同數據源的不同指標值往往歸屬某個區間范圍,比如方向、速度、電壓、溫度等。
Filed的連續性:現實世界的事物是連續變化的,除非突發事件,或者接收數據的傳感器設備故障,否則同一數據源的數據相鄰時間段內產生的數據比較接近,比如服務器內存指標值的采集。
Filed的周期性:監控數據往往具有周期性或者規律性。
Filed的異常性:設備故障或突發事件引起的異常性。例如某個新聞事件引起網站流量的激增。
GaussDB(for Influx)自適應壓縮算法
”大道至簡“不僅是生活哲學,也是GaussDB(for Influx)自適應數據壓縮算法的設計理念,化繁為簡,合適的才是最好的。
每一種壓縮方法都有其適合的數據類型和場景,比如Simple8b適合壓縮整型數據,但是不適合大整數或者浮動較大的值,如果固定一種壓縮算法對應一種數據類型,遇到不適合的場景,數據壓縮算法便會失效。
GaussDB(for Influx)自適應壓縮算法是一套框架,為每一種數據類型注冊有若干具體數據壓縮算法,比如Int(整型)有Simple8b、Delta、Delta-Of-Delta、Zigzag,ZSTD等。與傳統的數據壓縮算法相比,本質區別在於一種數據類型並非固定一種數據壓縮算法,而是根據數據類型和數據分布選擇最合適的數據壓縮算法,比如當檢測到大整型數據時,則放棄直接使用Simple8b,先使用Delta或者Delta-Of-Delta編碼后,再使用Simple8b亦或者Zigzag算法。再比如Float(浮點)型數據,在大多時序數據庫中直接采用XOR算法,但其實在實際的應用中,一些Float類型的數據可以轉為整型來處理效果更好。
GaussDB(for Influx)自適應壓縮算法的優勢是擴展方便、靈活選擇,能充分發揮每個數據壓縮算法的最優性能。已經集成的算法有:RLE,Simple8b,Delta,Delta-Of-Delta,Zigzag,XOR,Zstd,Snappy,Bit-packing,LZ4等,未來還會繼續加入更多高效壓縮算法。目前還不支持有損壓縮,后續根據需要還會加入有損壓縮算法。
GaussDB(for Influx)與InfluxDB的壓縮率結果對比和數據集說明如下表所示:
從對比圖可以看出,自適應壓縮算法相對於開源算法在壓縮率有顯著提升,同時數據壓縮速度並未受損
總結
如今我們正處在雲計算、5G和物聯網的快速發展期,時序數據被視為越來越重要的同時,隨着數據量的暴增,企業的存儲成本也隨之提高,數據壓縮勢在必行。慶幸的是,時序業務的特點決定了時序數據非常適合被壓縮存儲,時序數據的特征決定了時序數據可以被高效壓縮。時序數據庫作為時序數據存儲的基礎系統,數據壓縮能力顯得尤為重要。華為雲時序數據庫GaussDB (for Influx) 通過對典型場景深入分析后,提出了一個更高效的時序數據壓縮算法-自適應數據壓縮算法,在風力發電物聯網場景下,250萬時間線和150億指標數據,整體數據壓縮比達到6.8,是開源InfluxDB的1.3倍,OpenTSDB的2.8倍,其他的2-3倍。在運維監控場景下,華為雲某服務存儲空間從每天1035GB降低到82GB,縮減了12.6倍。