近期網(wǎng)絡(luò)上出現(xiàn)了有關(guān)catena、benchmarking boltdb等時間序列存儲方式的介紹,Go社區(qū)也有類似的討論話題,出現(xiàn)了seriesly、influxDB、prometheus等項目。原文作者Jason moiron目前從事Datadog相關(guān)工作,文中他針對時間序列數(shù)據(jù)庫發(fā)表了一些看法,(網(wǎng)友們在Hacker News上也有精彩的評論)我們一起來認(rèn)識下。
時間序列模型和圖模式先于計算機(jī)出現(xiàn),但是直到90年代初伴隨著MRTG的出現(xiàn)才逐漸發(fā)展壯大。這些系統(tǒng)的不斷成熟是有原因的:“大數(shù)據(jù)”的“豈止于大”;虛擬化和容器化帶來了可觀的分布式應(yīng)用節(jié)點增量;云服務(wù)對摩爾定律提出了挑戰(zhàn)。
時間序列存儲層(Time-series Storage Layer)
人們常常會這樣問自己:
有對寫入進(jìn)行優(yōu)化嗎?
有對讀取進(jìn)行優(yōu)化嗎?
數(shù)據(jù)庫要支援哪種語義學(xué)才能使用戶得到想要的查詢結(jié)果呢?
如果前兩個問題的答案是“是”,存儲層就務(wù)必同時對寫入和讀取進(jìn)行優(yōu)化。
如果你試圖對一個已索引的數(shù)據(jù)庫進(jìn)行多個序列寫入,想象下這是一個含有主鍵,時間戳,值等數(shù)據(jù)的SQL表,那么當(dāng)要處理讀請求時就不得不處理龐大的數(shù)據(jù)。如果你把序列分開寫入,那么這或許是差勁的寫入模式:高頻跨數(shù)據(jù)寫入。
我看到有的開發(fā)者的做法是:
使用文件(例如:RRD,Whisper)
使用LSM樹來備份(例如:LevelDB,RocksDB,Cassandra)
使用B-樹排序和k/v存儲(例如:BoltDB,LMDB)
這些做法有優(yōu)點也有缺點。這里不妨嘗試別的方法,時間序列是一個多點矢量,因此要做的其實很簡單:
創(chuàng)建一個新矢量
找出一個矢量(不同的)
附加到矢量上(0(1))
從矢量讀取數(shù)據(jù)
使用文件
顯然所有數(shù)據(jù)庫都是“文件式”的,但我這里所指的是文件即序列(file-as-a-series)的方式。透過該方式,你可以得到高效的緩沖附加并可進(jìn)行自由的緩存線性讀取。對于高級文件系統(tǒng)如zfs,ext4,xfs等來說,目錄記錄搜索是基于hash表的,也即意味著是0(1)。
文件系統(tǒng)越來越復(fù)雜而變得難于理解,因此需要一些黑藝術(shù)來對它進(jìn)行調(diào)節(jié)。盡管有些系統(tǒng)的設(shè)計目的是為了處理百萬級的文件,但是還沒有專門針對小文件而做的優(yōu)化處理。這樣就導(dǎo)致了對于少量數(shù)據(jù)查詢來說,很多時候都會存在空頁瀏覽的情況。后,會遍歷整個數(shù)據(jù)集,這對于備份,批量作業(yè)等操作都是有重要影響的。
使用基于樹的存儲方式
當(dāng)使用基于樹的KV存儲方式時,可以有幾種實現(xiàn)方法。鍵可以識別一個單序列,或一個單點,或一個序列中的某個時間片。無論你的鍵結(jié)構(gòu)甚或樹類似的選擇是什么,鍵查找都會是O(log n),從而在表上會留有很多空白。
對于大規(guī)模存儲時,如果點的數(shù)量過于龐大,這對于CPU緩存是個災(zāi)難;因此把數(shù)據(jù)看成是{series, timestamp} -> {point}的KV對是不會工作的。對于小規(guī)模數(shù)據(jù),開源時間序列存儲是嘗試使用類似的方式來處理,但是我很有信心地說,換用文件會更加簡單和快捷,除非你要經(jīng)常讀取很大量的數(shù)據(jù)集。對于O(log n)查找,我可不想在讀取上花費(fèi)很多時間。
所以接下來要關(guān)注寫入端,這是一個難點。使用雙B樹的COW方法看起來不適合于大量的隨機(jī)寫入。在實際中這不妨做進(jìn)一步的研究。所有這些使用mmap及頻繁微量寫入時,會對你的數(shù)據(jù)庫造成大量頁閱讀,從而導(dǎo)致f/msync的I/O處于高負(fù)荷狀態(tài)。附加在LSM上可能情況會好些,但是樹合并壓縮操作也是一個高強(qiáng)度作業(yè)。
總的來說,樹對于寫入和讀取都是可以兼顧的,這是很好的互補(bǔ)方式。
查詢語義
我認(rèn)為時間序列存儲所需的語義支持應(yīng)該是可以進(jìn)行批量和并行讀取;而其他的如壓縮讀取規(guī)模,更好的外部實現(xiàn),還有對時間序列存儲的約束等都是加分項。
維度
根據(jù)我的開發(fā)經(jīng)驗,發(fā)現(xiàn)維度是至關(guān)重要的;從產(chǎn)品層面看,缺乏對它的支持將會使你的產(chǎn)品被取代。
把所有的元數(shù)據(jù)都存入度量鍵中,然后以鍵/值(K/V)查找的方式來進(jìn)行查詢不優(yōu)的處理方式;你至少要擁有or/and和邏輯操作來實現(xiàn)跨維度;例如:eg: az=us-east-1 AND role=db-master, version=2.1 OR version=2.3,若有更豐富操作的語言則更好。但對于存儲層來說需要支援任何的額外語義來實現(xiàn)這些優(yōu)化嗎?在維度存儲中,查詢中的索引要么指向了大量無關(guān)數(shù)據(jù)的元組,要么包含了數(shù)據(jù)本身從而導(dǎo)致寫入緩慢。SSD方式或許好些,但仍需讀取所有數(shù)據(jù)頁才有效;數(shù)據(jù)位置仍是個問題。
聚合,失效等
時間聚合和數(shù)據(jù)失效在輪詢調(diào)度中的重要性不言而喻,這仍是開源的標(biāo)準(zhǔn)。例如rrdtool,graphite等。
此外還有幾個重要問題亟需解決。RRD是連續(xù)空間,但時間序列的使用往往包含了大量的稀疏序列。另外,對于寫入的壓縮/聚合會使寫入操作變得龐大。聚合和失效看起來很像維度:可以在一個獨立策略層中異步實現(xiàn)。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個個人學(xué)習(xí)交流的平臺,網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對作者和來源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請及時聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對此聲明的最終解釋權(quán)。