概述
設(shè)計原則
- 快速查詢:部分?jǐn)?shù)據(jù)的聚合 + 內(nèi)存化 + 索引
- 水平擴(kuò)展能力:分布式數(shù)據(jù) + 并行化處理
- 實(shí)時分析:不可變的過去 + 只追加的未來
實(shí)時分析
Druid 提供了包含基于時間維度數(shù)據(jù)的存儲服務(wù),并且任何一行都是歷史真實(shí)事件。所以設(shè)計之初約定事件一旦進(jìn)入系統(tǒng)硝皂,就不可改變手趣。
歷史數(shù)據(jù)存儲以segment數(shù)據(jù)文件的方式存儲在深度存儲系統(tǒng)(S3享怀、HDFS)中吭从。當(dāng)需要查詢時,Druid在再把數(shù)據(jù)從深度存儲系統(tǒng)中裝載到內(nèi)存中查詢使用蚂四。
技術(shù)特點(diǎn)
- 數(shù)據(jù)吞吐量大
- 支持流式數(shù)據(jù)攝入和實(shí)時索引服務(wù)
- 查詢靈活且快
- 社區(qū)支持力度大
基本概念
數(shù)據(jù)格式
- 數(shù)據(jù)源(DataSource):類似數(shù)據(jù)庫中表的概念
- 時間列(TimeStamp)
- 維度列(Dimension)
- 指標(biāo)列(Metric)
如下表沥阳,時間是時間列跨琳,國家、平臺桐罕、語言是維度列脉让,激活數(shù)、充值金額是指標(biāo)列
時間 | 國家 | 平臺 | 語言 | 激活數(shù) | 充值金額 |
---|---|---|---|---|---|
2017-08-04T00:00:00.000Z | SA | ios | en | 111 | 222.00 |
數(shù)據(jù)攝入
- 實(shí)時數(shù)據(jù)攝入
- 批處理數(shù)據(jù)攝入
數(shù)據(jù)查詢
- 原生查詢是采用JSON格式功炮,通過HTTP傳送溅潜;
- 不支持標(biāo)準(zhǔn)的SQL語言查詢;
- 的社區(qū)也為我們提供了多種查詢方式(Python接口pydruid薪伏、R接口RDruid伟恶、JavaScript接口plywood、類SQL接口plyql毅该、PHP接口druid-php等)
擴(kuò)展性
- 分布式系統(tǒng),采用Lambda架構(gòu)潦牛,實(shí)時數(shù)據(jù)和批處理數(shù)據(jù)解耦眶掌;
- 實(shí)時處理面向寫多讀少優(yōu)化
- 批處理面向讀多寫少優(yōu)化
- Shared nothing架構(gòu),各個節(jié)點(diǎn)有自己的存儲和計算能力
- 使用zookeeper協(xié)調(diào)巴碗,使用mysql/postgresql提供元數(shù)據(jù)存儲
架構(gòu)
總體架構(gòu)
- 實(shí)時節(jié)點(diǎn)(Realtime Mode):即時攝入實(shí)時數(shù)據(jù)朴爬,及生成Segment數(shù)據(jù)文件;
- 歷史節(jié)點(diǎn)(Historical Mode):負(fù)責(zé)處理歷史數(shù)據(jù)存儲和查詢歷史數(shù)據(jù)(非實(shí)時)橡淆,歷史節(jié)點(diǎn)從“deep storage”下載segments召噩,將結(jié)果數(shù)據(jù)返回給查詢節(jié)點(diǎn),歷史節(jié)點(diǎn)加載完segment通知Zookeeper逸爵,歷史節(jié)點(diǎn)使用Zookeeper監(jiān)控需要加載或者刪除哪些新的具滴;
- 查詢節(jié)點(diǎn)(Broker Mode):對外提供數(shù)據(jù)查詢服務(wù),并同時從實(shí)時節(jié)點(diǎn)與歷史節(jié)點(diǎn)查詢數(shù)據(jù)师倔,合并后返回給調(diào)用方构韵;
- 協(xié)調(diào)節(jié)點(diǎn)(Coordinator Mode):負(fù)責(zé)劣勢節(jié)點(diǎn)的數(shù)據(jù)負(fù)載均衡,以及通過規(guī)則(Rule)管理數(shù)據(jù)的生命周期;
- 索引服務(wù)(Indexing Service): 索引服務(wù)節(jié)點(diǎn)由多個worker組成的集群疲恢,負(fù)責(zé)為加載批量的和實(shí)時的數(shù)據(jù)創(chuàng)建索引凶朗,并且允許對已經(jīng)存在的數(shù)據(jù)進(jìn)行修改。
索引服務(wù):
- 統(tǒng)治節(jié)點(diǎn)(Overlord Node):索引服務(wù)的主節(jié)點(diǎn)显拳,對外負(fù)責(zé)接受任務(wù)請求棚愤,對內(nèi)負(fù)責(zé)將任務(wù)分解下去并下發(fā)到從節(jié)點(diǎn)(中間管理者)上;
- 中間管理者(Middle Managers):索引服務(wù)的工作節(jié)點(diǎn)杂数,負(fù)責(zé)接收通知節(jié)點(diǎn)分配的任務(wù)宛畦,然后啟動相關(guān)的苦工接獨(dú)立的JVM完成具體的任務(wù);
- 苦工(Peons):獨(dú)立的JVM耍休,完成具體的任務(wù)刃永。
索引服務(wù)的結(jié)構(gòu)類似Hadoop Yarn 架構(gòu)。
外部依賴
- 元數(shù)據(jù)庫(MetaStore):存儲Druid集群的原始數(shù)據(jù)信息羊精,如:Segment相關(guān)信息(Msyql斯够、PostgreSQL);
- 分布式協(xié)調(diào)服務(wù)(Zookeeper):幫助群集服務(wù)發(fā)現(xiàn)和維護(hù)當(dāng)前數(shù)據(jù)的拓?fù)浣Y(jié)構(gòu)喧锦;
- 數(shù)據(jù)文件存儲庫(DeepStorage): 存放生成的Segement文件读规,并供歷史節(jié)點(diǎn)下載。
druid數(shù)據(jù)流程:

