數(shù)據(jù)倉庫和傳統(tǒng)的事務型數(shù)據(jù)庫相比伶跷,一個很大的特點就是主要面向批量寫和查詢進行優(yōu)化,可以不支持更新野蝇、事務這些高級特性晰赞。一些商用的數(shù)據(jù)倉庫分析系統(tǒng),例如Vertica纽甘,已經(jīng)可以做到千億級數(shù)據(jù)的秒級導入和秒級查詢良蛮。本文主要探討如何利用現(xiàn)有的開源組件實現(xiàn)分析型數(shù)據(jù)倉庫當中的讀寫分離。
為什么要進行讀寫分離悍赢?
分析性數(shù)據(jù)倉庫一般有下面幾個特點:
- 面臨著復雜的多維分析需求决瞳,需要能夠進行任意維度的上卷下鉆。
- 存儲的數(shù)據(jù)維度一般比較多左权,所以是寬表皮胡,而且一般比較稀疏。
- 數(shù)據(jù)量比較大赏迟,一次寫入屡贺,多次查詢。
針對這樣一些特點,分析性數(shù)據(jù)庫一般選擇列存儲數(shù)據(jù)格式甩栈,例如Parquet等泻仙。優(yōu)點是對于統(tǒng)計分析效率很高,而且對于稀疏的寬表具有很高的存儲壓縮比量没。所以我們可以認為列存儲格式是一種面向讀進行優(yōu)化的存儲格式玉转,我們稱為Read Optimized Store(ROS)。但是列存儲格式還有一些缺點殴蹄,這種格式的數(shù)據(jù)一旦生成究抓,就很難進行修改,也很難往已有的數(shù)據(jù)文件當中插入新數(shù)據(jù)袭灯,只能增加新的數(shù)據(jù)文件刺下。所以我們自然而然的想到,像Mysql這種傳統(tǒng)的數(shù)據(jù)庫當中使用的行存儲文件格式是一種適合修改和插入的存儲格式妓蛮,我們可以認為這種行存儲格式是面向?qū)戇M行優(yōu)化的存儲格式怠李,我們稱為Write Optimized Store(WOS)。
綜上所訴蛤克,要實現(xiàn)一個可以秒級導入捺癞、秒級查詢的分析型數(shù)據(jù)庫,如果我們只選用ROS构挤,則很難支持大數(shù)據(jù)量的秒級導入髓介。如果我們只選用WOS,則很難實現(xiàn)任意維度的秒級查詢筋现。所以我們需要進行讀寫分離唐础。
讀寫分離的實現(xiàn)原理
數(shù)據(jù)倉庫當中需要同時存在WOS和ROS,這樣對于所有的寫操作我們都是生成WOS型文件矾飞;同時對于所有的讀操作一膨,我們主要依賴于ROS文件,但也要查詢少量的WOS文件洒沦。整體的示意圖如下:
如圖所示豹绪,WOS文件需要定期的轉(zhuǎn)換為ROS文件,同時因為ROS在數(shù)據(jù)倉庫當中一般是分為多個partition存在申眼,所以一個WOS可能需要轉(zhuǎn)化為多個ROS瞒津。同時轉(zhuǎn)化的過程需要是一個原子操作,因為對上層查詢引擎來說括尸,在同一時刻巷蚪,同樣的數(shù)據(jù)必須只能有一份。
開源方案的選擇
上面簡單介紹了讀寫分離方案的原理濒翻,在具體的工程實踐過程中我們還面臨著很多方案的選擇和實踐難點屁柏。下面簡單說一下我們的實踐選擇和碰到的技術難點啦膜,以后有時間在單獨寫一篇介紹實現(xiàn)方案。ROS的選擇比較簡單前联,我們已經(jīng)選擇了Parquet + Impala的查詢方案功戚,同時結(jié)合我們的業(yè)務特點做了很多代碼級別的優(yōu)化。WOS的選擇可能會比較多似嗤,例如我們可以選擇常用的HDFS行存儲文件格式啸臀,例如TextFile、SequenceFile烁落、Avro等乘粒。以SequenceFile為例,我們在定義自己的Impala表的時候伤塌,可以指定一個特殊的partition指定文件存儲格式為SequenceFile灯萍,同時其它的partition作為正常的按照日期partition的數(shù)據(jù)指定格式為Parquet。這種方式會簡單一些每聪,因為我們始終只有一個表旦棉。但是基于一些查詢效率和以后的架構(gòu)升級方面的考慮,我們最終選擇了Kudu作為我們的WOS药薯。架構(gòu)實現(xiàn)示意圖如下:
如圖所示绑洛,我們會建立三張物理表,其中兩張Kudu表作為WOS童本。一張Paquet表作為ROS真屯。所有的寫操作都會寫入到Ingesting狀態(tài)的Kudu表中,當Ingesting表寫到一定的大小之后穷娱,會自動轉(zhuǎn)換為Staging狀態(tài)绑蔫。這時我們一方面生成一張新的Kudu表作為Ingesting表,另一方面會開始WOS到ROS的轉(zhuǎn)換泵额。我們有一個叫做Mover的task來執(zhí)行這個操作配深,將Staging狀態(tài)的Kudu表中的數(shù)據(jù)全部轉(zhuǎn)換到對應partition的Parquet表當中。Staging狀態(tài)的表轉(zhuǎn)換完成且Ingesting狀態(tài)的表寫滿時嫁盲,會觸發(fā)一個切表操作凉馆,需要更新元數(shù)據(jù),告訴Impala使用新的數(shù)據(jù)進行查詢亡资,整個切表的操作是原子的。而且已經(jīng)轉(zhuǎn)化的Staging表還需要保留一段時間向叉,避免切表之前發(fā)起的查詢操作沒有及時執(zhí)行完成锥腻。對于查詢請求來說我們會建立一個包含Staging表、Ingesting表和ROS表的虛擬表母谎,即一個View瘦黑。用戶的查詢始終查詢始終指向的是一個View,但是下面的物理表會經(jīng)常發(fā)生變化。這樣就做到了既能查詢到最新的數(shù)據(jù)幸斥,又能夠?qū)Σ樵冃阅苓M行很好的優(yōu)化匹摇。
在實現(xiàn)的過程中還有很多具體的工作,如果:如何對表進行加列曹組甲葬,保證各個表的結(jié)構(gòu)一致廊勃;Parquet表中碎文件較多影響查詢效率如何定期的合并等。限于篇幅经窖,這里就不再具體介紹了坡垫。
寫后感
這是在簡書寫的第二篇文章,沒想到寫完第一篇文章之后簡書也成了我們的客戶(當然不是因為我_)』拢現(xiàn)在對簡書也更加親切了冰悠,也我們一起實現(xiàn)數(shù)據(jù)驅(qū)動,哈哈配乱。