本文根據(jù)平安產(chǎn)險(xiǎn)大數(shù)據(jù)開發(fā)工程師李凱勃、關(guān)志華在平安產(chǎn)險(xiǎn)&DataFunTalk大數(shù)據(jù)技術(shù)沙龍中分享的《Druid原理及產(chǎn)險(xiǎn)實(shí)踐》編輯整理而成。 今天分享的內(nèi)容分為兩部分,第一部分是Druid原理,包括相關(guān)選型、原理、架構(gòu)以及調(diào)優(yōu)經(jīng)驗(yàn)。第二部分是BDAS使用場景,是基于Druid做的監(jiān)控日志報(bào)表系統(tǒng)。 Druid非阿里開源的數(shù)據(jù)連接池,是一個(gè)MOLAP數(shù)據(jù)庫,架構(gòu)是MMDB架構(gòu),是一個(gè)多節(jié)點(diǎn)的系統(tǒng)。同時(shí)也是一個(gè)內(nèi)存數(shù)據(jù)庫,面向列的存儲(chǔ)。同時(shí)會(huì)使用PreAGG,是一個(gè)NoSQL數(shù)據(jù)庫,處理記錄與時(shí)間有強(qiáng)關(guān)聯(lián)的時(shí)序數(shù)據(jù)庫。Druid同時(shí)在社區(qū)支持很多插件,如kafka插件、mysql插件、hdfs插件等。 我們從去年五月份做技術(shù)選型,spark是用的比較廣的框架,特性Schema free,之前不用先定義數(shù)據(jù)格式就可以做存儲(chǔ)解析;效率高(中間結(jié)果不落盤),響應(yīng)時(shí)間依據(jù)數(shù)據(jù)量而定。最后沒有選用spark是因?yàn)椴l(fā)量上不去,因?yàn)槲覀儤I(yè)務(wù)并發(fā)量可能上千,使用spark很容易造成高溫。Elastic Search也是很熱門的一個(gè)領(lǐng)域,大家常見的理解就是一個(gè)全文搜索的引擎,其實(shí)在分析方面也有很多新技術(shù)。其特性也是Schema?free,本身架構(gòu)兼容這種數(shù)據(jù)格式,對(duì)比Druid的優(yōu)點(diǎn)是會(huì)保存原始數(shù)據(jù)。同時(shí)擁有一個(gè)完整的技術(shù)棧(elk),非常通用完善。在分析的基礎(chǔ)上有一個(gè)檢索的功能。其實(shí)選擇什么框架需要依據(jù)具體的場景,不同場景不同框架有不同的優(yōu)勢(shì)。支持高基維,但是缺點(diǎn)是數(shù)據(jù)量上不去,有時(shí)數(shù)據(jù)入庫需要做倒排索引,但是索引數(shù)據(jù)量和原始數(shù)據(jù)相差不大,最后舍棄。Druid需要預(yù)先定義維度和指標(biāo),還支持預(yù)聚合,根據(jù)時(shí)間或維度做預(yù)聚合,這樣入庫后會(huì)丟棄原始數(shù)據(jù)。數(shù)據(jù)響應(yīng)亞秒級(jí),數(shù)據(jù)可用毫秒級(jí),基本滿足需求;Lambda 架構(gòu),擴(kuò)張性、容錯(cuò)性高,我們選用的是Druid。SQL on Hadoop主要技術(shù)為MPP(大規(guī)模并行處理)和CS(列式存儲(chǔ)),特點(diǎn)是吞吐量大需要離線批量處理,我們目前是實(shí)時(shí)與離線并行使用。其他商業(yè)產(chǎn)品企業(yè)級(jí)特性,SQL支持良好,定制化硬件,天花板低(PB級(jí)別以下),非線性拓展,擴(kuò)容需要停機(jī)維護(hù),最重要的一點(diǎn)是二次開發(fā)困難。最后技術(shù)選型為Druid,將其定位為實(shí)時(shí)可用一個(gè)上升的SaaS層服務(wù),支持大型冷數(shù)據(jù)上的OLAP 場景,實(shí)現(xiàn)對(duì)一個(gè)多維度高基數(shù)的亞秒級(jí)響應(yīng)的支持。 下面是原始數(shù)據(jù)從一開始的產(chǎn)生到入庫的一些概念,原始數(shù)據(jù)有點(diǎn)類似傳統(tǒng)數(shù)據(jù)庫格式,而發(fā)表者、廣告商我們認(rèn)為是一個(gè)多維度,在入庫時(shí)都要定義好。Druid還有一個(gè)特性就是面向行級(jí)別依據(jù)時(shí)間做切分,不同的行可能會(huì)切到不同的segment里面,對(duì)于列會(huì)做一個(gè)壓縮。Segment是Druid存儲(chǔ)的基本單元,是以timestamp進(jìn)行數(shù)據(jù)分塊的,這樣做的好處是查詢的時(shí)候可以避免全局掃描,查詢就是遍歷起始時(shí)間終止時(shí)間并找到對(duì)應(yīng)數(shù)據(jù)塊,因此查詢場景比較快,真實(shí)的數(shù)據(jù)塊命名格式為數(shù)據(jù)源加開始時(shí)間和結(jié)束時(shí)間。需要注意的是如果是比較大的場景,幾個(gè)小時(shí)數(shù)據(jù)量可能就達(dá)到TB級(jí)別,這時(shí)建議在數(shù)據(jù)塊上再做一個(gè)分塊。 接下來講一下Druid數(shù)據(jù)流轉(zhuǎn),流轉(zhuǎn)圖中有很多節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都有自己的職責(zé)。中間有一個(gè)zookeeper,每一個(gè)節(jié)點(diǎn)都或多或少與其相連,zookeeper在其中負(fù)責(zé)同步作用,每一個(gè)節(jié)點(diǎn)不會(huì)做強(qiáng)關(guān)聯(lián)工作,只需要用zookeeper同步。從左到右是一個(gè)數(shù)據(jù)寫入過程,有離線數(shù)據(jù)和批量數(shù)據(jù)。 中樞節(jié)點(diǎn)Broker是查詢節(jié)點(diǎn),對(duì)外提供?REST 接口,接受來自外部客戶端的查詢,并將這些查詢轉(zhuǎn)發(fā)到 Realtime 和 Historical 節(jié)點(diǎn)。從這兩個(gè)節(jié)點(diǎn)拿數(shù)據(jù),然后將節(jié)點(diǎn)返回給Broker,將數(shù)據(jù)進(jìn)行合并返回給客戶端。這里broker節(jié)點(diǎn)起到一個(gè)轉(zhuǎn)發(fā)和合并的作用,合并過程需要規(guī)定的內(nèi)存,推薦配置內(nèi)存相對(duì)大一點(diǎn)。 歷史節(jié)點(diǎn)Historical 節(jié)點(diǎn)是非實(shí)時(shí)數(shù)據(jù)進(jìn)行處理存儲(chǔ)和查詢的地方,只響應(yīng)Broker請(qǐng)求。在查詢數(shù)據(jù)時(shí)現(xiàn)在本地找,然后在深度存儲(chǔ)里查找,查找到后返回給Broker,沒有與其他節(jié)點(diǎn)關(guān)聯(lián)。在 Zookeeper 的管理下提供服務(wù),并使用 Zookeeper 監(jiān)視信號(hào)加載或刪除新數(shù)據(jù)段。這個(gè)節(jié)點(diǎn)也是非常吃內(nèi)存,該節(jié)點(diǎn)可以多個(gè)節(jié)點(diǎn),建議使用多個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)互相不通信,同樣利用zookeeper同步,將信息解耦開來。 Coordinator扮演一個(gè)管理者的角色,負(fù)責(zé)Historical節(jié)點(diǎn)組的數(shù)據(jù)負(fù)載均衡,確保數(shù)據(jù)可用、可復(fù)制,并且處于“最佳”配置。同時(shí)通過從My SQL讀取數(shù)據(jù)段的元數(shù)據(jù)信息,來決定哪些數(shù)據(jù)段應(yīng)該在集群中被加載,使用 Zookeeper 來確定哪個(gè) Historical 節(jié)點(diǎn)存在,并且創(chuàng)建Zookeeper 條目告訴 Historical 節(jié)點(diǎn)加載和刪除新數(shù)據(jù)段。該節(jié)點(diǎn)可以是一個(gè),多個(gè)的節(jié)點(diǎn)進(jìn)行選舉產(chǎn)生 Leader,其余節(jié)點(diǎn)作為備份,一般兩個(gè)也是滿足需求的。 實(shí)時(shí)節(jié)點(diǎn)Realtime是實(shí)時(shí)攝取數(shù)據(jù),負(fù)責(zé)監(jiān)聽輸入數(shù)據(jù)流并讓其在內(nèi)部的?Druid 系統(tǒng)立即獲取。如果不需要實(shí)時(shí)加載數(shù)據(jù)就可以將該節(jié)點(diǎn)去掉,他只會(huì)響應(yīng)broker請(qǐng)求將數(shù)據(jù)返回給broker。如果Realtime和Historical節(jié)點(diǎn)同時(shí)返回同一種數(shù)據(jù),Broker會(huì)認(rèn)為Historical節(jié)點(diǎn)數(shù)據(jù)是可信的,如果數(shù)據(jù)進(jìn)入深度存儲(chǔ)Druid默認(rèn)數(shù)據(jù)是不變的。該節(jié)點(diǎn)本身會(huì)存儲(chǔ)數(shù)據(jù),如果超過一段時(shí)間窗口會(huì)將數(shù)據(jù)傳入深度存儲(chǔ),深度存儲(chǔ)將數(shù)據(jù)提供給Historical節(jié)點(diǎn)。 MySQL、zookeeper、深度存儲(chǔ)都是Druid的外部依賴,Deep Storage:可以是 HDFS 或 S3 或本地磁盤,用來保存“冷數(shù)據(jù)”,有兩個(gè)個(gè)數(shù)據(jù)來源,一個(gè)是批數(shù)據(jù)攝入, 另一個(gè)來自實(shí)時(shí)節(jié)點(diǎn);ZooKeeper 集群:為集群服務(wù)發(fā)現(xiàn)和維持當(dāng)前的數(shù)據(jù)拓?fù)涠?wù); My SQL 實(shí)例:用來維持系統(tǒng)服務(wù)所需的數(shù)據(jù)段的元數(shù)據(jù),比如去哪里加載數(shù)據(jù)段、每個(gè)數(shù)據(jù)段的元信息。 總結(jié)下各節(jié)點(diǎn)間分工明確,而且職責(zé)分離,掛掉某一個(gè)節(jié)點(diǎn)不影響其他節(jié)點(diǎn)的工作,對(duì)擴(kuò)容友好,容錯(cuò)率高。冷熱數(shù)據(jù)分離,不同數(shù)據(jù)通過硬件資源進(jìn)行物理隔離。查詢需求與數(shù)據(jù)如何在集群內(nèi)分布的需求分離:確保用戶的查詢請(qǐng)求不會(huì)影響數(shù)據(jù)在集群內(nèi)的分布情況,避免局部過熱,影響查詢性能。沒有絕對(duì)master結(jié)構(gòu),不僅僅是一個(gè)內(nèi)存數(shù)據(jù)庫,增加了內(nèi)存映射的能力。Lamada架構(gòu),能夠?qū)崟r(shí)校正數(shù)據(jù),如果數(shù)據(jù)進(jìn)入進(jìn)來節(jié)點(diǎn)沒有被消費(fèi)掉會(huì)被丟棄掉,就會(huì)出現(xiàn)數(shù)據(jù)庫性能問題。社區(qū)比較成熟的框架就是數(shù)據(jù)實(shí)時(shí)進(jìn)來寫到kafka,kafka數(shù)據(jù)兩次消費(fèi),一次在存儲(chǔ)節(jié)點(diǎn)上,一次在Hadoop上,如果數(shù)據(jù)不完整就再在Hadoop做一次embedding操作,補(bǔ)回?cái)?shù)據(jù)。 上面是一個(gè)推薦的架構(gòu),希望broker節(jié)點(diǎn)越多越好,Coordinator節(jié)點(diǎn)兩個(gè),overload兩個(gè),realtime?其他節(jié)點(diǎn)也是越多越好。性能方面也會(huì)做不同性能的轉(zhuǎn)換。調(diào)優(yōu)方面經(jīng)驗(yàn),對(duì)于broker消耗內(nèi)存大戶 ,建議 20G-30G 堆內(nèi)存,歷史節(jié)點(diǎn)除了內(nèi)存還有硬盤消耗,希望用更多的內(nèi)存去釋放硬盤的IO,Coordinator 消耗內(nèi)存相對(duì)較小,只需要滿足要求即可。查詢時(shí)盡量做一些聚合優(yōu)化,在攝入就做聚合,盡量少去group by。Historical?和?Realtime?分離,Coordinator?和?Broker?分離,在?Broker?上加?Nginx?做負(fù)載均衡,并高可用。異構(gòu)硬件方面通過劃分?Tier,讓 Historical 加載不同時(shí)間范圍的數(shù)據(jù)。 接下來講一下具體項(xiàng)目應(yīng)用,產(chǎn)險(xiǎn)原使用?Cognos ( Oracle )處理清單報(bào)表,上線有十年歷史。隨著數(shù)據(jù)量的增長、以及分析處理的訴求增加,Cognos 在 cube 過大時(shí)受限的弊端日益體現(xiàn),無法滿足實(shí)際生產(chǎn)需要。需要實(shí)現(xiàn)的第一個(gè)就是要快,第二個(gè)是想實(shí)現(xiàn)行級(jí)別的全列控制。 DBAS系統(tǒng)從去年五月份調(diào)入Druid,九月份上線了清單功能,直接查hive上數(shù)據(jù)做業(yè)務(wù)分析,12月份完全引入Druid,實(shí)現(xiàn)多維分析功能。線上一共有數(shù)十個(gè)數(shù)據(jù)源,最大數(shù)據(jù)源有上百個(gè)維度,單一維度最大屬性有幾十萬萬。聚合后單表行記錄有幾十億,最大單一數(shù)據(jù)源有幾十G,日均訪問量數(shù)千級(jí),主要應(yīng)用于產(chǎn)險(xiǎn)內(nèi)部分析,并發(fā)峰值數(shù)百,平均響應(yīng)時(shí)間 <2s。 接下來介紹下在HDFS下的使用場景,第一種是透視圖概念,用戶在某一定條件(不斷衰減)查看數(shù)據(jù)大體概要,一般采用Top N查詢,秒級(jí)響應(yīng)。響應(yīng)方式是在前端一個(gè)維度一個(gè)維度拖動(dòng),后端將上一次結(jié)果緩存,最后只查詢幾個(gè)維度。Top N查詢第一次查詢只查單一維度,當(dāng)增加維度在redis中取上一次緩存結(jié)果加下一維度,多維度會(huì)呈指數(shù)級(jí)增長,查詢速度明顯下降。我們引入單線程當(dāng)初考慮了兩種方式,第一種方式是依次將N個(gè)維度的top N都查出來,然后構(gòu)造M*N*P個(gè)多線程,這樣查詢速度會(huì)很快,大概就是一個(gè)top N的時(shí)間,這樣存在一個(gè)問題就是順序不能保障。第二種方式采用遞歸的方式,并統(tǒng)一由線程池執(zhí)行(是不是線程開線程?不是)更細(xì)粒度的緩存:如由維度A ,維度A 維度B 改為 維度A A1,維度A A2,維度A A1 維度B B1 ,這樣可以充分利用Druid的升降序,花費(fèi)的時(shí)間可能多點(diǎn),,大約需要N*M個(gè)top N的時(shí)間。 第二種場景是交叉表,分析人需要看到全量數(shù)據(jù)而不是概要數(shù)據(jù)。開始就是無論查多少維度都將其組裝成一起,當(dāng)超過4-5個(gè)維度就會(huì)效率很低。改進(jìn)的方式也是采用多線程,前面基本按照top N的方式構(gòu)造,保留最后兩個(gè)維度進(jìn)行g(shù)roup by,A1 B1 C維在查詢時(shí)有緩存策略,由于小集群采用block緩存,這樣可以省去網(wǎng)絡(luò)傳輸。兩種場景一種采用top N,一種采用group by。兩者區(qū)別top N可能會(huì)不準(zhǔn)確,top 1000能保證前900是準(zhǔn)確的。 第三種場景就是指標(biāo)計(jì)算,第一種方式是先將其計(jì)算出來存儲(chǔ)到hive上,到進(jìn)入Druid,這樣消耗很大。第二種方式是在Druid中計(jì)算,每次查詢自定義就可以比較快的得到結(jié)果。 維度合并和隱藏,合并是用戶希望把一些屬性值統(tǒng)一對(duì)待,隱藏就是減少眼睛干擾,其實(shí)更好的方式是減少一個(gè)維度就好。第四個(gè)就是實(shí)現(xiàn)行全權(quán)控制,這是需要接入用戶賬號(hào)才能實(shí)現(xiàn),用戶有一個(gè)department code,因此在每個(gè)數(shù)據(jù)源都設(shè)置了四個(gè)列,過濾后達(dá)到行全權(quán)控制。 作者介紹: 李凱勃、關(guān)志華倆位老師在大數(shù)據(jù)領(lǐng)域有多年工作經(jīng)驗(yàn),對(duì)bdas系統(tǒng)、Druid數(shù)據(jù)庫系統(tǒng)等有深入了解,專注于研究和開發(fā)大數(shù)據(jù)技術(shù)在金融領(lǐng)域的落地應(yīng)用。 ——END—— |
|