druid管理流程:

數(shù)據(jù)結(jié)構(gòu)
DataSource
Druid的DataSource類似RDBMS中的表
- 時間列(TimeStamp):表明每行數(shù)據(jù)的時間值燃少,默認(rèn)使用UTC時間且精確到毫秒束亏;
- 維度列(Dimension):用于標(biāo)識數(shù)據(jù)行的各個類別信息;
- 指標(biāo)列(Metric):用于聚合和計算的列阵具。

Druid基于DataSource結(jié)構(gòu)存儲數(shù)據(jù)時即可選擇對任意的指標(biāo)進(jìn)行聚合(Roll Up)操作碍遍。該操作主要基于維度列與時間范圍:
- 同維度列的值做聚合
- 對指定時間粒度內(nèi)的值做聚合
DataSource聚合后數(shù)據(jù):

Segment
DataSource是一個邏輯概念,Segment是數(shù)據(jù)的實(shí)際物理存儲格式阳液。
Druid正是通過 Segment實(shí)現(xiàn)了對數(shù)據(jù)的橫縱向切割( Slice and Dice)操作怕敬。從數(shù)據(jù)按時間分布的角度來看,通過參數(shù) segmentGranularity的設(shè)置帘皿, Druid將不同時間范圍內(nèi)的數(shù)據(jù)存儲在不同的 Segment數(shù)據(jù)塊中东跪,這便是所謂的數(shù)據(jù)橫向切割。這種設(shè)計為 Druid帶來一個顯而易見的優(yōu)點(diǎn):按時間范圍查詢數(shù)據(jù)時鹰溜,僅需要訪問對應(yīng)時間段內(nèi)的這些 Segment數(shù)據(jù)塊虽填,而不需要進(jìn)行全表數(shù)據(jù)范圍查詢,這使效率得到了極大的提高曹动。

同時斋日,在 Segment中也面向列進(jìn)行數(shù)據(jù)壓縮存儲,這便是所謂的數(shù)據(jù)縱向切割墓陈。而且在 Segment中使用了 Bitmap等技術(shù)對數(shù)據(jù)的訪問進(jìn)行了優(yōu)化
擴(kuò)展系統(tǒng)
實(shí)時節(jié)點(diǎn)(Realtime Mode)
實(shí)時節(jié)點(diǎn)(Realtime Node) 負(fù)責(zé)即時攝入實(shí)時數(shù)據(jù)桑驱,以及生成Segment數(shù)據(jù)文件竭恬,并提供實(shí)時數(shù)據(jù)的查詢。
- 存儲:metadata(元數(shù)據(jù))寫入MySQL熬的,在ZooKeeper中新增一條記錄S痊硕。egment定期會轉(zhuǎn)存到DeepStorage;
- 查詢:提供實(shí)時查詢索引押框,響應(yīng)broker的查詢岔绸。
master即為協(xié)調(diào)節(jié)點(diǎn)(coordinator)

