動態數據源@四種實現方案對比

簡單描述需求,當前咱們的分析型數據都是不可變的,且每次的分析都是要將總體數據都加載到計算節點進行分析計算,因此基礎的存儲和緩存都是面向文件的,並不支持對某一行的修改,若是須要Update某些行或者插入新的記錄,須要將增量修改與原數據源聯合進行復雜的合併操做,對於常常須要修改的數據源尤爲是更新某些行的屬性值不那麼方便,若是隻是Append還好,而且還有對這個數據源的實時查詢需求,用戶但願可以在頁面上進行交互式查詢,要求響應速度亞秒級別。git

看起來這個需求很像是一個數據庫所擅長的,可是從另外的角度看,這並非典型的數據庫的應用場景,咱們平時使用數據庫都是做爲某個成熟的業務場景的數據保存,這個數據通常是提早定義好的結構,數量能夠很大可是數一個或者一組數據庫實例服務組合在一塊兒的這個集羣,其中的表格種類通常是有限的幾十最多幾百個,而在咱們的產品中,這種可變數據源不屬於產品的結構化數據,而是用戶所自定義的我的數據,屬於數據裏邊的數據,格式多種多樣,做爲一個個獨立的數據源,且使用的頻率很是低,有可能存在很大量的這種數據源,每一個的結構徹底不一樣且屬於不一樣的用戶,有可能一天也用不上一次,使用數據庫來管理這種低頻數據對資源有些浪費,大概能夠採用的方案有如下三種:github

1. 分佈式數據庫:

也就是上邊提到的,數據再也不以文件的形式存在於分佈式存儲中,而是直接寫入到支持索引和複雜查詢的數據庫中,這個數據庫能夠支持各類存儲結構,文檔、圖、key-value最好都支持,最好是支持很方便橫向的擴展,可以無限制的新建不少的數據庫和表,而且能夠控制將表加載到內存以及釋放內存,以減小資源的佔用。從NOSQL Databases這個網站看了比較了不少的數據庫,目前看來支持以上要求的數據庫有RethinkDB和ArangoDB(ArangoDB on Github),Mongodb因爲有明確的命名空間數量限制,因此建立表有數量限制,暫時不考慮,RethinkDB理念不錯且支持對錶的加載釋放,API和文檔很是友好,然而這家公司已經被收購,產品將來前景不明朗,而ArangoDB相對來講很小衆,支持的數據模型和索引種類不少,使用起來也相對比較靈活,運行效率也不錯,能夠做爲首選考慮。sql

  • 優點就是使用起來簡單,數據採用傳統的數據庫增刪改語句寫入到數據庫中,查詢也就直接使用索引,執行效率較高,使用數據庫的引擎能夠避免咱們本身去處理各類原始數據和增量數據的合併,以Write-Ahead-Log(WAL)系統爲例,其實全部的修改操做都是直接寫入日誌,由數據庫引擎去尋找對應的數據同步或者異步的將操做反應到底層的數據庫存儲中,多是某種自定義的文件結構,也多是某種更小巧的嵌入式數據庫。最終數據的存在形式通常是一個方便插入的樹型結構,常見的有B+樹,LSM樹。數據庫

  • 缺點也比較明顯,一是資源的佔用,用戶的數據做爲低頻使用數據使用數據庫來作託管相對比較昂貴,若是支持從內存中釋放還能夠減小數據庫自身的緩存處理壓力,若是表的數據很大數量不少則壓力會更大,二是寫入速度受限於數據庫集羣的處理能力,好比有大量的插入時須要路由節點的運行效率足夠高,與Alluxio這種直接寫本地緩存的速度有較大的差距,另外插入的過程當中須要創建大量的鏈接,不然單鏈接的循環寫入速度會很是慢,三是跟Spark等分佈式處理框架的結合,目前數據的輸入輸出都是類Hadoop文件的,若是直接讀取或者寫入數據庫,須要本身開發,目前這方便比較少見,你們的分析型數據要麼是直接從某系統導出要麼就是直接生成的日誌,不多直接使用分佈式計算引擎去讀取已經結構化的帶索引的數據庫,這樣也會加大當前支持業務產品服務的數據庫的壓力。四是分析型數據的使用,假如這個數據源也會常常的跟其餘數據聯合或者獨立的進行復雜的統計分析,這時典型的場景會經過Spark將數據都加載到內存中,至關於一次將數據庫全表導出的過程,比直接讀一個幾百M的文件要慢不少。緩存

2. 採用嵌入式數據庫

