聊聊時序數據庫
前陣子有朋友留言希望我寫篇關于時序數據庫的文章,以前我討論的數據庫大多數是RDBMS,其他數據庫討論的不多。說實在的對于時序數據庫,我也只是一個小學生,我的客戶使用時序數據庫在一個應用系統中只是一部分很小的功能,大部分的應用系統的主要數據還是使用關系型數據庫。
隨著工業互聯網的發展,以及物聯網技術與應用的發展,時序數據庫變得越來越熱了。時序數據庫是一種特殊的數據庫管理系統,針對時間序列數據的處理進行了優化,每條記錄都有時間戳。時序數據可能由物聯網中的傳感器、智能儀表或 RFID 產生,也可以由電網運行的各個采集點中產生,也可以從股票交易記錄中產生。
時序數據的處理與關系型數據庫的處理事不同的,時序數據庫旨在有效地收集、存儲和查詢高頻產生的各種時間序列數據。并在數據庫的入庫、批量查詢、時序數據分析和過期數據自動處理等方面有著獨特的方式。盡管可以使用傳統的關系型數據庫或者鍵值數據庫來管理時序數據。其特點是大批量的寫入帶有時間戳的數據,可能高達每秒幾百萬甚至幾千萬個。同時數據被一次寫入后不再修改,會被多次讀取使用。這些數據要么被用于實時分析,要么被用于事后研究。一般應用軟件會按照某種規則按照時間區間來裝載一批數據,或者通過內建的統計函數去分析這些數據。這種應用往往不太關注單點的數據或者幾個數據之間的關系。
因為有一部分數據量并不是很大的時序數據庫應用可以采用關系型數據庫、HBASE、REDIS這樣的KV數據庫來存儲,因此在日常應用中純時序數據庫使用的相對較少。因此時序數據庫這些年發展的不溫不火。從DB-ENGINES上看,純粹的時序數據庫的流行度得分并不高。
以第一模式為時序數據庫類型的數據庫排名看,排名最高的InfluxDB也僅僅29.15分,在數據庫流行度排名中十分靠后。如果我們把主要數據庫模式是其他類型,第二模式帶有時序數據庫模式的數據庫加上,看到的是一個完全不同的情況。
在這里我們看到了一些大佬的身影,特別是現在大火的MongDB,作為文檔數據庫,MongoDB實際上是一種多模數據庫,也支持時序數據。在國內MongoDB僅僅被作為文檔數據庫使用,僅僅存儲一些目錄與日志信息,不過MongoDB是一個十分全能的數據庫產品,支持強一致性交易,甚至在時序數據庫模式上也十分強大。西門子、博世等世界五百強企業用MongoDB來處理時序數據。在目前XC替代方面,實際上MongoDB是十分難以替代的,特別是你真正用了MongDB的事務、時序特性等,沒有第二個數據庫產品擁有MongoDB如此強大的功能。而MongoDB從商業利益上考慮將開源協議轉為SSPL后,開始收割云服務廠商,而這種接近于商用協議的開源協議極容易受到美國政府出口管制措施的影響,因此對于有XC要求的企業來說,還是要十分小心的。
令人意外的事Redis這種我們經常用來做緩沖的,十分簡單的內存KV數據庫,也是多模的,也支持時序數據。Redis支持SortedSets數據結構,支持按權重存儲數據并支持按照權重的范圍查詢。如果把時間戳作為權重值,key存儲具體的度量維度,那么Redis就可以支持時序數據了。不過這種模式過于簡單粗暴,十分消耗內存,而且并發寫入性能也不好,只適合最為簡單的模式。從Redis 5.0開始,Redis開始支持消息隊列Stream,流式數據也是時序數據處理中的一種常見場景。而真正讓Redis具有真正的流式數據庫能力的是Redis TimeSeries擴展模塊的引入。這是
在這個列表里我們還看到了最近比較火的ClickHose。Clickhouse是俄羅斯yandex公司于2016年開源的一個列式數據庫管理系統,近些年像一匹黑馬一樣迅速在具有時序處理需求的OLAP場景中收割用戶。其向量化引擎SIMD讓一些大數據量的簡單分析查詢性能得到了極大的釋放。只不過ClickHose簡單粗暴的向量引擎限制了應用的并發,不過在OLAP場景中,高并發并不總是剛需。
大多數時序數據庫的應用場景可以將時序數據庫獨立開來存儲與訪問,而應用中的較為復雜的業務數據可以放在關系型數據庫里。而時序數據的讀寫場景相對簡單,因此時序數據庫在數據庫領域的熱度較低。
有些關系型數據庫用戶開始的時候都把時序數據存儲在關系型數據庫里,不過因為時序數據的數據量太大了。會導致關系型數據庫的容量變得超大,我以前做過一個優化項目,業務數據庫的庫容高達上百TB,而實際上里面的關系型的業務數據只有幾百GB,大多數都是寫入后只讀的時序數據。后來我建議他們吧時序數據獨立出去了,這樣數據庫備份,運維就簡單多了。
而把超大規模的時序數據寫入關系型數據庫,很可能就會到達關系型數據庫的天花板,讓數據庫的性能無法跟上。如果把這類數據存儲到純粹的時序數據庫里,那么就很容易利用其分布式特性很好的橫向擴展了。時序數據庫存儲這些數據的時候,會占用更小的空間,也很容易實現自動的數據壓縮。另外利用專用的API訪問時間,對數據做復雜的匯總統計,也比SQL接口要快捷的多。因此很多企業都陸續將時序數據從傳統的關系型數據庫中分離出來,存儲到專業的時序數據庫中。
不過還有另外一種思路,那就是在關系型數據庫中增加時序數據庫的能力。最為典型的就是TimeScaleDB。當時序數據的量還不算太大的時候,有些用戶選擇了將時序數據存儲到關系型數據庫中。在PostgreSQL數據庫中安裝TimeScaleDB插件,創建時序表來存儲時序數據。同事利用PG的SQL引擎來訪問和處理這些時序數據。利用TimeScaleDB的歷史數據自動壓縮功能壓縮歷史數據,可以大大減少海量歷史數據的存儲量。我們的D-SMART中需要采集大量的數據庫的監控數據,大概每2分鐘采集一次,每次有上千個實例,每個實例有數百條記錄。這樣的話,一個納管了2000個數據庫的D-SMART,每隔兩分鐘,就會有100萬條數據被寫入TimeScaleDB,并且這些數據還需要按照時間區間,通過SQL查詢出來,進行分析處理。從這些年的使用來看,TimeScaleDB是可以輕松應對這樣的場景的,每個SQL查詢也都是幾十毫秒就可以完成。我們最初是使用PG的普通表存儲這些監控數據的,換成TimeScaleDB后,寫入性能與查詢性能都有了多倍的提升。最令我們喜歡的是歷史數據的自動壓縮功能,作為運維自動化系統,7天前的監控數據被訪問的比例很低,因此我們設置了7天數據自動壓縮,大大節約了存儲資源。
使用TimeScaleDB最大的好處是保留了我們團隊在SQL上的所有研發經驗,只要不亂寫SQL,大部分SQL不需要特殊的優化改寫,就可以達到性能要求。實現這種開發自由來自于TimeScaleDB優秀的設計,因為時間問題,我們在這里就展開討論了。如果是千萬到數億級別的時序數據處理,使用TimeScaleDB是沒有任何壓力的。
國產的時序數據庫產品也很多,在墨天輪上目前有32種國產時序數據庫,已經和DB-ENGINES上35種純時序數據庫的列表差不多長了。其中排名靠前的濤思數據的TDengine和智叟科技的DolphinDB。在DB-ENGINES的時序數據庫排行中,這兩種時序數據庫也比較靠前。也有一些國產時序數據庫基于openTSDB,或者與之兼容。
時序數據庫與時序應用的發展呈現出三種模式,大家也都在爭論哪種模式更好。
第一種模式是放棄關系型數據庫,轉向時序數據庫或者用帶有時序數據庫模式的多模數據庫替代關系型數據庫。利用原生分布式架構,帶有向量處理能力的數據庫引擎來支撐特別大數據量寫入,大數據量輸出需求的場景。這些人認為NOSQL才是時序數據處理的最終解決方案。
第二種模式正好相反,他們從NOSQL的時序數據庫轉向了具有時序數據處理能力的關系型數據庫,充分利用SQL的能力來解決應用的問題。最典型的就是我今天介紹的D-SMART里使用的TimeScaleDB。對于更大數據量的需求,可以使用CrateDB、TDengine這樣的分布式數據庫。
第三種模式是使用HBASE這樣的KV數據庫來存儲時序數據,而不專門使用時序數據庫。對于僅僅把海量時序數據找個地方存起來,滿足大并發寫入,大吞吐量輸出的場景要求就行了,大量的數據處理都是應用程序自己來干,那么這樣的用法也沒啥問題。
實際上也無需爭論,因為不同的應用場景就會選擇不同的模式。到底你選擇什么樣的時序數據庫方案,往往取決于下面幾個因素:1)你的時序數據的量級是什么樣的,每秒幾萬,幾十萬,還是幾百萬,幾千萬;2)你的時序數據如何被使用,每次讀取的批次是多少;3)你需要數據庫的內置功能來處理和分析時序數據,還是有自己的數據分析應用模塊;4)你如何處理過期的數據;5)你的歷史數據的訪問模式;6)你的查詢并發QPS是多少;……。
我想你把這幾個問題考慮清楚了,再根據目前主流的時序數據庫或者帶有時序功能的多模數據庫的特征去找尋,那么就不難做出相對靠譜的選擇了。