第3章 標(biāo)簽數(shù)據(jù)存儲(chǔ)
在畫像系統(tǒng)搭建的過程中衍慎,數(shù)據(jù)存儲(chǔ)的技術(shù)選型是非常重要的一項(xiàng)內(nèi)容甥角,不同的存儲(chǔ)方式適用于不同的應(yīng)用場景。本章主要介紹使用Hive呼寸、MySQL艳汽、HBase、Elasticsearch存儲(chǔ)畫像相關(guān)數(shù)據(jù)的應(yīng)用場景及對(duì)應(yīng)的解決方案对雪。
3.1 Hive存儲(chǔ)
3.1.1 Hive數(shù)據(jù)倉庫
建立用戶畫像首先需要建立數(shù)據(jù)倉庫河狐,用于存儲(chǔ)用戶標(biāo)簽數(shù)據(jù)。Hive是基于Hadoop的數(shù)據(jù)倉庫工具瑟捣,依賴于HDFS存儲(chǔ)數(shù)據(jù)馋艺,提供的SQL語言可以查詢存儲(chǔ)在HDFS中的數(shù)據(jù)。開發(fā)時(shí)一般使用Hive作為數(shù)據(jù)倉庫迈套,存儲(chǔ)標(biāo)簽和用戶特征庫等相關(guān)數(shù)據(jù)捐祠。
“數(shù)據(jù)倉庫之父”W.H.Inmon在《Building the Data Warehouse》一書中定義數(shù)據(jù)倉庫是“一個(gè)面向主題的、集成的交汤、非易失的雏赦、隨時(shí)間變化的劫笙、用來支持管理人員決策的數(shù)據(jù)集合”芙扎。
數(shù)據(jù)抽取到數(shù)據(jù)倉庫的流程如圖3-1所示。
在數(shù)據(jù)倉庫建模的過程中填大,主要涉及事實(shí)表和維度表的建模開發(fā)(圖3-2)戒洼。
事實(shí)表主要圍繞業(yè)務(wù)過程設(shè)計(jì),就應(yīng)用場景來看主要包括事務(wù)事實(shí)表允华,周期快照事實(shí)表和累計(jì)快照事實(shí)表:
?事務(wù)事實(shí)表:用于描述業(yè)務(wù)過程圈浇,按業(yè)務(wù)過程的單一性或多業(yè)務(wù)過程可進(jìn)一步分為單事務(wù)事實(shí)表和多事務(wù)事實(shí)表。其中單事務(wù)事實(shí)表分別記錄每個(gè)業(yè)務(wù)過程靴寂,如下單業(yè)務(wù)記入下單事實(shí)表磷蜀,支付業(yè)務(wù)記入支付事實(shí)表。多事務(wù)事實(shí)表在同一個(gè)表中包含了不同業(yè)務(wù)過程百炬,如下單褐隆、支付、簽收等業(yè)務(wù)過程記錄在一張表中剖踊,通過新增字段來判斷屬于哪一個(gè)業(yè)務(wù)過程庶弃。當(dāng)不同業(yè)務(wù)過程有著相似性時(shí)可考慮將多業(yè)務(wù)過程放到多事務(wù)事實(shí)表中。
?周期快照事實(shí)表:在一個(gè)確定的時(shí)間間隔內(nèi)對(duì)業(yè)務(wù)狀態(tài)進(jìn)行度量德澈。例如查看一個(gè)用戶的近1年付款金額歇攻、近1年購物次數(shù)、近30日登錄天數(shù)等梆造。
?累計(jì)快照事實(shí)表:用于查看不同事件之間的時(shí)間間隔缴守,例如分析用戶從購買到支付的時(shí)長、從下單到訂單完結(jié)的時(shí)長等。一般適用于有明確時(shí)間周期的業(yè)務(wù)過程斧散。
維度表主要用于對(duì)事實(shí)屬性的各個(gè)方面描述供常,例如,商品維度包括商品的價(jià)格鸡捐、折扣栈暇、品牌、原廠家箍镜、型號(hào)等方面信息源祈。維度表開發(fā)的過程中,經(jīng)常會(huì)遇到維度緩慢變化的情況色迂,對(duì)于緩慢變化維一般會(huì)采用:
①重寫維度值香缺,對(duì)歷史數(shù)據(jù)進(jìn)行覆蓋;
②保留多條記錄歇僧,通過插入維度列字段加以區(qū)分图张;
③開發(fā)日期分區(qū)表,每日分區(qū)數(shù)據(jù)記錄當(dāng)日維度的屬性诈悍;
④開發(fā)拉鏈表按時(shí)間變化進(jìn)行全量存儲(chǔ)等方式進(jìn)行處理祸轮。
在畫像系統(tǒng)中主要使用Hive作為數(shù)據(jù)倉庫,開發(fā)相應(yīng)的維度表和事實(shí)表來存儲(chǔ)標(biāo)簽侥钳、人群适袜、應(yīng)用到服務(wù)層的相關(guān)數(shù)據(jù)。
拉鏈表說明:
拉鏈表 - 維護(hù)歷史狀態(tài)舷夺,以及最新狀態(tài)數(shù)據(jù)的一種表苦酱,拉鏈表根據(jù)拉鏈粒度的不同,實(shí)際上相當(dāng)于快照给猾,只不過做了優(yōu)化疫萤,去除了一部分不變的記錄而已,通過拉鏈表可以很方便的還原出拉鏈時(shí)點(diǎn)的客戶記錄。拉鏈表通常是對(duì)賬戶信息的歷史變動(dòng)進(jìn)行處理保留的結(jié)果敢伸。
3.1.2 分區(qū)存儲(chǔ)
如果將用戶標(biāo)簽開發(fā)成一張大的寬表扯饶,在這張寬表下放幾十種類型標(biāo)簽,那么每天該畫像寬表的ETL作業(yè)將會(huì)花費(fèi)很長時(shí)間详拙,而且不便于向這張寬表中新增標(biāo)簽類型帝际。要解決這種ETL花費(fèi)時(shí)間較長的問題,可以從以下幾個(gè)方面著手:
?將數(shù)據(jù)分區(qū)存儲(chǔ)饶辙,分別執(zhí)行作業(yè)蹲诀;
?標(biāo)簽?zāi)_本性能調(diào)優(yōu);
?基于一些標(biāo)簽共同的數(shù)據(jù)來源開發(fā)中間表弃揽。
下面介紹一種用戶標(biāo)簽分表脯爪、分區(qū)存儲(chǔ)的解決方案则北。根據(jù)標(biāo)簽指標(biāo)體系的人口屬性、行為屬性痕慢、用戶消費(fèi)尚揣、風(fēng)險(xiǎn)控制、社交屬性等維度分別建立對(duì)應(yīng)的標(biāo)簽表進(jìn)行分表存儲(chǔ)對(duì)應(yīng)的標(biāo)簽數(shù)據(jù)掖举。如圖3-3所示快骗。
?人口屬性表:dw.userprofile_attritube_all;
?行為屬性表:dw.userprofile_action_all塔次;
?用戶消費(fèi)表:dw.userprofile_consume_all方篮;
?風(fēng)險(xiǎn)控制表:dw.userprofile_riskmanage_all;
?社交屬性表:dw.userprofile_social_all
例如創(chuàng)建用戶的人口屬性寬表:
同樣的励负,用戶其他id維度(如cookieid藕溅、deviceid、registerid等)的標(biāo)簽數(shù)據(jù)存儲(chǔ)继榆,也可以使用上面案例中的表結(jié)構(gòu)巾表。
在上面的創(chuàng)建中通過設(shè)立人口屬性維度的寬表開發(fā)相關(guān)的用戶標(biāo)簽,為了提高數(shù)據(jù)的插入和查詢效率略吨,在Hive中可以使用分區(qū)表的方式集币,將數(shù)據(jù)存儲(chǔ)在不同的目錄中。在Hive使用select查詢時(shí)一般會(huì)掃描整個(gè)表中所有數(shù)據(jù)晋南,將會(huì)花費(fèi)很多時(shí)間掃描不是當(dāng)前要查詢的數(shù)據(jù)惠猿,為了掃描表中關(guān)心的一部分?jǐn)?shù)據(jù)羔砾,在建表時(shí)引入了partition的概念负间。在查詢時(shí),可以通過Hive的分區(qū)機(jī)制來控制一次遍歷的數(shù)據(jù)量姜凄。
3.1.3 標(biāo)簽匯聚
在3.1.2節(jié)的案例中政溃,用戶的每個(gè)標(biāo)簽都插入到相應(yīng)的分區(qū)下面,但是對(duì)一個(gè)用戶來說态秧,打在他身上的全部標(biāo)簽存儲(chǔ)在不同的分區(qū)下面董虱。為了方便分析和查詢,需要將用戶身上的標(biāo)簽做聚合處理申鱼。緊接3.1.2節(jié)的案例愤诱,下面講解標(biāo)簽匯聚的開發(fā)案例(見圖3-4)。
標(biāo)簽匯聚后將一個(gè)每個(gè)用戶身上的全量標(biāo)簽匯聚到一個(gè)字段中捐友,表結(jié)構(gòu)設(shè)計(jì)如下:
開發(fā)udf函數(shù)“cast_to_json”將用戶身上的標(biāo)簽匯聚成json字符串淫半,執(zhí)行命令將按分區(qū)存儲(chǔ)的標(biāo)簽進(jìn)行匯聚:
匯聚后用戶標(biāo)簽的存儲(chǔ)格式如圖3-5所示
將用戶身上的標(biāo)簽進(jìn)行聚合便于查詢和計(jì)算。例如匣砖,在畫像產(chǎn)品中科吭,輸入用戶id后通過直接查詢?cè)摫砘璧危馕鰳?biāo)簽id和對(duì)應(yīng)的標(biāo)簽權(quán)重后,即可在前端展示該用戶的相關(guān)信息(如圖3-6所示)对人。
3.1.4 ID-MAP
開發(fā)用戶標(biāo)簽的時(shí)候谣殊,有項(xiàng)非常重要的內(nèi)容——ID-MApping,即把用戶不同來源的身份標(biāo)識(shí)通過數(shù)據(jù)手段識(shí)別為同一個(gè)主體牺弄。用戶的屬性姻几、行為相關(guān)數(shù)據(jù)分散在不同的數(shù)據(jù)來源中,通過ID-MApping能夠把用戶在不同場景下的行為串聯(lián)起來势告,消除數(shù)據(jù)孤島鲜棠。圖3-7展示了用戶與設(shè)備間的多對(duì)多關(guān)系。圖3-8展示了同一用戶在不同平臺(tái)間的行為示意圖培慌。
舉例來說豁陆,用戶在未登錄App的狀態(tài)下,在App站內(nèi)訪問吵护、搜索相關(guān)內(nèi)容時(shí)盒音,記錄的是設(shè)備id(即cookieid)相關(guān)的行為數(shù)據(jù)。而用戶在登錄App后馅而,訪問祥诽、收藏、下單等相關(guān)的行為記錄的是賬號(hào)id(即userid)相關(guān)行為數(shù)據(jù)瓮恭。雖然是同一個(gè)用戶雄坪,但其在登錄和未登錄設(shè)備時(shí)記錄的行為數(shù)據(jù)之間是未打通的。通過ID-MApping打通userid和cookieid的對(duì)應(yīng)關(guān)系屯蹦,可以在用戶登錄维哈、未登錄設(shè)備時(shí)都能捕獲其行為軌跡。
下面通過一個(gè)案例介紹如何通過Hive的ETL工作完成ID-Mapping的數(shù)據(jù)清洗工作登澜。
緩慢變化維是在維表設(shè)計(jì)中常見的一種方式阔挠,維度并不是不變的,隨時(shí)間也會(huì)發(fā)生緩慢變化脑蠕。如用戶的手機(jī)號(hào)购撼、郵箱等信息可能會(huì)隨用戶的狀態(tài)變化而改變,再如商品的價(jià)格也會(huì)隨時(shí)間變化而調(diào)整上架的價(jià)格谴仙。因此在設(shè)計(jì)用戶迂求、商品等維表時(shí)會(huì)考慮用緩慢變化維來開發(fā)。同樣晃跺,在設(shè)計(jì)ID-Mapping表時(shí)揩局,由于一個(gè)用戶可以在多個(gè)設(shè)備上登錄,一個(gè)設(shè)備也能被多個(gè)用戶登錄哼审,所以考慮用緩慢變化維表來記錄這種不同時(shí)間點(diǎn)的狀態(tài)變化(圖3-9)谐腰。
拉鏈表是針對(duì)緩慢變化維表的一種設(shè)計(jì)方式孕豹,記錄一個(gè)事物從開始到當(dāng)前狀態(tài)的全部狀態(tài)變化信息。
在上圖中十气,通過拉鏈表記錄了userid每一次關(guān)聯(lián)到不同cookieid的情況励背。如userid為44463729的用戶,在20190101這天登錄某設(shè)備砸西,在6號(hào)那天變換了另一個(gè)設(shè)備登錄叶眉。其中start_date表示該記錄的開始日期,end_date表示該記錄的結(jié)束日期芹枷,當(dāng)end_date為99991231時(shí)衅疙,表示該條記錄當(dāng)前仍然有效。
首先需要從埋點(diǎn)表和訪問日志表里面獲取到cookieid和userid同時(shí)出現(xiàn)的訪問記錄鸳慈。下面案例中饱溢,ods.page_event_log是埋點(diǎn)日志表,ods.page_view_log是訪問日志表走芋,將獲取到的userid和cookieid信息插入cookieid-userid關(guān)系表(ods.cookie_user_signin)中绩郎。代碼執(zhí)行如下:
創(chuàng)建ID-Map的拉鏈表,將每天新增到ods.cookie_user_signin表中的數(shù)據(jù)與拉鏈表歷史數(shù)據(jù)做比較翁逞,如果有變化或新增數(shù)據(jù)則進(jìn)行更新肋杖。
數(shù)據(jù)寫入表中,如圖3-9所示挖函。對(duì)于該拉鏈表状植,可查看某日(如20190801)的快照數(shù)據(jù)。
例如怨喘,目前存在一個(gè)記錄userid和cookieid關(guān)聯(lián)關(guān)系的表津畸,但是為多對(duì)多的記錄(即一個(gè)userid對(duì)應(yīng)多條cookieid記錄,以及一條cookieid對(duì)應(yīng)多條userid記錄)哲思。這里可以通過拉鏈表的日期來查看某個(gè)時(shí)間點(diǎn)userid對(duì)應(yīng)的cookieid洼畅。查看某個(gè)用戶(如32101029)在某天(如20190801)關(guān)聯(lián)到的設(shè)備id(圖3-10)吩案。
上圖可看出用戶‘32101029’在歷史中曾登錄過3個(gè)設(shè)備棚赔,通過限定時(shí)間段可找到特定時(shí)間下用戶的登錄設(shè)備。
在開發(fā)中需要注意關(guān)于userid與cookieid的多對(duì)多關(guān)聯(lián)徘郭,如果不加條件限制就做關(guān)聯(lián)靠益,很可能引起數(shù)據(jù)膨脹問題。
在實(shí)際應(yīng)用中残揉,會(huì)遇到許多需要將userid和cookieid做關(guān)聯(lián)的情況胧后。例如,需要在userid維度開發(fā)出該用戶近30日的購買次數(shù)抱环、購買金額壳快、登錄時(shí)長纸巷、登錄天數(shù)等標(biāo)簽。前兩個(gè)標(biāo)簽可以很容易地從相應(yīng)的業(yè)務(wù)數(shù)據(jù)表中根據(jù)算法加工出來眶痰,而登錄時(shí)長瘤旨、登錄天數(shù)的數(shù)據(jù)存儲(chǔ)在相關(guān)日志數(shù)據(jù)中,日志數(shù)據(jù)表記錄的userid與cookieid為多對(duì)多關(guān)系竖伯。因此在結(jié)合業(yè)務(wù)需求開發(fā)標(biāo)簽時(shí)存哲,要確定好標(biāo)簽口徑定義。
本節(jié)中通過案例介紹了將userid和cookieid打通的一種解決方案七婴,實(shí)踐中還存在需要將用戶在不同平臺(tái)間(如Web端和App端)行為打通的應(yīng)用場景祟偷。
3.2 MySQL存儲(chǔ)
MySQL作為關(guān)系型數(shù)據(jù)庫打厘,在用戶畫像中可用于元數(shù)據(jù)管理户盯、監(jiān)控預(yù)警數(shù)據(jù)氛赐、結(jié)果集存儲(chǔ)等應(yīng)用中。下面詳細(xì)介紹這3個(gè)應(yīng)用場景先舷。
3.2.1 元數(shù)據(jù)管理
Hive適合于大數(shù)據(jù)量的批處理作業(yè)艰管,對(duì)于量級(jí)較小的數(shù)據(jù),MySQL具有更快的讀寫速度蒋川。Web端產(chǎn)品讀寫MySQL數(shù)據(jù)庫會(huì)有更快的速度,方便標(biāo)簽的定義捺球、管理氮兵。在7.2節(jié)和7.3節(jié)中,我們會(huì)介紹元數(shù)據(jù)錄入和查詢功能泣栈,將相應(yīng)的數(shù)據(jù)存儲(chǔ)在MySQL中卜高。用戶標(biāo)簽的元數(shù)據(jù)表結(jié)構(gòu)設(shè)計(jì)會(huì)在7.3節(jié)進(jìn)行詳細(xì)的介紹。這里給出了平臺(tái)標(biāo)簽視圖(如圖3-11所示)和元數(shù)據(jù)管理頁面(如圖3-12所示)南片。
平臺(tái)標(biāo)簽視圖中的標(biāo)簽元數(shù)據(jù)可以維護(hù)在MySQL關(guān)系數(shù)據(jù)庫中,便于標(biāo)簽的編輯、查詢和管理濒析。
3.2.2 監(jiān)控預(yù)警數(shù)據(jù)
MySQL還可用于存儲(chǔ)每天對(duì)ETL結(jié)果的監(jiān)控信息。從整個(gè)畫像調(diào)度流的關(guān)鍵節(jié)點(diǎn)來看护赊,需要監(jiān)控的環(huán)節(jié)主要包括對(duì)每天標(biāo)簽的產(chǎn)出量、服務(wù)層數(shù)據(jù)同步情況的監(jiān)控等主要場景砾跃。圖3-13所示是用戶畫像調(diào)度流主要模塊骏啰,下面詳細(xì)介紹。
1.標(biāo)簽計(jì)算數(shù)據(jù)監(jiān)控
主要用于監(jiān)控每天標(biāo)簽ETL的數(shù)據(jù)量是否出現(xiàn)異常抽高,如果有異常情況則發(fā)出告警郵件判耕,同時(shí)暫停后面的ETL任務(wù)。
2.服務(wù)層同步數(shù)據(jù)監(jiān)控
服務(wù)層一般采用HBase翘骂、Elasticsearch等作為數(shù)據(jù)庫存儲(chǔ)標(biāo)簽數(shù)據(jù)供線上調(diào)用壁熄,將標(biāo)簽相關(guān)數(shù)據(jù)從Hive數(shù)倉向服務(wù)層同步的過程中,有出現(xiàn)差錯(cuò)的可能雏胃,因此需要記錄相關(guān)數(shù)據(jù)在Hive中的數(shù)量及同步到對(duì)應(yīng)服務(wù)層后的數(shù)量请毛,如果數(shù)量不一致則觸發(fā)告警。
在對(duì)畫像的數(shù)據(jù)監(jiān)控中瞭亮,調(diào)度流每跑完相應(yīng)的模塊,就將該模塊的監(jiān)控?cái)?shù)據(jù)插入MySQL中固棚,當(dāng)校驗(yàn)任務(wù)判斷達(dá)到觸發(fā)告警閾值時(shí)统翩,發(fā)送告警郵件仙蚜,同時(shí)中斷后續(xù)的調(diào)度任務(wù)。待開發(fā)人員解決問題后厂汗,可重啟后續(xù)調(diào)度委粉。
3.2.3 結(jié)果集存儲(chǔ)
結(jié)果集可以用來存儲(chǔ)多維透視分析用的標(biāo)簽、圈人服務(wù)用的用戶標(biāo)簽娶桦、當(dāng)日記錄各標(biāo)簽數(shù)量贾节,用于校驗(yàn)標(biāo)簽數(shù)據(jù)是否出現(xiàn)異常。
有的線上業(yè)務(wù)系統(tǒng)使用MySQL衷畦、Oracle等關(guān)系型數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)栗涂,如短信系統(tǒng)、消息推送系統(tǒng)等祈争。在打通畫像數(shù)據(jù)與線上業(yè)務(wù)系統(tǒng)時(shí)斤程,需要考慮將存儲(chǔ)在Hive中的用戶標(biāo)簽相關(guān)數(shù)據(jù)同步到各業(yè)務(wù)系統(tǒng),此時(shí)MySQL可用于存儲(chǔ)結(jié)果集菩混。
Sqoop是一個(gè)用來將Hadoop和關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)相互遷移的工具忿墅。它可以將一個(gè)關(guān)系型數(shù)據(jù)庫(如MySQL、Oracle沮峡、PostgreSQL等)中的數(shù)據(jù)導(dǎo)入Hadoop的HDFS中疚脐,也可以將HDFS中的數(shù)據(jù)導(dǎo)入關(guān)系型數(shù)據(jù)庫中。
下面通過一個(gè)案例來講解如何使用Sqoop將Hive中的標(biāo)簽數(shù)據(jù)遷移到MySQL中邢疙。
電商亮曹、保險(xiǎn)、金融等公司的客服部門的日常工作內(nèi)容之一是對(duì)目標(biāo)用戶群(如已流失用戶秘症、高價(jià)值用戶等)進(jìn)行主動(dòng)外呼照卦,以此召回用戶來平臺(tái)進(jìn)行購買或復(fù)購。這里可以借助用戶畫像系統(tǒng)實(shí)現(xiàn)該功能乡摹。
將Hive中存儲(chǔ)的與用戶身份相關(guān)的數(shù)據(jù)同步到客服系統(tǒng)中役耕,首先在Hive中建立一張記錄用戶身份相關(guān)信息的表(dw.userprofile_userservice_all)。設(shè)置日期分區(qū)以滿足按日期選取當(dāng)前人群的需要聪廉。
在MySQL中建立一張用于接收同步數(shù)據(jù)的表(userservice_data)瞬痘。
通過Python腳本調(diào)用shell命令,將Hive中的數(shù)據(jù)同步到MySQL中板熊。執(zhí)行如下腳本:
其中用到了sqoop從Hive導(dǎo)出數(shù)據(jù)到MySQL的命令:
同步后MySQL中的數(shù)據(jù)如圖3-14所示框全。
3.3 HBase存儲(chǔ)
3.3.1 HBase簡介
HBase是一個(gè)高性能、列存儲(chǔ)干签、可伸縮津辩、實(shí)時(shí)讀寫的分布式存儲(chǔ)系統(tǒng),同樣運(yùn)行在HDFS之上。與Hive不同的是喘沿,HBase能夠在數(shù)據(jù)庫上實(shí)時(shí)運(yùn)行闸度,而不是跑MapReduce任務(wù),適合進(jìn)行大數(shù)據(jù)的實(shí)時(shí)查詢蚜印。
畫像系統(tǒng)中每天在Hive里跑出的結(jié)果集數(shù)據(jù)可同步到HBase數(shù)據(jù)庫莺禁,用于線上實(shí)時(shí)應(yīng)用的場景。下面介紹幾個(gè)基本概念:
?row key:用來表示唯一一行記錄的主鍵窄赋,HBase的數(shù)據(jù)是按照row key的字典順序進(jìn)行全局排列的哟冬。
訪問HBase中的行只有3種方式:
○通過單個(gè)row key訪問;
○通過row key的正則訪問忆绰;
○全表掃描浩峡。
由于HBase通過rowkey對(duì)數(shù)據(jù)進(jìn)行檢索,而rowkey由于長度限制的因素不能將很多查詢條件拼接在rowkey中较木,因此HBase無法像關(guān)系數(shù)據(jù)庫那樣根據(jù)多種條件對(duì)數(shù)據(jù)進(jìn)行篩選红符。一般地,HBase需建立二級(jí)索引來滿足根據(jù)復(fù)雜條件查詢數(shù)據(jù)的需求伐债。
Rowkey設(shè)計(jì)時(shí)需要遵循三大原則:
○唯一性原則:rowkey需要保證唯一性预侯,不存在重復(fù)的情況。在畫像中一般使用用戶id作為rowkey峰锁。
○長度原則:rowkey的長度一般為10-100bytes萎馅。
○散列原則:rowkey的散列分布有利于數(shù)據(jù)均衡分布在每個(gè)RegionServer,可實(shí)現(xiàn)負(fù)載均衡虹蒋。
?columns family:指列簇糜芳,HBase中的每個(gè)列都?xì)w屬于某個(gè)列簇。列簇是表的schema的一部分魄衅,必須在使用表之前定義峭竣。劃分columns family的原則如下:
○是否具有相似的數(shù)據(jù)格式;
○是否具有相似的訪問類型晃虫。
常用的增刪改查命令如下皆撩。
1)創(chuàng)建一個(gè)表,指定表名和列簇名:[插圖]
create '<table name>','<column family>'
2)掃描表中數(shù)據(jù)哲银,并顯示其中的10條記錄:[插圖]
scan 'table name',{LIMIT =>10}
3)使用get命令讀取數(shù)據(jù):[插圖]
get '<table name>','row1'
4)插入數(shù)據(jù):[插圖]
put '<table name>','row ','colfamily:colname','<value>'
5)更新數(shù)據(jù):[插圖]
put '<table name>','row','Column family:column name','new value'
6)在刪除表之前先將其禁用扛吞,然后刪除:[插圖]
disable '<table name>'
drop '<table name>'
下面通過一個(gè)案例來介紹HBase在畫像系統(tǒng)中的應(yīng)用場景和工程化實(shí)現(xiàn)方式。
3.3.2 應(yīng)用場景
某渠道運(yùn)營人員為促進(jìn)未注冊(cè)的新安裝用戶注冊(cè)荆责、下單滥比,計(jì)劃通過App首頁彈窗(如圖3-15所示)發(fā)放紅包或優(yōu)惠券的方式進(jìn)行引導(dǎo)。在該場景中可通過畫像系統(tǒng)實(shí)現(xiàn)對(duì)應(yīng)功能做院。
業(yè)務(wù)邏輯上盲泛,渠道運(yùn)營人員通過組合用戶標(biāo)簽(如“未注冊(cè)用戶”和“安裝距今天數(shù)”小于××天)篩選出對(duì)應(yīng)的用戶群濒持,然后選擇將對(duì)應(yīng)人群推送到“廣告系統(tǒng)”(產(chǎn)品功能詳見7.4節(jié)),這樣每天畫像系統(tǒng)的ETL調(diào)度完成后對(duì)應(yīng)人群數(shù)據(jù)就被推送到HBase數(shù)據(jù)庫進(jìn)行存儲(chǔ)查乒。滿足條件的新用戶來訪App時(shí)弥喉,由在線接口讀取HBase數(shù)據(jù)庫郁竟,在查詢到該用戶時(shí)為其推送該彈窗玛迄。
下面通過某工程案例來講解HBase在該觸達(dá)用戶場景中的應(yīng)用方式。
3.3.3 工程化案例
運(yùn)營人員在畫像系統(tǒng)(詳見第7章)中根據(jù)業(yè)務(wù)規(guī)則定義組合用戶標(biāo)簽篩選出用戶群棚亩,并將該人群上線到廣告系統(tǒng)中(如圖3-16所示)蓖议。
在業(yè)務(wù)人員配置好規(guī)則后,下面我們來看在數(shù)據(jù)調(diào)度層面是如何運(yùn)行的讥蟆。
用戶標(biāo)簽數(shù)據(jù)經(jīng)過ETL將每個(gè)用戶身上的標(biāo)簽聚合后插入到目標(biāo)表中勒虾,如dw.userprofile_userlabel_map_all(詳見3.1.3節(jié))。聚合后數(shù)據(jù)存儲(chǔ)為每個(gè)用戶id瘸彤,以及他身上對(duì)應(yīng)的標(biāo)簽集合修然,數(shù)據(jù)格式如圖3-17所示。
接下來需要將Hive中的數(shù)據(jù)導(dǎo)入HBase质况,便于線上接口實(shí)時(shí)調(diào)用庫中數(shù)據(jù)愕宋。
HBase的服務(wù)器體系結(jié)構(gòu)遵循主從服務(wù)器架構(gòu)(如圖3-18所示),同一時(shí)刻只有一個(gè)HMaster處于活躍狀態(tài)结榄,當(dāng)活躍的Master掛掉后中贝,Backup HMaster自動(dòng)接管整個(gè)HBase集群。在同步數(shù)據(jù)前臼朗,首先需要判斷HBase的當(dāng)前活躍節(jié)點(diǎn)是哪臺(tái)機(jī)器邻寿。
執(zhí)行如下腳本:
執(zhí)行完畢后,可通過返回的“State”字段判斷當(dāng)前節(jié)點(diǎn)狀態(tài)(活躍為“active”视哑,不活躍為“standby”)绣否,如圖3-19所示。
為避免數(shù)據(jù)都寫入一個(gè)region挡毅,造成HBase的數(shù)據(jù)傾斜問題蒜撮。在當(dāng)前HMaster活躍的節(jié)點(diǎn)上,創(chuàng)建預(yù)分區(qū)表:
將待同步的數(shù)據(jù)寫入HFile慷嗜,HFile中的數(shù)據(jù)以key-value鍵值對(duì)方式存儲(chǔ)淀弹,然后將HFile數(shù)據(jù)使用BulkLoad批量寫入HBase集群中。Scala腳本執(zhí)行如下:
......
提交Spark任務(wù)庆械,將HFile中數(shù)據(jù)bulkload到HBase中薇溃。執(zhí)行完成后,可以在HBase中看到該數(shù)據(jù)已經(jīng)寫入“userprofile_labels”中(圖3-20)缭乘。
在線接口在查詢HBase中數(shù)據(jù)時(shí)沐序,由于HBase無法像關(guān)系數(shù)據(jù)庫那樣根據(jù)多種條件對(duì)數(shù)據(jù)進(jìn)行篩選(類似SQL語言中的where篩選條件)。一般地HBase需建立二級(jí)索引來滿足根據(jù)復(fù)雜條件查詢數(shù)據(jù)的需求,本案中選用Elasticsearch存儲(chǔ)HBase索引數(shù)據(jù)(圖3-21)策幼。
在組合標(biāo)簽查詢對(duì)應(yīng)的用戶人群場景中邑时,首先通過組合標(biāo)簽的條件在Elasticsearch中查詢對(duì)應(yīng)的索引數(shù)據(jù),然后通過索引數(shù)據(jù)去HBase中批量獲取rowkey對(duì)應(yīng)的數(shù)據(jù)(Elasticsearch中的documentid和HBase中的rowkey都設(shè)計(jì)為用戶id)特姐。
為了避免從Hive向HBase灌入數(shù)據(jù)時(shí)缺失晶丘,在向HBase數(shù)據(jù)同步完成后,還需要校驗(yàn)HBase和Hive中數(shù)據(jù)量是否一致唐含,如出現(xiàn)較大的波動(dòng)則發(fā)送告警信息浅浮。下面通過Python腳本來看該HBase狀態(tài)表數(shù)據(jù)校驗(yàn)邏輯:
本案例中將userid作為rowkey存入HBase,一方面在組合標(biāo)簽的場景中可以支持條件查詢多用戶人群捷枯,另一方面可以支持單個(gè)用戶標(biāo)簽的查詢滚秩,例如查看某id用戶身上的標(biāo)簽,以便運(yùn)營人員決定是否對(duì)其進(jìn)行運(yùn)營操作淮捆。HBase在離線數(shù)倉環(huán)境的服務(wù)架構(gòu)如圖3-22所示郁油。
3.4 Elasticsearch存儲(chǔ)
3.4.1 Elasticsearch簡介
Elasticsearch是一個(gè)開源的分布式全文檢索引擎,可以近乎實(shí)時(shí)地存儲(chǔ)攀痊、檢索數(shù)據(jù)桐腌。而且可擴(kuò)展性很好,可以擴(kuò)展到上百臺(tái)服務(wù)器蚕苇,處理PB級(jí)別的數(shù)據(jù)哩掺。對(duì)于用戶標(biāo)簽查詢、用戶人群計(jì)算涩笤、用戶群多維透視分析這類對(duì)響應(yīng)時(shí)間要求較高的場景嚼吞,也可以考慮選用Elasticsearch進(jìn)行存儲(chǔ)。
Elasticsearch是面向文檔型數(shù)據(jù)庫蹬碧,一條數(shù)據(jù)在這里就是一個(gè)文檔舱禽,用json作為文檔格式。為了更清晰地理解Elasticsearch查詢的一些概念恩沽,將其和關(guān)系數(shù)據(jù)庫的類型進(jìn)行對(duì)照誊稚,如圖3-23所示。
在關(guān)系型數(shù)據(jù)庫中查詢數(shù)據(jù)時(shí)可通過選中數(shù)據(jù)庫罗心、表视事、行任岸、列來定位所查找的內(nèi)容乘客,在Elasticsearch中通過索引(index)含潘、類型(type)、文檔(document)飒箭、字段來定位查找內(nèi)容狼电。一個(gè)Elasticsearch集群可以包括多個(gè)索引(數(shù)據(jù)庫)蜒灰,也就是說,其中包含了很多類型(表)肩碟,這些類型中包含了很多的文檔(行)强窖,然后每個(gè)文檔中又包含了很多的字段(列)。Elasticsearch的交互可以使用Java API削祈,也可以使用HTTP的RESTful API方式翅溺。
3.4.2 應(yīng)用場景
基于HBase的存儲(chǔ)方案并沒有解決數(shù)據(jù)的高效檢索問題。在實(shí)際應(yīng)用中岩瘦,經(jīng)常有根據(jù)特定的幾個(gè)字段進(jìn)行組合后檢索的應(yīng)用場景未巫,而HBase采用rowkey作為一級(jí)索引窿撬,不支持多條件查詢启昧,如果要對(duì)庫里的非rowkey進(jìn)行數(shù)據(jù)檢索和查詢,往往需要通過MapReduce等分布式框架進(jìn)行計(jì)算劈伴,時(shí)間延遲上會(huì)比較高密末,難以同時(shí)滿足用戶對(duì)于復(fù)雜條件查詢和高效率響應(yīng)這兩方面的需求。
為了既能支持對(duì)數(shù)據(jù)的高效查詢跛璧,同時(shí)也能支持通過條件篩選進(jìn)行復(fù)雜查詢严里,需要在HBase上構(gòu)建二級(jí)索引,以滿足對(duì)應(yīng)的需要追城。在本案中我們采用Elasticsearch存儲(chǔ)HBase的索引信息刹碾,以支持復(fù)雜高效的查詢功能。
主要查詢過程包括:
1)在Elasticsearch中存放用于檢索條件的數(shù)據(jù)座柱,并將rowkey也存儲(chǔ)進(jìn)去迷帜;
2)使用Elasticsearch的API根據(jù)組合標(biāo)簽的條件查詢出rowkey的集合;
3)使用上一步得到的rowkey去HBase數(shù)據(jù)庫查詢對(duì)應(yīng)的結(jié)果(見圖3-24)色洞。
HBase數(shù)據(jù)存儲(chǔ)數(shù)據(jù)的索引放在Elasticsearch中戏锹,實(shí)現(xiàn)了數(shù)據(jù)和索引的分離。在Elasticsearch中documentid是文檔的唯一標(biāo)識(shí)火诸,在HBase中rowkey是記錄的唯一標(biāo)識(shí)锦针。在工程實(shí)踐中,兩者可同時(shí)選用用戶在平臺(tái)上的唯一標(biāo)識(shí)(如userid或deviceid)作為rowkey或documentid置蜀,進(jìn)而解決HBase和Elasticsearch索引關(guān)聯(lián)的問題奈搜。
下面通過使用Elasticsearch解決用戶人群計(jì)算和分析應(yīng)用場景的案例來了解這一過程。
對(duì)匯聚后的用戶標(biāo)簽表dw.userprofile_userlabel_map_all(3.1.3節(jié))中的數(shù)據(jù)進(jìn)行清洗盯荤,過濾掉一些無效字符馋吗,達(dá)到導(dǎo)入Elasticsearch的條件,如圖3-25所示廷雅。
然后將dw.userprofile_userlabel_map_all數(shù)據(jù)寫入Elasticsearch中耗美,Scala代碼如下:
.......
工程依賴如下:
將該工程打包之后提交任務(wù)京髓,傳入日期分區(qū)參數(shù)“20190101”執(zhí)行。提交命令“spark-submit--class com.example.HiveDataToEs--master yarn--deploy-mode client--executor-memory 2g--num-executors 50--driver-memory 3g--executor-cores 2 spark-hive-to-es.jar 20190101”商架。任務(wù)執(zhí)行完畢后堰怨,當(dāng)日userid維度的用戶標(biāo)簽數(shù)據(jù)全部導(dǎo)入Elasticsearch中。使用RESTfulAPI查詢包含某個(gè)標(biāo)簽的用戶量蛇摸,可實(shí)時(shí)得到返回結(jié)果备图,如圖3-26所示。
赶袄。揽涮。。
3.5 本章小結(jié)
本章講解了使用Hive饿肺、MySQL蒋困、HBase和Elasticsearch存儲(chǔ)標(biāo)簽數(shù)據(jù)的解決方案,包括:Hive存儲(chǔ)數(shù)據(jù)相關(guān)標(biāo)簽表敬辣、人群計(jì)算表的表結(jié)構(gòu)設(shè)計(jì)以及ID-Mapping的一種實(shí)現(xiàn)方式雪标;MySQL存儲(chǔ)標(biāo)簽元數(shù)據(jù)、監(jiān)控?cái)?shù)據(jù)及結(jié)果集數(shù)據(jù)溉跃;HBase存儲(chǔ)線上接口實(shí)時(shí)調(diào)用的數(shù)據(jù)村刨;Elasticsearch存儲(chǔ)標(biāo)簽用于人群計(jì)算和人群多維透視分析。存儲(chǔ)過程中涉及如下相關(guān)表撰茎。
?dw.userprofile_attritube_all:存儲(chǔ)人口屬性維度的標(biāo)簽表嵌牺;
?dw.userprofile_action_all:存儲(chǔ)行為屬性維度的標(biāo)簽表;
?dw.userprofile_consume_all:存儲(chǔ)用戶消費(fèi)維度的標(biāo)簽表龄糊;
?dw.userprofile_riskmanage_all:存儲(chǔ)風(fēng)險(xiǎn)控制維度的標(biāo)簽表逆粹;
?dw.userprofile_social_all:存儲(chǔ)社交屬性維度的標(biāo)簽表;
?dw.userprofile_userlabel_map_all:匯聚用戶各維度標(biāo)簽的表绎签;
?dw.userprofile_usergroup_labels_all:存儲(chǔ)計(jì)算后人群數(shù)據(jù)的表枯饿。
面向不同的工程場景使用不同的存儲(chǔ)方案,本章通過“工程場景+案例”的形式介紹了一種可實(shí)現(xiàn)的用戶標(biāo)簽存儲(chǔ)解決方案诡必。
本文為讀書筆記奢方,更多精彩內(nèi)容請(qǐng)自行購買書籍。