嵌入式數據庫相對分佈式數據庫更靈活,只須要在數據須要進行讀寫的時候啓動一個實例供調用,不用的時候數據以文件的形式存在於系統中,對資源的消耗低,同時具備數據庫讀寫的各類優點。缺點是文件只能存在於本地,若是咱們須要以統一的存儲來做爲嵌入式數據的來源,每次修改都須要去遠程分佈式文件系統去比較數據是否有更新,若是有須要加鎖並下載數據到本地,啓動實例進行讀寫,若是這時候有其餘用戶想修改則只能等待這個寫操做釋放,若是是讀操做則不影響直接下載使用。在修改完成以後將數據寫入分佈式存儲某地址,並標記新數據的地址爲該數據源地址,控制起來比較複雜,因爲沒有統一的服務實例地址,本地操做之間互不知曉,因此不支持並行寫入。一樣也有分佈式數據庫的問題,須要本身開發Spark到嵌入式數據結構的轉換代碼,若是有直接支持遠程分佈式存儲的嵌入式數據庫就比較完美了,固然這種定義自己就比較矛盾,不是嵌入式數據庫的使用場景。有個比較有趣的數據庫是CouchBase,他家的嵌入式數據庫能夠在聯網的時候將修改同步到遠程數據庫,適合網絡環境不穩定的移動端,若是要在咱們的產品中使用也存在數據同步問題,由於數據不是在固定的某個「移動端」,隨着計算資源分配的不一樣,用戶的可變數據源多是在任意一臺機器的任意的一個容器。另外就是嵌入式數據庫支持的數據量廣泛規模較小。網絡

3. 採用文件存儲+OLAP解決方案

Parquet+Druid解決方案,目前咱們採用Alluxio做爲文件還存,HDFS或者S3做爲底層的文件存儲,具體的存儲格式採用了利於分析的Parquet格式,且通過了壓縮。可是不論是Alluxio仍是Partqut,都不支持對原來數據的修改,只適合於不可變的分析型數據源,假如須要對原來的數據進行修改,須要在Spark內部進行數據的聯合,以後寫入新的數據源,這個操做消耗較大,讀寫成本高。並且直接使用SparkSQL作數據分析實時性較差,即便對DataSet作了Cache也難以在秒內返回結果,因此須要藉助於額外的索引服務,這裏考慮了Druid,Pinot,Kylin這三種OLAP方案,其中麒麟純粹的以絕對的空間換取時間,創建索引的時間也很長,使用不靈活,不考慮,前二者區別不大,成熟度上Druid更高,LinkIn 所開發的Pinot對非BitMap索引支持的較好,可能將來會比Druid好,但暫時不考慮。數據結構

Druid作的事情比較簡單,就是根據預先定義的數據格式(包括timestamp, dimension, metric 列的屬性)將批量的和實時的數據通過一個Indexing service來生成目標的segment數據,生成的數據通過了壓縮,針對不一樣的統計列和分析列來生成對應的segment數據,以本身開發的列式存儲的形式將這些中間索引數據保存下來,用戶提交的查詢通過broker節點會根據預先保存在metadata server裏邊的數據找到對應的historical節點或者realtime節點去進行索引數據的二次查詢分析,不須要查詢的節點不會收到請求,最終結果彙總到broker返回給客戶端。做爲一個額外的索引服務,其數據來源能夠是Hadoop文件系統或者兼容的協議,索引數據也能夠保存到他所定義的deep storage裏邊,也就是hdfs或者s3,保證數據也是分佈式存儲的,這個額外的服務除了佔用系統計算資源不對如今的存儲結構形成大的影響,也能夠方便的遷移或者替換,若是咱們採用了數據庫,這樣若是要切換一種數據庫,所須要的遷移工做是巨大的。框架

4. ElasticSearch解決方案

原始數據依然經過文件備份,同時發送給ES作索引服務,支持增量更新以及一些簡單的聚合運算,優點在於查詢速度快,對於須要小規模結果返回的查詢來講優點很大,索引同時攜帶原始數據,能夠做爲數據庫使用,但其核心引擎又是列式存儲,利用率很高。
ES還能夠跟Spark直接鏈接,讀取或者寫入都有成熟的connector可用,結合ES的索引能力和Spark的分析能力,能夠知足大部分的需求。異步

目前看來,選擇哪一種方案仍是看具體的需求,能知足產品的設計。
是否須要提供用戶交互界面修改數據,或者每次批量的更新規模很是小,這種狀況適合經過數據庫來託管關係型數據源。
是否常常須要從新分析這個數據源,仍是隻是用來作實時查詢展現用,若是須要分析,就會涉及倒全量數據的讀取,適合採用文件。nosql

轉載自:
https://medium.com/@leighton....

相關文章
相關標籤/搜索