- 實(shí)時節(jié)點(diǎn)緩存事件數(shù)據(jù)到內(nèi)存中的索引上,然后有規(guī)律的持久化到磁盤上橡伞。在轉(zhuǎn)移之前盒揉,持久化的索引會周期性地合并在一起。(查詢會同時命中內(nèi)存中的和已持久化的索引兑徘。)
- 實(shí)時節(jié)點(diǎn)周期性的啟動后臺的計劃任務(wù)搜索本地的持久化索引刚盈,后臺計劃任務(wù)將這些持久化的索引合并到一起并生成一塊不可變的數(shù)據(jù),這些數(shù)據(jù)塊包含了
- 一段時間內(nèi)的所有已經(jīng)由實(shí)時節(jié)點(diǎn)導(dǎo)入的事件數(shù)據(jù)挂脑,稱這些數(shù)據(jù)塊為”Segment”藕漱。
- 在傳送階段,實(shí)時節(jié)點(diǎn)將這些segment上傳到一個永久持久化的備份存儲中,即Deep Storage
歷史節(jié)點(diǎn)(Historical Mode)
歷史節(jié)點(diǎn)負(fù)責(zé)加載已生成好的數(shù)據(jù)文件以及提供數(shù)據(jù)查詢崭闲。

歷史節(jié)點(diǎn)在從下載segment前肋联,會從本地緩存檢查是否存在,如果不存在才從hdfs下載刁俭。下載完成之后橄仍,會根據(jù)zk獲取到的壓縮信息進(jìn)行解壓處理并加載到內(nèi)存,提供查詢服務(wù)牍戚。
數(shù)據(jù)分層
可以通過配置給歷史節(jié)點(diǎn)劃分不同的層(Tier)侮繁,然后在coordinator配置規(guī)則來加載指定數(shù)據(jù)源到某個層。這樣可以實(shí)現(xiàn)冷熱數(shù)據(jù)劃分處理如孝,熱數(shù)據(jù)查詢多存量小宪哩,采用更好的cpu和內(nèi)存機(jī)型配置,冷數(shù)據(jù)查詢少存量大暑竟,采用更大的硬盤機(jī)型配置
查詢節(jié)點(diǎn)(Broker Mode)
查詢節(jié)點(diǎn)對外提供數(shù)據(jù)查詢服務(wù),并同時從實(shí)時節(jié)點(diǎn)與歷史節(jié)點(diǎn)查詢數(shù)據(jù)育勺,合并后返回調(diào)用方但荤。
緩存使用
Druid使用Cache機(jī)制提高查詢效率。
- 外部緩存涧至,如:Memcached
- 本地緩存腹躁,如:查詢節(jié)點(diǎn)或歷史節(jié)點(diǎn)的內(nèi)存
協(xié)調(diào)節(jié)點(diǎn)(Coordinator Mode)
協(xié)調(diào)節(jié)點(diǎn)負(fù)責(zé) 歷史節(jié)點(diǎn)的負(fù)載均衡,并通過規(guī)則管理數(shù)據(jù)的生命周期南蓬。
- 規(guī)則(Rules):每分鐘從mysql拉取druid_rules和druid_segments纺非,rules用來告知historical將如何load和drop索引文件哑了,coordinator會讀取這些rules,然后修改zk烧颖,通知historical加載刪除指定的segment弱左,這些都可以在coordinator的UI配置;
- 負(fù)載均衡:根據(jù)zk中每個historical node負(fù)責(zé)的segment量炕淮,做負(fù)載均衡拆火;
- 副本(replication):在coordinator的UI中配置rules時,可以同時配置加載segment的備份數(shù)量涂圆,這些備份數(shù)量會以load balance的形式们镜,分配到多個historical上面。這個備份數(shù)量與hdfs的segment備份數(shù)量不一樣润歉,hdfs那個保證深度存儲的數(shù)據(jù)不會丟失模狭,historical上面?zhèn)浞菔菫榱吮WC當(dāng)某個historical掛掉的時候,其他存儲了備份segment的節(jié)點(diǎn)能接著提供查詢服務(wù)踩衩。
索引服務(wù)
索引服務(wù)包含一組組件嚼鹉,并以主從結(jié)構(gòu)作為其架構(gòu)方式。其中統(tǒng)治節(jié)點(diǎn)(Overlord Node)為主節(jié)點(diǎn)九妈,中間管理者(Middle Manager)為從節(jié)點(diǎn)反砌。

- 統(tǒng)治節(jié)點(diǎn):接收tranquility請求的實(shí)時索引task,選擇slot空閑最多的middle-manager萌朱,通過zk將task分配給middle-manager宴树,填滿為止;
- 中間管理者:通過zk獲取task晶疼,啟動本地進(jìn)程peon執(zhí)行task酒贬;
- 苦工(peon):執(zhí)行task,完成索引建立翠霍。peon本身還負(fù)責(zé)索引查詢服務(wù)锭吨。