达观数据分析平台架构和Hive实践
http://www.infoq.com/cn/articles/hadoop-ten-years-part03
編者按:Hadoop于2006年1月28日誕生,至今已有10年,它改變了企業(yè)對(duì)數(shù)據(jù)的存儲(chǔ)、處理和分析的過程,加速了大數(shù)據(jù)的發(fā)展,形成了自己的極其火爆的技術(shù)生態(tài)圈,并受到非常廣泛的應(yīng)用。在2016年Hadoop十歲生日之際,InfoQ策劃了一個(gè)Hadoop熱點(diǎn)系列文章,為大家梳理Hadoop這十年的變化,技術(shù)圈的生態(tài)狀況,回顧以前,激勵(lì)以后。
近十年來,隨著Hadoop生態(tài)系統(tǒng)的不斷完善,Hadoop早已成為大數(shù)據(jù)事實(shí)上的行業(yè)標(biāo)準(zhǔn)之一。面對(duì)當(dāng)今互聯(lián)網(wǎng)產(chǎn)生的巨大的TB甚至PB級(jí)原始數(shù)據(jù),利用基于Hadoop的數(shù)據(jù)倉(cāng)庫(kù)解決方案Hive早已是Hadoop的熱點(diǎn)應(yīng)用之一。達(dá)觀數(shù)據(jù)團(tuán)隊(duì)長(zhǎng)期致力于研究和積累Hadoop系統(tǒng)的技術(shù)和經(jīng)驗(yàn),并構(gòu)建起了分布式存儲(chǔ)、分析、挖掘以及應(yīng)用的整套大數(shù)據(jù)處理平臺(tái)。
本文將從Hive原理、數(shù)據(jù)分析平臺(tái)架構(gòu)、數(shù)據(jù)分析實(shí)戰(zhàn)、Hive優(yōu)化等四個(gè)方面來分享一些關(guān)于系統(tǒng)架構(gòu)和Hive的心得和實(shí)戰(zhàn)經(jīng)驗(yàn),希望大家有所收獲。
1 Hive原理
Hadoop是一個(gè)流行的開源框架,用來存儲(chǔ)和處理商用硬件上的大規(guī)模數(shù)據(jù)集。對(duì)于HDFS上的海量日志而言,編寫Mapreduce程序代碼對(duì)于類似數(shù)據(jù)倉(cāng)庫(kù)的需求來說總是顯得相對(duì)于難以維護(hù)和重用,Hive作為一種基于Hadoop的數(shù)據(jù)倉(cāng)庫(kù)解決方案應(yīng)運(yùn)而生,并得到了廣泛應(yīng)用。
Hive是基于Hadoop的數(shù)據(jù)倉(cāng)庫(kù)平臺(tái),由Facebook貢獻(xiàn),其支持類似SQL的結(jié)構(gòu)化查詢功能。Facebook設(shè)計(jì)開發(fā)Hive的初衷就是讓那些熟悉sql編程方式的人也可以更好的利用hadoop,hive可以讓數(shù)據(jù)分析人員只關(guān)注于具體業(yè)務(wù)模型,而不需要深入了解Map/Reduce的編程細(xì)節(jié),但是這并不意味著使用hive不需要了解和學(xué)習(xí)Map/Reduce編程模型和hadoop。對(duì)于Hive分析人員來說,深入了解Hadoop和Hive的原理和Mapreduce模型,對(duì)于優(yōu)化查詢總有益處。
1.1 Hive組件與模型
Hive的組件總體上可以分為以下幾個(gè)部分:用戶接口(UI)、驅(qū)動(dòng)、編譯器、元數(shù)據(jù)(Hive系統(tǒng)參數(shù)數(shù)據(jù))和執(zhí)行引擎。Hive中包含4中數(shù)據(jù)模型:Tabel、ExternalTable、Partition、Bucket。
圖:hive數(shù)據(jù)模型
a) Table:每一個(gè)Table在Hive中都有一個(gè)相應(yīng)的目錄來存儲(chǔ)數(shù)據(jù);
b) Partition:表中的一個(gè)Partition對(duì)應(yīng)于表下的一個(gè)目錄,所有的Partition數(shù)據(jù)都存儲(chǔ)在對(duì)應(yīng)的目錄中;
c) Buckets:對(duì)指定列計(jì)算的hash,根據(jù)hash值切分?jǐn)?shù)據(jù),目的是為了便于并行,每一個(gè)Buckets對(duì)應(yīng)一個(gè)文件;
d) External Table指向已存在HDFS中的數(shù)據(jù),可創(chuàng)建Partition。
讀時(shí)驗(yàn)證機(jī)制
與傳統(tǒng)數(shù)據(jù)庫(kù)對(duì)表數(shù)據(jù)進(jìn)行寫時(shí)嚴(yán)重不同,Hive對(duì)數(shù)據(jù)的驗(yàn)證方式為讀時(shí)模式,即只有在讀表數(shù)據(jù)的時(shí)候,hive才檢查解析具體的字段、shema等,從而保證了大數(shù)據(jù)量的快速加載。
如果表schema與表文件內(nèi)容不匹配,Hive會(huì)盡其所能的去讀數(shù)據(jù)。如果schema中表有10個(gè)字段,而文件記錄卻只有3個(gè)字段,那么其中7個(gè)字段將為null;如果某些字段類型定位為數(shù)值類型,但是記錄中卻為非數(shù)值字符串,這些字段也將會(huì)被轉(zhuǎn)換為null。Hive會(huì)努力catch讀數(shù)據(jù)時(shí)遇到的錯(cuò)誤,并努力返回。既然Hive表數(shù)據(jù)存儲(chǔ)在HDFS中且Hive采用的是讀時(shí)驗(yàn)證方式,定義完表的schema會(huì)自動(dòng)生成表數(shù)據(jù)的HDFS目錄,且我們可以以任何可能的方式來加載表數(shù)據(jù)或者利用HDFS API將數(shù)據(jù)寫入文件,同理,當(dāng)我們?nèi)粜枰獙ive數(shù)據(jù)寫入其他庫(kù)(如oracle),也可以直接通過api讀取數(shù)據(jù)再寫入目標(biāo)庫(kù)。
再次注意,加載或者寫入的數(shù)據(jù)內(nèi)容要和表定義的schema一致,否則將會(huì)造成字段或者表為空。
1.2 HQL翻譯成MapReduce Job
Hive編譯器將HQL代碼轉(zhuǎn)換成一組操作符(operator),操作符是Hive的最小操作單元,每個(gè)操作符代表了一種HDFS操作或者M(jìn)apReduce作業(yè)。Hive中的操作符包括:TableScanOperator、ReduceSinkOperator、JoinOperator、SelectOperator、FileSinkOperator、FilterOperator、GroupByOperator、MapJoinOperator等。
Hive語句
INSERT OVERWRITE TABLE read_log_tmp SELECT a.userid,a.bookid,b.author,b.categoryid FROM user_read_log a JOIN book_info b ON a.bookid = b.bookid;其執(zhí)行計(jì)劃為:
圖:join的任務(wù)執(zhí)行流程
1.3 與一般SQL的區(qū)別
Hive 視圖與一般數(shù)據(jù)庫(kù)視圖
Hive視圖只支持邏輯視圖,不支持物化視圖,即每次對(duì)視圖的查詢hive都將執(zhí)行查詢?nèi)蝿?wù),因此視圖不會(huì)帶來性能上的提升。作為Hive查詢優(yōu)化的一部分,對(duì)視圖的查詢條件語句和視圖的定義查詢條件語句將會(huì)盡可能的合并成一個(gè)條件查詢。
Hive索引與一般數(shù)據(jù)庫(kù)索引
Hive1.2.1版本目前支持的索引類型有CompactIndexHandler和Bitmap。
CompactIndexHandler 壓縮索引通過將列中相同的值得字段進(jìn)行壓縮從而減小存儲(chǔ)和加快訪問時(shí)間。需要注意的是Hive創(chuàng)建壓縮索引時(shí)會(huì)將索引數(shù)據(jù)也存儲(chǔ)在Hive表中。對(duì)于表tb_index (id int, name string) 而言,建立索引后的索引表中默認(rèn)的三列一次為索引列(id)、hdfs文件地址(_bucketname)、偏移量(offset)。
Bitmap 位圖索引作為一種常見的索引,如果索引列只有固定的幾個(gè)值,那么就可以采用位圖索引來加速查詢。利用位圖索引可以方便的進(jìn)行AND/OR/XOR等各類計(jì)算,Hive0.8版本開始引入位圖索引,位圖索引在大數(shù)據(jù)處理方面的應(yīng)用廣泛,比如可以利用bitmap來計(jì)算用戶留存率(索引做與運(yùn)算,效率遠(yuǎn)好于join的方式)。如果Bitmap索引很稀疏,那么就需要對(duì)索引壓縮以節(jié)省存儲(chǔ)空間和加快IO。Hive的Bitmap Handler采用的是EWAH(https://github.com/lemire/javaewah)壓縮方式。
2 數(shù)據(jù)分析平臺(tái)
2.1 架構(gòu)與模塊
達(dá)觀數(shù)據(jù)分析平臺(tái)包括數(shù)據(jù)收集加載模塊、數(shù)據(jù)分析計(jì)算模塊、任務(wù)調(diào)度系統(tǒng)以及可視化系統(tǒng)。
圖:數(shù)據(jù)分析平臺(tái)基本框架
數(shù)據(jù)收集模塊
數(shù)據(jù)模塊負(fù)責(zé)收集移動(dòng)端app、網(wǎng)頁端以及服務(wù)器端大量的日志數(shù)據(jù)。移動(dòng)端可自行開發(fā)數(shù)據(jù)上報(bào)功能或者使用sdk來上報(bào)數(shù)據(jù)。網(wǎng)頁端利用植入的js將用戶的行為進(jìn)行上報(bào),服務(wù)器端通過http server來收集上報(bào)的數(shù)據(jù)。服務(wù)器端的日志信息可以通過DX模塊(一個(gè)跨庫(kù)的數(shù)據(jù)交換系統(tǒng))來將待處理數(shù)據(jù)推入hive數(shù)據(jù)分析平臺(tái)。除此之外,數(shù)據(jù)來源還包括大量的user 、item基本數(shù)據(jù)等等。數(shù)據(jù)收集完成將所有需要處理分析的原始數(shù)據(jù)推入hadoop平臺(tái)。從物理形式來看,即將待分析數(shù)據(jù)寫入HDFS。
數(shù)據(jù)ETL模塊
一般而言,上報(bào)的數(shù)據(jù)都是非結(jié)構(gòu)化或者半結(jié)構(gòu)化的。ETL(抽取、轉(zhuǎn)換、加載)模塊負(fù)責(zé)將所有的非結(jié)構(gòu)或者半結(jié)構(gòu)的數(shù)據(jù)轉(zhuǎn)換成結(jié)構(gòu)化的數(shù)據(jù)并加載到hive庫(kù)表中。例如對(duì)于用戶訪問日志(可能是web server日志),我們需要從每行日志中抽取出用戶的標(biāo)識(shí)(cookie、imei或者userid),ip來源、url等。從形式上來看,ETL將HDFS的原始數(shù)據(jù)結(jié)構(gòu)化,以表的形式提供分析。
數(shù)據(jù)分析與計(jì)算
根據(jù)業(yè)務(wù)需求和功能,利用HQL實(shí)現(xiàn)各種統(tǒng)計(jì)分析。一個(gè)Hive任務(wù)的來源表可能是多個(gè),結(jié)果數(shù)據(jù)也有可能會(huì)寫入多張表。
圖:Hive任務(wù)執(zhí)行輸入輸出
任務(wù)調(diào)度系統(tǒng)
從上圖可以看出,Hive任務(wù)之間存在依賴關(guān)系,不至于Hive任務(wù)之間存在依賴,Hive任務(wù)與DX任務(wù)之間、DX任務(wù)之間都可能存在某種依賴關(guān)系,達(dá)觀數(shù)據(jù)分析平臺(tái)支持的任務(wù)類型還包括MR任務(wù)、shell任務(wù)等,達(dá)觀數(shù)據(jù)分析平臺(tái)自行開發(fā)司南調(diào)度系統(tǒng)來完成平臺(tái)中所有任務(wù)的調(diào)度。關(guān)于司南調(diào)度系統(tǒng)可見后續(xù)討論。
數(shù)據(jù)分析平臺(tái)模塊
圖:數(shù)據(jù)分析平臺(tái)基本模塊
接下來將陸續(xù)介紹,數(shù)據(jù)分析平臺(tái)中的兩個(gè)重要模塊:DX數(shù)據(jù)交換系統(tǒng)以及任務(wù)調(diào)度系統(tǒng)。
2.2 DX數(shù)據(jù)交換
DX系統(tǒng)可以在關(guān)系型數(shù)據(jù)庫(kù)、Hive、FTP等系統(tǒng)之間實(shí)現(xiàn)數(shù)據(jù)的交換。DX定義了Writer和Reader接口來抽象對(duì)數(shù)據(jù)的讀寫操作,對(duì)于各種存儲(chǔ)類型的數(shù)據(jù),需定制他們的實(shí)現(xiàn)方法。
關(guān)系型數(shù)據(jù)庫(kù)利用JDBC實(shí)現(xiàn)其讀寫功能;對(duì)于Hive而言,直接利用HDFS API實(shí)現(xiàn)對(duì)HDFS文件的讀寫,由于Hive的讀時(shí)驗(yàn)證機(jī)制,需要在讀寫Hive表文件時(shí),定義其字段個(gè)數(shù)、名稱等信息,保證與表定義一致;FTP文件目前的處理方法是先將數(shù)據(jù)從FTP服務(wù)器拉下來,然后將讀取文件內(nèi)容,寫入Hive數(shù)據(jù)庫(kù)。
以上過程是其他數(shù)據(jù)源到Hive的數(shù)據(jù)傳輸過程,Hive數(shù)據(jù)同樣可以通過DX系統(tǒng)寫入其他數(shù)據(jù)源。
2.3 任務(wù)調(diào)度
達(dá)觀數(shù)據(jù)分析平臺(tái)開發(fā)的司南調(diào)度系統(tǒng)將任務(wù)分為資源依賴型和實(shí)踐依賴型。時(shí)間依賴型任務(wù)類似于crontab定時(shí)任務(wù)一樣,到時(shí)觸發(fā)其執(zhí)行。資源依賴型任務(wù)需要其依賴的資源都滿足時(shí)才會(huì)觸發(fā)其執(zhí)行。可調(diào)度的任務(wù)類型包括DX任務(wù)、Hive任務(wù)、MR任務(wù)、shell任務(wù)等。
司南系統(tǒng)中最為關(guān)鍵的是dispatcher模塊,該模塊通過zookeeper來調(diào)度任務(wù)在agent(執(zhí)行任務(wù)的代理服務(wù)器,需要設(shè)置多個(gè))上的運(yùn)行,關(guān)于zookeeper如何協(xié)調(diào)分布式應(yīng)用的一致性在此不再累述。
2.4 架構(gòu)演化
達(dá)觀數(shù)據(jù)分析平臺(tái)在使用過程中,不斷提高其易用性和穩(wěn)定性。在大量的研究和開發(fā)過程中,平臺(tái)從無到有,走出第一步到功能完善、發(fā)揮巨大的業(yè)務(wù)價(jià)值。
從分散的數(shù)據(jù)交換到集中的數(shù)據(jù)交換系統(tǒng)
在使用統(tǒng)一的數(shù)據(jù)交換系統(tǒng)DX后,各業(yè)務(wù)系統(tǒng)的數(shù)據(jù)可以更好的進(jìn)行匯聚和打通,進(jìn)行統(tǒng)一的分析和處理。
從分散的作業(yè)調(diào)度到集中的任務(wù)調(diào)度系統(tǒng)
每天幾千規(guī)模的任務(wù)數(shù)使得任務(wù)的調(diào)度極其困難,特別是當(dāng)任務(wù)之間存在依賴關(guān)系時(shí),顯然簡(jiǎn)單的通過crontab已經(jīng)無法滿足業(yè)務(wù)的需求。司南調(diào)度系統(tǒng)保證所有任務(wù)有序正確的運(yùn)行。
從批量式處理到集成流式處理
隨著實(shí)時(shí)統(tǒng)計(jì)分析的需求越來越多,hive查詢基于MR任務(wù)來實(shí)現(xiàn)的缺點(diǎn)日益明顯(任務(wù)啟動(dòng)開銷大)。為了提供實(shí)時(shí)的數(shù)據(jù)分析請(qǐng)求,平臺(tái)開始引入storm流式計(jì)算模型。Storm以數(shù)據(jù)流為驅(qū)動(dòng)。觸發(fā)計(jì)算,每來一條數(shù)據(jù)就產(chǎn)生一次計(jì)算結(jié)果,時(shí)效性非常高,在業(yè)界也得到了豐富的應(yīng)用。
從關(guān)系型數(shù)據(jù)庫(kù)到Hbase
初期,數(shù)據(jù)分析的結(jié)果數(shù)據(jù)都是通過DX導(dǎo)入關(guān)系型數(shù)據(jù)庫(kù),以便數(shù)據(jù)可視化平臺(tái)調(diào)用或者其他系統(tǒng)使用,大量的數(shù)據(jù)造成關(guān)系數(shù)據(jù)庫(kù)的日益龐大,帶來嚴(yán)重的性能問題。HBase是一個(gè)開源、列式分布式的數(shù)據(jù)庫(kù),基于HDFS文件系統(tǒng),可以方面的和Hive進(jìn)行集成。經(jīng)過集成HBase,為可視化平臺(tái)和線上系統(tǒng)提供服務(wù),降低DX任務(wù)量,降低訪問延遲。
3 Hive分析實(shí)踐
3.1 Schema設(shè)計(jì)
沒有通用的schema,只有合適的schema。在設(shè)計(jì)Hive的schema的時(shí)候,需要考慮到存儲(chǔ)、業(yè)務(wù)上的高頻查詢?cè)斐傻拈_銷等等,設(shè)計(jì)適合自己的數(shù)據(jù)模型。
設(shè)置分區(qū)表
對(duì)于Hive來說,利用分區(qū)來設(shè)計(jì)表總是必要的,分區(qū)提供了一種隔離數(shù)據(jù)和優(yōu)化查詢的便利的方式。設(shè)置分區(qū)時(shí),需要考慮被設(shè)置成分區(qū)的字段,按照時(shí)間分區(qū)一般而言就是一個(gè)好的方案,其好處在于其是按照不同時(shí)間粒度來確定合適大小的數(shù)據(jù)積累量,隨著時(shí)間的推移,分區(qū)數(shù)量的增長(zhǎng)是均勻的,分區(qū)的大小也是均勻的。
避免小文件
雖然分區(qū)有利于隔離數(shù)據(jù)和查詢,設(shè)置過多過細(xì)的分區(qū)也會(huì)帶來瓶頸,主要是因?yàn)檫^多的分區(qū)意味著文件的數(shù)目就越多,過多增長(zhǎng)的小文件會(huì)給namecode帶來巨大的性能壓力。同時(shí)小文件過多會(huì)影響JOB的執(zhí)行,hadoop會(huì)將一個(gè)job轉(zhuǎn)換成多個(gè)task,即使對(duì)于每個(gè)小文件也需要一個(gè)task去單獨(dú)處理,帶來性能開銷。因此,hive表設(shè)計(jì)的分區(qū)不應(yīng)該過多過細(xì),每個(gè)目錄下的文件足夠大,應(yīng)該是文件系統(tǒng)中塊大小的若干倍。
選擇文件格式
Hive提供的默認(rèn)文件存儲(chǔ)格式有textfile、sequencefile、rcfile等。用戶也可以通過實(shí)現(xiàn)接口來自定義輸入輸?shù)奈募袷健?/p>
在實(shí)際應(yīng)用中,textfile由于無壓縮,磁盤及解析的開銷都很大,一般很少使用。Sequencefile以鍵值對(duì)的形式存儲(chǔ)的二進(jìn)制的格式,其支持針對(duì)記錄級(jí)別和塊級(jí)別的壓縮。rcfile是一種行列結(jié)合的存儲(chǔ)方式(text file和sequencefile都是行表[row table]),其保證同一條記錄在同一個(gè)hdfs塊中,塊以列式存儲(chǔ)。rcfile的聚合運(yùn)算不一定總是存在,但是rcfile的高壓縮率確實(shí)減少文件大小,因此實(shí)際應(yīng)用中,rcfile總是成為不二的選擇,達(dá)觀數(shù)據(jù)平臺(tái)在選擇文件存儲(chǔ)格式時(shí)也大量選擇了rcfile方案。
3.2 統(tǒng)計(jì)分析
本節(jié)將從排序和窗口函數(shù)兩個(gè)方面的介紹Hive的統(tǒng)計(jì)分析功能。
排名
熱門排名在實(shí)際的業(yè)務(wù)場(chǎng)景中經(jīng)常遇見。例如最受歡迎的書籍、銷量TOP100的商品等等。再實(shí)際情況下,我們不僅需要考慮各量化指標(biāo),還需要考慮置信度問題。
最簡(jiǎn)單的排名:ORDER BY value LIMIT n
上述查詢僅僅考慮了量化指標(biāo),排名不夠平滑,波動(dòng)較大。
各種排名方法眾多,達(dá)觀數(shù)據(jù)分析平臺(tái)在進(jìn)行item 排名多采用基于用戶投票的排名算法。如基于威爾遜區(qū)間的排名算法,該算法可以較好的解決小樣本的不準(zhǔn)確問題。
圖:威爾遜區(qū)間
窗口分析函數(shù)
Hive提供了豐富了數(shù)學(xué)統(tǒng)計(jì)函數(shù),同時(shí)也提供了用戶自定義函數(shù)的接口,用戶可以自定義UDF、UDAF、UDTF Hive 0.11版本開始提供窗口和分析函數(shù)(Windowing and Analytics Functions),包括LEAD、LAG、FIRST_VALUE、LAST_VALUE、RANK、ROW_NUMBER、PERCENT_RANK、CUBE、ROLLUP等。窗口函數(shù)與聚合函數(shù)一樣,都是對(duì)表子集的操作,從結(jié)果上看,區(qū)別在于窗口函數(shù)的結(jié)果不會(huì)聚合,原有的每行記錄依然會(huì)存在。窗口函數(shù)的典型分析應(yīng)用包括:按分區(qū)聚合(排序,top n問題)、行間計(jì)算(時(shí)間序列分析)、關(guān)聯(lián)計(jì)算(購(gòu)物籃分析)。
我們以一個(gè)簡(jiǎn)單的行間計(jì)算的例子說明窗口函數(shù)的應(yīng)用(關(guān)于其他函數(shù)的具體說明,請(qǐng)參考hive文檔)。用戶閱讀行為的統(tǒng)計(jì)分析需要從點(diǎn)擊書籍行為中歸納統(tǒng)計(jì)出來。用戶瀏覽日志結(jié)構(gòu)如下表所示,每條記錄為用戶的單次點(diǎn)擊行為。
通過對(duì)連續(xù)的用戶點(diǎn)擊日志分析,通過Hive提供的窗口分析函數(shù)可以計(jì)算出用戶各章節(jié)的閱讀時(shí)間。
SELECT userid, bookid, chapterid, end_time – start_time as read_time FROM (SELECT userid, bookid, chapterid, log_time as start_time, lead(log_time,1,null) over(partition by userid, bookid order by log_time) as end_time FROM user_read_log where pt=’2015-12-01’ ) t;通過上述查詢既可以找出2015-12-01日所有用戶對(duì)每一章節(jié)的閱讀時(shí)間。只能通過開發(fā)mr代碼或者實(shí)現(xiàn)udaf來實(shí)現(xiàn)上述功能。
窗口分析函數(shù)關(guān)鍵在于定義的窗口數(shù)據(jù)集及其對(duì)窗口的操作,通過over(窗口定義語句)來定義窗口。日常分析和實(shí)際應(yīng)用中,經(jīng)常會(huì)有窗口分析應(yīng)用的場(chǎng)景,例如基于分區(qū)的排序、集合、統(tǒng)計(jì)等復(fù)雜操作。例如我們需要統(tǒng)計(jì)每個(gè)用戶閱讀時(shí)間最多的3本書:
圖:行間計(jì)算示意圖及代碼
窗口函數(shù)使得Hive的具備了完整的數(shù)據(jù)分析功能,在實(shí)際的應(yīng)用環(huán)境中,達(dá)觀數(shù)據(jù)分析團(tuán)隊(duì)大量使用hive窗口分析函數(shù)來實(shí)現(xiàn)較為復(fù)雜的邏輯,提高開發(fā)和迭代效率。
3.3 用戶畫像
用戶畫像即基于真實(shí)數(shù)據(jù)的用戶模型。簡(jiǎn)單來說,用戶畫像提取了用戶的屬性信息、行為信息,從而歸納統(tǒng)計(jì)出其人口學(xué)特征、偏好特征等。建立用戶模型的首要任務(wù)就是提取特征,既包括用戶基本特征,也包括行為特征和統(tǒng)計(jì)特征。
用戶模型本質(zhì)上就是刻畫用戶興趣的模型,而用戶的興趣模型是多維度、多尺度的。刻畫用戶模型還需要從時(shí)間上進(jìn)行度量,甚至是進(jìn)行多尺度的組合,根據(jù)用戶行為統(tǒng)計(jì)時(shí)間的長(zhǎng)短,可以將用戶的偏好分為短期偏好和長(zhǎng)期偏好。偏好的權(quán)重即為用戶的偏好程度的度量。
對(duì)用戶偏好的描述,還需要考慮置信度的問題,例如對(duì)于一個(gè)閱讀行為極其稀疏的用戶來說,刻畫其閱讀類別偏好是毫無意義的。
圖:用戶畫像刻畫
3.4 反作弊分析
眾所周知,存在排名就可能存在作弊。搜索廣告、索互聯(lián)網(wǎng)刷單、刷榜現(xiàn)象層出不窮。一般來說,作弊的目的都是為了提高自己的排名,或者是降低對(duì)手的排名。利用Hive對(duì)數(shù)據(jù)進(jìn)行分析可以過濾掉較明顯的作弊數(shù)據(jù),達(dá)到數(shù)據(jù)清洗的目的。
例如對(duì)于一個(gè)刷榜作弊行為,需要作弊著不斷刷日志行為來提高其排名,我們可以指定若干規(guī)則來過濾作弊數(shù)據(jù)。如同IP同物品同行為數(shù)目異常、同用戶ID行為頻次異常、同物品ID行為頻次異常等等。如下圖,如果相比于所有item的平均增長(zhǎng)趨勢(shì),如果某item的增長(zhǎng)趨勢(shì)相對(duì)平均水平過大,那么其作弊的概率就比較高。
圖:作弊數(shù)據(jù)趨勢(shì)與平均趨勢(shì)數(shù)據(jù)對(duì)比
作弊分析還需要結(jié)合業(yè)務(wù)需求和特點(diǎn),采用合適的機(jī)器學(xué)習(xí)算法來進(jìn)行更進(jìn)一步的判斷和過濾,達(dá)到反作弊的目標(biāo)。
4 Hive優(yōu)化
達(dá)觀的數(shù)據(jù)倉(cāng)庫(kù)基于Hive搭建,每日需要處理大量的計(jì)算流程,Hive的穩(wěn)定性和性能至關(guān)重要。眾多的任務(wù)需要我們合理的調(diào)節(jié)分配集群資源,合理的配置各參數(shù),合理的優(yōu)化查詢。Hive優(yōu)化包含各個(gè)方面,如job個(gè)數(shù)優(yōu)化、job的map/reducer個(gè)數(shù)優(yōu)化、并行執(zhí)行優(yōu)化等等,本節(jié)將主要討論HQL中的無時(shí)不在的JOIN的優(yōu)化經(jīng)驗(yàn)。
4.1 Join語句
對(duì)于上述的join語句,其中book_info表數(shù)量為千規(guī)模,
INSERT OVERWRITE TABLE read_log_tmp SELECT a.userid,a.bookid,b.author FROM user_read_log a JOIN book_info b ON a.bookid = b.bookid;該語句的執(zhí)行計(jì)劃為:
圖:map join的任務(wù)執(zhí)行流程
對(duì)于小數(shù)據(jù)量,hive會(huì)自動(dòng)采取map join的方式來優(yōu)化join,從mapreduce的編程模型來看,實(shí)現(xiàn)join的方式主要有map端join、reduce端join。Map端join利用hadoop 分布式緩存技術(shù)通過將小表變換成hashtable文件分發(fā)到各個(gè)task,map大表時(shí)可以直接判斷hashtable來完成join,注意小表的hashtable是放在內(nèi)存中的,在內(nèi)存中作匹配,因此map join是一種非常快的join方式,也是一種常見的優(yōu)化方式。如果小表夠小,那么就可以以map join的方式來完成join完成。Hive通過設(shè)置hive.auto.convert.join=true(默認(rèn)值)來自動(dòng)完成map join的優(yōu)化,而無需顯示指示map join。缺省情況下map join的優(yōu)化是打開的。
Reduce端join需要reducer來完成join過程,對(duì)于上述join代碼,reduce 端join的mr流程如下,
圖:reduce端join的mapreduce過程
相比于map join, reduce 端join無法再map過程中過濾任何記錄,只能將join的兩張表的所有數(shù)據(jù)按照join key進(jìn)行shuffle/sort,并按照join key的hash值將<key,value>對(duì)分發(fā)到特定的reducer。Reducer對(duì)于所有的鍵值對(duì)執(zhí)行join操作,例如0號(hào)(bookid的hash值為0)reducer收到的鍵值對(duì)如下,其中T1、T2表示記錄的來源表,起到標(biāo)識(shí)作用:
圖:reduce端join的reducer join
Reducer端join無法避免的reduce截?cái)嘁约皞鬏數(shù)拇罅繑?shù)據(jù)都會(huì)給集群網(wǎng)絡(luò)帶來壓力,從上圖可以看出所有hash(bookid) % reducer_number等于0的key-value對(duì)都會(huì)通過shuffle被分發(fā)到0號(hào)reducer,如果分到0號(hào)reducer的記錄數(shù)目遠(yuǎn)大于其他reducer的記錄數(shù)目,顯然0號(hào)的reducer的數(shù)據(jù)處理量將會(huì)遠(yuǎn)大于其他reducer,因此處理時(shí)間也會(huì)遠(yuǎn)大于其他reducer,甚至?xí)韮?nèi)存等其他問題,這就是數(shù)據(jù)傾斜問題。對(duì)于join造成的數(shù)據(jù)傾斜問題我們可以通過設(shè)置參數(shù)set Hive.optimize.skewjoin=true,讓hive自己嘗試解決join過程中產(chǎn)生的傾斜問題。
4.2 Group by語句
我們對(duì)user_read_log表按userid goup by語句來繼續(xù)探討數(shù)據(jù)傾斜問題,首先我們explain group by語句:
explain select userid,count(*) from user_read_log group by userid
圖:goup by的執(zhí)行計(jì)劃
Group by的執(zhí)行計(jì)劃按照userid的hash值分發(fā)數(shù)據(jù),同時(shí)在map端也做了本地reduce,group by的shuffle過程是按照hash(userid)來分發(fā)的,實(shí)際應(yīng)用中日志中很多用戶都是未注冊(cè)用戶或者未登錄,userid字段為空的記錄數(shù)遠(yuǎn)大于userid不為空的記錄數(shù),當(dāng)所有的空userid記錄都分發(fā)到特定某一個(gè)reducer后,也會(huì)帶來嚴(yán)重的數(shù)據(jù)傾斜問題。造成數(shù)據(jù)傾斜的主要原因在于分發(fā)到某個(gè)或某幾個(gè)reducer的數(shù)據(jù)量遠(yuǎn)大于其他reducer的數(shù)據(jù)量。
對(duì)于group by造成的數(shù)據(jù)傾斜問題,我們可以通過設(shè)置參數(shù)
set hive.map.aggr=true (開啟map端combiner);
set hive.groupby.skewindata=true;
這個(gè)參數(shù)的作用是做reduce操作的時(shí)候,拿到的key并不是所有相同值給同一個(gè)Reduce,而是隨機(jī)分發(fā),然后reduce做聚合,做完之后再做一輪MR,拿前面聚合過的數(shù)據(jù)再算結(jié)果。雖然多了一輪MR任務(wù),但是可以有效的減少數(shù)據(jù)傾斜問題可能帶來的危險(xiǎn)。
Hive解決數(shù)據(jù)傾斜
正確的設(shè)置Hive參數(shù)可以在某種程度上避免的數(shù)據(jù)傾斜問題,合適的查詢語句也可以避免數(shù)據(jù)傾斜問題。要盡早的過濾數(shù)據(jù)和裁剪數(shù)據(jù),減少后續(xù)處理的數(shù)據(jù)量,使得join key的數(shù)據(jù)分布較為均勻,將空字段隨機(jī)賦予值,這樣既可以均勻分發(fā)傾斜的數(shù)據(jù):
select userid,name from user_info a join (select case when userid is null then cast(rand(47)*100000 as int)else userid from user_read_log ) b on a.userid = b.userid如果用戶在定義schema的時(shí)候就已經(jīng)預(yù)料到表數(shù)據(jù)可能會(huì)存在嚴(yán)重的數(shù)據(jù)傾斜問題,Hive自0.10.0引入了skew table的概念,如建表語句
CREATE TABLE user_read_log (userid int,bookid, …) SKEWED BY (userid) ON (null) [STORED AS DIRECTORIES];需要注意的是,skew table只是將傾斜特別嚴(yán)重的列的分開存儲(chǔ)為不同的文件,每個(gè)制定的傾斜值制定為一個(gè)文件或者目錄,因此在查詢的時(shí)候可以通過過濾傾斜值來避免數(shù)據(jù)傾斜問題:
select userid,name from user_info a join ( select userid from user_read_log where pt=’2015’ and userid is not null ) b on a.userid = b.userid可以看出,如果不加過濾條件,傾斜問題還是會(huì)存在,通過對(duì)skew table加過濾條件的好處是避免了mapper的表掃描過濾操作。
4.3 Join的物理優(yōu)化
Hive內(nèi)部實(shí)現(xiàn)了MapJoinResolver(處理MapJoin)、SkewJoinResolver(處理傾斜join)、CommonJoinResolver(處理普通Join)等類來實(shí)現(xiàn)join的查詢物理優(yōu)化(/org/apache/hadoop/hive/ql/optimizer/physical)。
CommonJoinResolver類負(fù)責(zé)將普通Join轉(zhuǎn)換成MapJoin,Hive通過這個(gè)類來實(shí)現(xiàn)mapjoin的自動(dòng)優(yōu)化。對(duì)于表A和表B的join查詢,會(huì)產(chǎn)生3個(gè)分支:
1) 以表A作為大表進(jìn)行Mapjoin;
2) 以表A作為大表進(jìn)行Mapjoin;
3) Map-reduce join
由于不知道輸入數(shù)據(jù)規(guī)模,因此編譯時(shí)并不會(huì)決定走那個(gè)分支,而是在運(yùn)行時(shí)判斷走那個(gè)分支。需要注意的是要像完成上述自動(dòng)轉(zhuǎn)換,需要將hive.auto.convert.join.noconditionaltask設(shè)置為true(默認(rèn)值),同時(shí)可以手工控制轉(zhuǎn)載進(jìn)內(nèi)存的小表的大小(hive.auto.convert.join.noconditionaltask.size)。
MapJoinResolver 類負(fù)責(zé)迭代各個(gè)mr任務(wù),檢查每個(gè)任務(wù)是否存在map join操作,如果有,會(huì)將local map work轉(zhuǎn)換成local map join work。
SkewJoinResolver類負(fù)責(zé)迭代有join操作的reducer任務(wù),一旦單個(gè)reducer產(chǎn)生了傾斜,那么就會(huì)將傾斜值得數(shù)據(jù)寫入hdfs,然后用一個(gè)新的map join的任務(wù)來處理傾斜值的計(jì)算。雖然多了一輪mr任務(wù),但是由于采用的map join,效率也是很高的。良好的mr模式和執(zhí)行流程總是至關(guān)重要的。
5 總結(jié)
本文詳細(xì)介紹了達(dá)觀大數(shù)據(jù)分析平臺(tái)的基本架構(gòu)和原理,基于hadoop/hive的大數(shù)據(jù)分析平臺(tái)使海量數(shù)據(jù)的存儲(chǔ)、分析、挖掘逐步成為現(xiàn)實(shí),并帶來意想不到的益處。作為數(shù)據(jù)分析平臺(tái)主力軍的Hive仍然處在不斷的發(fā)展之中,將HQL理解成Mapreduce程序、理解Hadoop的核心能力是更好的使用和優(yōu)化Hive的根本。達(dá)觀數(shù)據(jù)團(tuán)隊(duì)也將緊跟技術(shù)發(fā)展潮流,結(jié)合自身的業(yè)務(wù)需求,采取合理的框架架構(gòu),提升數(shù)據(jù)平臺(tái)的處理能力。
6 參考資料
- Hive wiki:https://cwiki.apache.org/confluence/display/Hive/Home
- Hive Design Docs:https://cwiki.apache.org/confluence/display/Hive/DesignDocs
- Hadoop: The Definitive Guide (3rd Edition)
- Programming Hive
- Analytical Queries with Hive:http://www.slideshare.net/Hadoop_Summit/analytical-queries-with-hive
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/9746333.html
總結(jié)
以上是生活随笔為你收集整理的达观数据分析平台架构和Hive实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 兼顾稳定和性能,58大数据平台的技术演进
- 下一篇: 大数据sql引擎