李晋面试总结
集群規(guī)模
- 團(tuán)隊(duì)規(guī)模 5個(gè)人 OLAP 1 數(shù)據(jù)采集1 報(bào)表 2 組長(zhǎng)
- 數(shù)據(jù)量 3 千萬(wàn)條 實(shí)時(shí) 5-6 百萬(wàn)條
- 12核 24 線(xiàn)程 內(nèi)存 64 G 硬盤(pán) 8 T * 8 個(gè)
- kafka 3臺(tái) 副本兩個(gè) mysql 4臺(tái) hdfs + yarn
- CDH 6.2
- hadoop 3.0.3
- hive 2.1
- spark 2.4
- linux版本CentOS-7 就是linux7
集群安裝步驟 : 免密 ip映射 集群同步
公司概況
自我介紹!!!
面試官您好 我叫李晉 畢業(yè)后一直從事大數(shù)據(jù)開(kāi)發(fā)這一行業(yè),離線(xiàn)數(shù)據(jù)分析和實(shí)時(shí)數(shù)據(jù)分析之前都有做過(guò),包括數(shù)倉(cāng)的搭建也都有參與過(guò),之前工作離線(xiàn)主要是基于hive和spark來(lái)進(jìn)行開(kāi)發(fā),實(shí)時(shí)使用的是flink進(jìn)行的開(kāi)發(fā),另外平常的話(huà)喜歡逛逛博客呀,學(xué)習(xí)學(xué)習(xí)新技術(shù),自己呢也會(huì)寫(xiě)一點(diǎn)總結(jié)什么的以上就是我的一點(diǎn)個(gè)人介紹項(xiàng)目背景
根據(jù)大數(shù)據(jù)分析 實(shí)現(xiàn)精準(zhǔn)的廣告投放 以便提高公司業(yè)務(wù)量 同時(shí)的話(huà)可以根據(jù)用戶(hù)的消費(fèi)水平 消費(fèi)行為 推薦給用戶(hù)對(duì)應(yīng)的商品
基礎(chǔ)流量指標(biāo)分析 (流量會(huì)話(huà)聚合表) (指標(biāo)有 日/周/月 pv uv 總訪問(wèn)時(shí)長(zhǎng)等)
- 比如統(tǒng)計(jì)日活 月活這些指標(biāo) 我們可以清晰的看出我們的產(chǎn)品目前的狀態(tài) 根據(jù)日活月活分析判斷我們的產(chǎn)品是否需要更進(jìn)一步的推廣
- 假如當(dāng)前日活月活穩(wěn)定在一個(gè)正常值,但是增長(zhǎng)緩慢,可以嘗試進(jìn)一步推廣,擴(kuò)大用戶(hù)規(guī)模
歸因事件分析
首次歸因 進(jìn)行分析 同一個(gè)用戶(hù)購(gòu)買(mǎi)一件商品歸因分析 先按時(shí)間將待歸因事件進(jìn)行過(guò)濾 然后在取出第一個(gè)事件 得到的就是首次歸因 和業(yè)務(wù)人員以及前端人員一起商量
比如提交訂單這個(gè)事件
- 他可能有多種行為導(dǎo)致他提交訂單的操作
- 包括自己搜索呀, 點(diǎn)擊某個(gè)廣告位 某個(gè)運(yùn)營(yíng)位 點(diǎn)擊他人分享等 我們一般會(huì)和運(yùn)營(yíng)人員進(jìn)行商討 選擇合適的歸因模型
- 比如選擇首次歸因 判斷用戶(hù)每次提交訂單的行為是從那個(gè)行為上最先感興趣的的
- 如果大部分都是某個(gè)廣告位點(diǎn)擊進(jìn)行的 那我們就提高此廣告位的曝光率 以便提高訂單的轉(zhuǎn)換率
離線(xiàn)數(shù)據(jù)系統(tǒng)的整體架構(gòu)
數(shù)倉(cāng)分為 行為域 業(yè)務(wù)域
主要負(fù)責(zé)行為域域
項(xiàng)目是一個(gè)純離線(xiàn)的項(xiàng)目 , 整體上分三層 , 數(shù)據(jù)采集層 , 數(shù)據(jù)計(jì)算層 , 數(shù)據(jù)服務(wù)層
數(shù)據(jù)整體框架流向
離線(xiàn)
- 日志數(shù)據(jù) 使用 flume 采集至 hdfs 中(采集到的都是 json 格式的數(shù)據(jù)) flume 構(gòu)建攔截器將臟數(shù)據(jù)直接過(guò)濾
- 基于hive搭建的一個(gè)離線(xiàn)的數(shù)倉(cāng) hive中分了四層 ods dwd dws ads
- 將hdfs中的數(shù)據(jù) 直接load到hive的 ods 也是就貼源層
- 經(jīng)過(guò)一系列的數(shù)據(jù)清洗轉(zhuǎn)換集成等操作形成一張大寬表放置到 dwd 層
- 將數(shù)據(jù)分主題進(jìn)行計(jì)算各類(lèi)成品表 因?yàn)橛幸恍┑某善繁砜赡芎芏鄶?shù)據(jù)都可以由一張中間表得出 我們就制作了中間表放置在dws層
- 最后ads層就是我們的成品報(bào)表
- 成品報(bào)表我們一般會(huì)導(dǎo)入至hbase中以供后續(xù)提供給運(yùn)營(yíng)部進(jìn)行分析什么的 這也就是olap那塊了
- 其他的比如多維統(tǒng)計(jì)我們一開(kāi)始使用的是hive的高階聚合函數(shù) 后來(lái)的話(huà)使用的是kylin
- 一些臨時(shí)性的指標(biāo)查詢(xún)我們使用的是 presto 基于內(nèi)存計(jì)算 對(duì)接多種數(shù)據(jù)源
- 第二個(gè)項(xiàng)目是對(duì)第一個(gè)項(xiàng)目進(jìn)行了一些改進(jìn)和擴(kuò)展 改進(jìn)主要是ods - dwd 數(shù)據(jù)處理那塊
- 匿名數(shù)據(jù)的標(biāo)識(shí)我們之前采用的是直接使用設(shè)備ID作為匿名數(shù)據(jù)的標(biāo)識(shí)
- 改進(jìn)后使用動(dòng)態(tài)綁定的方式 做了一張?jiān)O(shè)備賬號(hào)評(píng)分關(guān)聯(lián)表 根據(jù)每個(gè)設(shè)備上賬號(hào)的登錄次數(shù)我們給與評(píng)分 將匿名用戶(hù)歸給評(píng)分高的用戶(hù) 當(dāng)然了如果該設(shè)備沒(méi)有登錄過(guò)任何一個(gè)賬號(hào) 那就還使用設(shè)備ID
- 新增了用戶(hù)畫(huà)像板塊 主要就是提取一些基本標(biāo)簽
實(shí)時(shí)
- 對(duì)離線(xiàn)數(shù)據(jù)采集部分進(jìn)行了更改 使用flume將數(shù)據(jù)直接采集到kafka 中
- 通過(guò)編寫(xiě)flink程序?qū)?shù)據(jù)進(jìn)行處理后使用側(cè)流輸出將離線(xiàn)部分的數(shù)據(jù)寫(xiě)到hdfs中
- 實(shí)時(shí)使用的數(shù)據(jù)分主題側(cè)流輸出到kafka對(duì)應(yīng)的topic中
- 業(yè)務(wù)數(shù)據(jù)采用的canal 實(shí)時(shí)將mysql的增量數(shù)據(jù)采集對(duì)kafka對(duì)應(yīng)的topic中
- 對(duì)各主題的數(shù)據(jù)進(jìn)行計(jì)算然后導(dǎo)入至clickHouse中或redis中 以供數(shù)據(jù)的展示使用
數(shù)據(jù)建模!!!
-
一般的數(shù)據(jù)建模分兩種
- 一種是自上而下 也就是從需求出發(fā) 根據(jù)業(yè)務(wù)需求 對(duì)接運(yùn)營(yíng)人員 整理所需要的各種指標(biāo) 根據(jù)這些指標(biāo)然后自上而下尋找可以得出這些指標(biāo)的事實(shí)表 維度表等 著這樣一步一步捋清楚 然后進(jìn)行分析開(kāi)發(fā)
- 自下而上 從數(shù)據(jù)源出發(fā) 根據(jù)我們之前埋點(diǎn)的數(shù)據(jù)分析能夠計(jì)算的各種指標(biāo) 和運(yùn)營(yíng)人員對(duì)接 溝通所需要的指標(biāo) 然后進(jìn)行分析
-
關(guān)于大數(shù)據(jù)開(kāi)發(fā) , 阿里提出過(guò) oneData標(biāo)準(zhǔn), 里面提出了建模時(shí)指標(biāo)統(tǒng)一規(guī)范定義 對(duì)數(shù)據(jù)開(kāi)發(fā)的幫助其實(shí)是很有幫助的 因?yàn)橹伴_(kāi)發(fā)的時(shí)候可能遇到兩個(gè)表join的問(wèn)題 , 比如按id進(jìn)行join id這個(gè)字段有int 類(lèi)型的也有String 類(lèi)型的 數(shù)據(jù)類(lèi)型不統(tǒng)一 , 進(jìn)行join的話(huà)默認(rèn)是按 int類(lèi)型來(lái)進(jìn)行join 所有的String類(lèi)型字段就會(huì)進(jìn)入同一個(gè)reduce中 導(dǎo)致數(shù)據(jù)傾斜 解決辦法就是使用函數(shù) cast( id as int )
-
具體我自己實(shí)際操作也沒(méi)有什么大的方向的建模 也就是一些小的表的建模
-
比如之前給我一個(gè)需求,就是計(jì)算新用戶(hù)留存
-
一開(kāi)始我們那邊沒(méi)有一個(gè)固定的規(guī)劃,留存分析的需求會(huì)比較隨機(jī),比如某一天突然來(lái)一個(gè)需求,求X日的新用戶(hù)在Y天(比如7天)后的留存。面對(duì)這種需求,我們都是臨時(shí)去拿X號(hào)的日活表join 7天后的日新表來(lái)計(jì)算。
-
還有像這樣的需求,指定日期段內(nèi),比如10.01 -> 10.20號(hào)期間,查詢(xún)出連續(xù)活躍天數(shù)超過(guò)5天的用戶(hù),我們也是用臨時(shí)手段來(lái)做。
-
后來(lái),我為這一類(lèi)的需求(留存,活躍分析等),就設(shè)計(jì)了一套模型,為這一類(lèi)的需求分析提高了便利和效率
-
我是這樣做的
- 首先,我設(shè)計(jì)了一個(gè)表模型,叫做 用戶(hù)連續(xù)活躍區(qū)間記錄,表里面主要記錄
- 用戶(hù)的首訪日期,用戶(hù)的活躍區(qū)間起始日,用戶(hù)的活躍區(qū)間結(jié)束日
- 如果在計(jì)算日仍然活躍的用戶(hù),則它的最后一個(gè)活躍區(qū)間的結(jié)束日為9999-12-31
- 這個(gè)表的設(shè)計(jì),我借鑒了“拉鏈表”的思想
-
有了這個(gè)表之后,計(jì)算留存分析,就變得很容易;只需要查看連續(xù)活躍區(qū)間表中連續(xù)活躍結(jié)束日是9999 的就可以了
-
計(jì)算用戶(hù)連續(xù)活躍天數(shù)這種需求,也很容易直接group by 用戶(hù) max(datediff ( 時(shí)間差 ) ) 就可以得出了
數(shù)據(jù)采集
- 將app端的日志數(shù)據(jù)通過(guò)flume采集到hdfs , 當(dāng)時(shí)的為了保證數(shù)據(jù)采集的安全可靠 , 我們采用了 taildir + filechannel + hdfssink 同時(shí)為了防止 日志服務(wù)器連接hdfs要開(kāi)啟太多的連接, 我們配置了級(jí)聯(lián)的方式來(lái)采集, 還將sink的策略選擇了 fileover ,保證其中sink掛掉之后還能正常工作 同時(shí), 我們?cè)趂lume channel中里面還設(shè)置了一個(gè)攔截器, 直接將有問(wèn)題的數(shù)據(jù)過(guò)濾掉了, 然 據(jù)里面的時(shí)間取出來(lái),讓對(duì)應(yīng)的數(shù)據(jù)進(jìn)入到對(duì)應(yīng)時(shí)間的的文件夾 因?yàn)閒lume中可以設(shè)置header 和 body 在sink寫(xiě)入文件中時(shí)我們使用通配符的方式 直接讓他取header中找對(duì)應(yīng)的數(shù)據(jù)
- 業(yè)務(wù)數(shù)據(jù)的話(huà)我們采用的是sqoop來(lái)進(jìn)行采集的, 直接將mysql中的數(shù)據(jù)直接采集到了hive中 這邊的數(shù)據(jù)一般都是采用了增量抽取的方式來(lái)進(jìn)行采集的
數(shù)據(jù)計(jì)算層
-
數(shù)據(jù)計(jì)算層的話(huà)我們主要是 基于hive做的一個(gè)離線(xiàn)數(shù)據(jù)分析, 建模的話(huà) 采用的是維度建模, 分了四層, 包括就是 ods , dwd , dws , ads
-
ods 的數(shù)據(jù)就是我們flume采集到的數(shù)據(jù) , flume采集到的數(shù)據(jù)放在hdfs中 , 我們直接在hive中建表然后load到表中, 因?yàn)椴杉降臄?shù)據(jù)都json格式數(shù)據(jù)嘛, 我們就建表的時(shí)候指定了jsonserde
-
然后我們使用spark 程序?qū)ds層的數(shù)據(jù)進(jìn)行了一些加工處理, 包括集成了一些地理維度數(shù)據(jù), 過(guò)濾掉了一些缺少關(guān)鍵字段信息的數(shù)據(jù), 我們?cè)谶@里還將匿名數(shù)據(jù)的問(wèn)題進(jìn)行了解決 , 之前時(shí)直接使用設(shè)備ID來(lái)作為匿名數(shù)據(jù)的用戶(hù) 之后進(jìn)行了改進(jìn)使用動(dòng)態(tài)綁定的方式來(lái)對(duì)匿名用戶(hù)進(jìn)行確定 主要就是做了一個(gè) 設(shè)備賬號(hào)評(píng)分關(guān)聯(lián)表
- 設(shè)備賬號(hào)評(píng)分關(guān)聯(lián)表
一個(gè)設(shè)備可能登錄了多個(gè)用戶(hù) , 這張表保存了每個(gè)設(shè)備上每個(gè)賬號(hào)的登錄得分 登錄一次得分 +100 沒(méi)有登錄則分?jǐn)?shù)就會(huì)衰減- 數(shù)據(jù)過(guò)來(lái) 取出數(shù)據(jù)中 用戶(hù)id 和 設(shè)備ID ,如果有用戶(hù)ID ,則使用用戶(hù)ID 作為 該數(shù)據(jù)的標(biāo)識(shí)
- 如果沒(méi)有用戶(hù)ID ,則拿 設(shè)備ID 去關(guān)聯(lián)評(píng)分字典查詢(xún),取出分值最高的 用戶(hù)ID 作為 guid
- 如果設(shè)備ID 和字典表沒(méi)有關(guān)聯(lián)上 ,就使用設(shè)備ID作為 guid
- 賬號(hào)設(shè)備評(píng)分關(guān)聯(lián)表實(shí)現(xiàn)流程
數(shù)據(jù)中存在匿名訪問(wèn)數(shù)據(jù) 我們需要對(duì)匿名訪問(wèn)數(shù)據(jù)關(guān)聯(lián)一個(gè)guid
因?yàn)樵O(shè)備ID是必須存在 不存在我們就直接過(guò)濾掉了 但是一個(gè)設(shè)備上可能登錄多個(gè)賬號(hào)我們需要選擇一個(gè)作為guid 使用動(dòng)態(tài)綁定的方式 構(gòu)建了一張?jiān)O(shè)備賬號(hào)評(píng)分關(guān)聯(lián)表 表中的字段包括 設(shè)備ID 賬號(hào)ID 得分 最后登錄時(shí)間- 按設(shè)備和賬號(hào)進(jìn)行分組, 計(jì)算每個(gè)分組內(nèi)會(huì)話(huà)次數(shù), 每次會(huì)話(huà)算一次登錄, 一次登錄得 100分
- 將 計(jì)算好的結(jié)果 和 前一天的設(shè)備賬號(hào)評(píng)分關(guān)聯(lián)表 數(shù)據(jù)進(jìn)行full join 連接條件 登錄ID 和 設(shè)備ID 相同
- 前一天 登錄 今天 登錄 score相加
- 前一天 登錄 今天 沒(méi)有登錄 score衰減 為 0.7
- 前一天 沒(méi)有登錄 今天 登錄 score為 今天 的值
- 設(shè)備賬號(hào)評(píng)分關(guān)聯(lián)表
-
集成地理位置信息
- 日志數(shù)據(jù)中一般只記錄了經(jīng)緯度 沒(méi)有記錄對(duì)應(yīng)的省市區(qū),需要集成
- 公司有對(duì)應(yīng)的地理位置字典表 但是字段是省市區(qū) 經(jīng)緯度 使用geohash的方式將數(shù)據(jù)進(jìn)行了處理 變成 省市區(qū) geohash值 然后廣播出去
- 將數(shù)據(jù)中的經(jīng)緯度也轉(zhuǎn)換成geohash值 到廣播的數(shù)據(jù)中匹配 匹配的上就取出對(duì)應(yīng)的省市區(qū)
- 匹配不上就使用ip2region進(jìn)行查找匹配
-
dwd層放的就是我們處理好的明細(xì)寬表
-
dws層的數(shù)據(jù)主要就是對(duì)最終的結(jié)果報(bào)表數(shù)據(jù)做準(zhǔn)備的
- dws這一層我們分主題做了一些輕度聚合表和一些中間表, 基礎(chǔ)流量指標(biāo)分析 , 活躍度相關(guān)報(bào)表的分析等等的, 主要是為了最后的結(jié)果數(shù)據(jù)做準(zhǔn)備, 比如流量主題的我當(dāng)時(shí)做了有流量會(huì)話(huà)聚合表 (指標(biāo)有 日/周/月 pv uv 總訪問(wèn)時(shí)長(zhǎng)等),
- 用戶(hù)活躍度相關(guān)分析, 做了一個(gè)日活明細(xì)表, 保存了當(dāng)天活躍的用戶(hù), 這個(gè)表就是來(lái)自于流量會(huì)話(huà)聚合表, 取出了里面所有的guid然后又做了一個(gè)用戶(hù)連續(xù)活躍區(qū)間記錄表, 這是一個(gè)拉鏈表, 可以清楚的看到用戶(hù)那天活躍那天沒(méi)活躍
-
最后ads層 , 這里面就是放的是一些我們計(jì)算時(shí)用到的需要進(jìn)行展示的表
-
接下來(lái)就是數(shù)據(jù)服務(wù)層的一些東西了, 也就是olap平臺(tái) 這塊的話(huà)也分三部分,
- 第一部分 常規(guī)的我們保存在ads層的一些固定的報(bào)表, 這些表我們一般就是直接使用 blukload 導(dǎo)入到hbase中, 用來(lái)做數(shù)據(jù)的可視化展現(xiàn)
- 寫(xiě)spark程序?qū)?/li>
- 多維數(shù)據(jù)分析, 我們之前的時(shí)候直接用的hive的高階聚合函數(shù) , 像 with cube , grouping sets(可自己定義聚合維度) , with rollup(層級(jí)聚合), 后來(lái)引入了kylin , 就使用kylin來(lái)做, 聚合好的結(jié)果默認(rèn)就是保存在hbase中
- 然后的話(huà)就是一些非固定模型的在線(xiàn)實(shí)時(shí)計(jì)算, 我們當(dāng)時(shí)使用的是presto , 他是一個(gè)純內(nèi)存的計(jì)算引擎, 可以對(duì)接多種數(shù)據(jù)源
- 第一部分 常規(guī)的我們保存在ads層的一些固定的報(bào)表, 這些表我們一般就是直接使用 blukload 導(dǎo)入到hbase中, 用來(lái)做數(shù)據(jù)的可視化展現(xiàn)
-
整體的話(huà)就是這樣, 其他的話(huà), 比如當(dāng)時(shí)我們?cè)獢?shù)據(jù)管理系統(tǒng)用的是atlas 任務(wù)調(diào)度的話(huà)當(dāng)時(shí)使用的是azkaban
-
Atlas跟大數(shù)據(jù)中各種數(shù)據(jù)源組件進(jìn)行了深度整合,它可以自動(dòng)去獲取這些數(shù)據(jù)源組件中的數(shù)據(jù)的元信息,納入自己的存儲(chǔ)提供管理查看,可以省卻大量的人工錄入元信息工作
-
寫(xiě)各種的腳本然后然后根據(jù)互相之間的依賴(lài)呀串成一串 , 提交到azkaban上去執(zhí)行
業(yè)務(wù)域 :
主要從業(yè)務(wù)庫(kù)表中拿去數(shù)據(jù)來(lái)進(jìn)行分析, 業(yè)務(wù)庫(kù)的數(shù)據(jù)一般來(lái)自業(yè)務(wù)系統(tǒng)的數(shù)據(jù)庫(kù)mysql中, 主要表格包括 :
-
cms 是網(wǎng)站的內(nèi)容管理相關(guān)表 發(fā)帖, 回帖…
-
oms 是訂單相關(guān)的表, 和交易有關(guān)的 生成訂單, 添加購(gòu)物車(chē)…
-
pms 是關(guān)于產(chǎn)品相關(guān)的表, 產(chǎn)品評(píng)論 內(nèi)容 回復(fù) …
-
sms 營(yíng)銷(xiāo)類(lèi)表 優(yōu)惠卷 廣告 …
-
ums 會(huì)員相關(guān)的 …
-
ods層 : 放置了每天的用戶(hù),訂單等等的增量數(shù)據(jù)
-
dw層 : 將ods層中的增量導(dǎo)入dwd層, 同時(shí)對(duì)一些重要的表做了拉鏈表(全量表) 例 訂單表, 緩慢變化維度表. 便于查詢(xún)歷史上任何一天的數(shù)據(jù)的狀態(tài),
-
dws層 : 主要是一些寬表, 根據(jù)需求將事實(shí)表和維度表進(jìn)行join形成一張寬表, 以此為基礎(chǔ)計(jì)算所需的報(bào)表
主要的策略 : 大表 增量抽取 小表 全量抽取
主要負(fù)責(zé)!!!
- 基礎(chǔ)流量指標(biāo)分析 (流量會(huì)話(huà)聚合表) (指標(biāo)有 日/周/月 pv uv 總訪問(wèn)時(shí)長(zhǎng)等)
- 用戶(hù)活躍度主題 (拉鏈表 用戶(hù)活躍區(qū)間) ( 指標(biāo) 連續(xù)活躍超過(guò) 5 天 10天 連續(xù)沉默 … 用戶(hù)留存 )
- 歸因事件分析(支付訂單 這個(gè)操作可能有多個(gè)條件導(dǎo)致 通過(guò)點(diǎn)擊某個(gè)運(yùn)營(yíng)位,點(diǎn)擊廣告位看到點(diǎn)進(jìn)去購(gòu)買(mǎi) 或者直接搜索) 一般使用首次歸因進(jìn)行分析 同一個(gè)用戶(hù)購(gòu)買(mǎi)一件商品歸因分析 先按時(shí)間將待歸因事件進(jìn)行過(guò)濾 然后在取出第一個(gè)事件 得到的就是首次歸因 和業(yè)務(wù)人員以及前端人員一起商量
- 多維指標(biāo)的統(tǒng)計(jì) 之前的話(huà)是使用hive的高階聚合函數(shù)來(lái)進(jìn)行 后使用kylin
離線(xiàn)指標(biāo)計(jì)算
基礎(chǔ)指標(biāo)
基礎(chǔ)流量指標(biāo)分析 (流量會(huì)話(huà)聚合表) (指標(biāo)有 日/周/月 pv uv 總訪問(wèn)時(shí)長(zhǎng)等)
- 比如統(tǒng)計(jì)日活 月活這些指標(biāo) 我們可以清晰的看出我們的產(chǎn)品目前的狀態(tài) 根據(jù)日活月活分析判斷我們的產(chǎn)品是否需要更進(jìn)一步的推廣
- 假如當(dāng)前日活月活穩(wěn)定在一個(gè)正常值,但是增長(zhǎng)緩慢,從這里或許我們就能得出,用戶(hù)增長(zhǎng)穩(wěn)定但增速變慢了,可以嘗試進(jìn)一步推廣,擴(kuò)大用戶(hù)規(guī)模
歸因分析
歸因事件分析(支付訂單 這個(gè)操作可能有多個(gè)條件導(dǎo)致 通過(guò)點(diǎn)擊某個(gè)運(yùn)營(yíng)位,點(diǎn)擊廣告位看到點(diǎn)進(jìn)去購(gòu)買(mǎi) 或者直接搜索) 一般使用首次歸因進(jìn)行分析 同一個(gè)用戶(hù)購(gòu)買(mǎi)一件商品歸因分析 先按時(shí)間將待歸因事件進(jìn)行過(guò)濾 然后在取出第一個(gè)事件 得到的就是首次歸因 和業(yè)務(wù)人員以及前端人員一起商量
比如提交訂單這個(gè)事件
- 他可能有多種行為導(dǎo)致他提交訂單的操作
- 包括自己搜索呀, 點(diǎn)擊某個(gè)廣告位 點(diǎn)擊他人分享等 我們一般會(huì)和運(yùn)營(yíng)人員進(jìn)行商討 選擇合適的歸因模型
- 比如選擇首次歸因 判斷用戶(hù)每次提交訂單的行為是從那個(gè)行為上最先感興趣的的
- 如果大部分都是某個(gè)廣告位點(diǎn)擊進(jìn)行的 那我們就提高此廣告位的曝光率 以便提高訂單的轉(zhuǎn)換率
用戶(hù)活躍度
我們當(dāng)時(shí)有一張日活表, 就是記錄了每天的活躍用戶(hù)
用戶(hù)活躍度分析
需求 : 求一個(gè)月內(nèi)用戶(hù)連續(xù)登錄超過(guò)5天的人數(shù) 10 天的人數(shù)…
- 最簡(jiǎn)單的方法也是最笨的方法就是連續(xù)join 效率極低
- 為此我當(dāng)時(shí)開(kāi)發(fā)了一個(gè)拉鏈表樣子的用戶(hù)連續(xù)活躍區(qū)間記錄表 表中字段大概就是 用戶(hù)首次登陸日期 用戶(hù) 連續(xù)活躍起始日 連續(xù)活躍結(jié)束日, 以此 再來(lái)開(kāi)發(fā)最終報(bào)表就變得很容易了 而且根據(jù)這張表我們當(dāng)時(shí)順帶的就將用戶(hù)留存分析也做完了 因?yàn)榱舸娣治鲂枨笠话悴皇翘辔覀冎耙话愣际乾F(xiàn)算, 之前的一般都是拿之前天的日活表去join 需要查看的天的日活, join上的就是留存了的, 現(xiàn)在我們只需要查看連續(xù)活躍區(qū)間表中連續(xù)活躍結(jié)束日是9999 的就可以了
- 具體表的實(shí)現(xiàn) :
- 使用 T-1 日的用戶(hù)連續(xù)活躍記錄表 fulljoin T 日的用戶(hù)日活表( 這張表記錄了每天的活躍用戶(hù) )
- 分情況進(jìn)行處理
- 用戶(hù) t-1 為 9999 的且 當(dāng)日活躍的 只需要修改連續(xù)活躍結(jié)束日
- 用戶(hù) t-1 為 9999 但join不上的 說(shuō)明當(dāng)日沒(méi)有活躍 修改 9999為 t-1日
- 用戶(hù) t-1 為 null t 不為null 的 使用 t日作為 首訪日期 連續(xù)活躍起始日 連續(xù)活躍結(jié)束日
- 用戶(hù) t-1 結(jié)束日不為 9999 的不做任何改變
- 有一個(gè)問(wèn)題是之前已經(jīng)是閉區(qū)間的數(shù)據(jù) 需要新生成一條數(shù)據(jù)然后 union 到之前的表中
- 查詢(xún)出是閉區(qū)間的數(shù)據(jù) 和 日活表進(jìn)行join 將join上數(shù)據(jù)取出 t-1日的 首訪日期 t日作為連續(xù)活躍起始日, 9999作為連續(xù)活躍結(jié)束日 和之前表 union到一起
- 用戶(hù) t-1 為 9999 的且 當(dāng)日活躍的 只需要修改連續(xù)活躍結(jié)束日
- 分情況進(jìn)行處理
- 使用 T-1 日的用戶(hù)連續(xù)活躍記錄表 fulljoin T 日的用戶(hù)日活表( 這張表記錄了每天的活躍用戶(hù) )
多維聚合bitmap
bitmap算法 就是保存在內(nèi)存中的連續(xù)的二進(jìn)制位, 用于對(duì)大量的整數(shù)型數(shù)據(jù)做去重和查詢(xún)操作 .
一開(kāi)始并不是使用kylin來(lái)進(jìn)行多維統(tǒng)計(jì)的使用的hive 的高階函數(shù) with cube , 但是hive 的高階聚合函數(shù)在進(jìn)行多維計(jì)算時(shí)有一些的指標(biāo)的計(jì)算需要使用到count(distinct) , 會(huì)消耗很大的資源, 因此我們當(dāng)時(shí)借鑒了bitmap的思想, 來(lái)對(duì)那些需要去重聚合的指標(biāo)進(jìn)行計(jì)算-
我們當(dāng)時(shí)使用的是roaring bitmap 性能比較好, 它提供了方法將數(shù)據(jù)轉(zhuǎn)換成bitmap類(lèi)型, 一條數(shù)據(jù)在bitmap中只占用一個(gè)bit位 , 存進(jìn)去數(shù)據(jù)后它會(huì)將相應(yīng)bit位的值置為 1 , 下次相同的數(shù)據(jù)再進(jìn)來(lái)還是會(huì)進(jìn)入到同一個(gè)bit位上 , 這樣就能實(shí)現(xiàn)去重 , 同時(shí)bitmap中還提供了計(jì)算bitmap中 1 的個(gè)數(shù)的方法, 這樣我們就可以將去重總數(shù)統(tǒng)計(jì)出來(lái)了.
-
同時(shí)我們還通過(guò) bitmap 的 思想實(shí)現(xiàn)了層級(jí)聚合的操作 , 比如計(jì)算好 省市區(qū) 的數(shù)據(jù)之后在計(jì)算 省市 的維度我們就可以使用bitmap 中提供的or操作來(lái)進(jìn)行計(jì)算
- 例 :
省 市 區(qū) 人
a b c [1001]
a b d [1100]
- 例 :
-
計(jì)算
- 那么如果要計(jì)算 a省b市 的人數(shù) 只需要將兩個(gè)數(shù)據(jù)進(jìn)行or操作 就能得到的結(jié)果 [1 1 0 1]
- 因?yàn)閔ive中不支持bitmap類(lèi)型 , 因此我們將數(shù)據(jù)轉(zhuǎn)換成binary類(lèi)型存儲(chǔ)在hive中
- 通過(guò)自定義函數(shù)的方式實(shí)現(xiàn)了這些方法, 同時(shí)我們編寫(xiě)sparkSQL 得到最終的結(jié)果
多維分析中的常用操作(上鉆 … ):
數(shù)據(jù)立方體中最常見(jiàn)的五大操作:切片Slice,切塊Dice,旋轉(zhuǎn)Pivot,上卷(也叫向上鉆取)Roll-up,下鉆Drill-down
- 下鉆Drill-down:向下從更細(xì)分的粒度(維度)來(lái)探索分析數(shù)據(jù),如按照時(shí)間維度,按照天粒度來(lái)分析數(shù)據(jù)
- 改變維的層次,變換分析的粒度。從上層降到下一層,或者說(shuō)是將匯總數(shù)據(jù)拆分到更細(xì)節(jié)的數(shù)據(jù)。比如通過(guò)對(duì)2010年第二季度的總銷(xiāo)售數(shù)據(jù)進(jìn)行鉆取來(lái)查看2010年第二季度4、5、6每個(gè)月的消費(fèi)數(shù)據(jù),當(dāng)然也可以鉆取浙江省來(lái)查看杭州市、寧波市、溫州市……這些城市的銷(xiāo)售數(shù)據(jù)。
- 上卷Roll-up: 向上從更粗的粒度(維度)來(lái)探索分析數(shù)據(jù),比如時(shí)間維度,按照季度來(lái)分析數(shù)據(jù)
- 鉆取的逆操作,即從細(xì)粒度數(shù)據(jù)向高層的聚合,如將江蘇省、上海市和浙江省的銷(xiāo)售數(shù)據(jù)進(jìn)行匯總來(lái)查看江浙滬地區(qū)的銷(xiāo)售數(shù)據(jù)。
- 切片Slice: 查詢(xún)某個(gè)維度等于某個(gè)指定值的數(shù)據(jù)集 比如按照產(chǎn)品種類(lèi)等于電子產(chǎn)品的維度 來(lái)分析數(shù)據(jù)
- 選擇維中特定的值進(jìn)行分析,比如只選擇電子產(chǎn)品的銷(xiāo)售數(shù)據(jù),或者2010年第二季度的數(shù)據(jù)。
- 切塊Dice: 查詢(xún)某個(gè)維度等于某幾個(gè)指定值的數(shù)據(jù)集
- 選擇維中特定區(qū)間的數(shù)據(jù)或者某批特定值進(jìn)行分析,比如選擇2010年第一季度到2010年第二季度的銷(xiāo)售數(shù)據(jù),或者是電子產(chǎn)品和日用品的銷(xiāo)售數(shù)據(jù)。
- 旋轉(zhuǎn)Pivot:即維的位置的互換,就像是二維表的行列轉(zhuǎn)換,如通過(guò)旋轉(zhuǎn)實(shí)現(xiàn)產(chǎn)品維和地域維的互換。 旋轉(zhuǎn) 變換維度展現(xiàn)順序
用戶(hù)畫(huà)像
主要工作就是提取一些基礎(chǔ)指標(biāo) 或者 給專(zhuān)門(mén)的做機(jī)器學(xué)習(xí)的同時(shí)提供點(diǎn)數(shù)據(jù) 了解過(guò)一點(diǎn)機(jī)器學(xué)習(xí)算法
用戶(hù)訂單畫(huà)像標(biāo)簽表開(kāi)發(fā)
- 標(biāo)簽包括 用戶(hù)id 第一次下單時(shí)間 最后一次下單時(shí)間 一個(gè)月下單次數(shù) 一個(gè)月內(nèi)下單總金額 最大訂單金額 最小訂單金額 平均訂單金額 常用支付方式 常購(gòu)買(mǎi)物品品類(lèi) 收貨地址…
- 需要使用到 訂單表 訂單商品明細(xì)表 都是從mysql中導(dǎo)入過(guò)來(lái)的表
- 將對(duì)應(yīng)的字段取出
樸素貝葉斯
向量是一串?dāng)?shù)字
向量可以代表現(xiàn)實(shí)中某種事物的一系列特征和特征值
向量可以理解為:這串?dāng)?shù)字,基于原點(diǎn),所指向的n維空間的,某個(gè)方向的,固定長(zhǎng)度;最終代表的就是一個(gè)點(diǎn)
- 用戶(hù)行為性別預(yù)測(cè)
先經(jīng)過(guò)大量統(tǒng)計(jì)得到一份經(jīng)驗(yàn)數(shù)據(jù) ( 相對(duì)教準(zhǔn)確的數(shù)據(jù) ) 將這些數(shù)據(jù)經(jīng)過(guò)向量化 調(diào)用API得到訓(xùn)練模型將需要預(yù)測(cè)的數(shù)據(jù)也經(jīng)過(guò)向量化 然后加載之前的訓(xùn)練模型對(duì)數(shù)據(jù)進(jìn)行預(yù)測(cè)分析得到最終結(jié)果
實(shí)時(shí)指標(biāo)統(tǒng)計(jì)
ETL 實(shí)時(shí)新老用戶(hù)標(biāo)記
判斷一條數(shù)據(jù)所屬用戶(hù)是新用戶(hù)還是老用戶(hù)
使用布隆過(guò)濾器 + Rocks DB
布隆過(guò)濾器 更加的節(jié)省空間
RocksDB 可以存儲(chǔ)更多狀態(tài)、有長(zhǎng)窗口(window state)、key、value的可以保存更大的數(shù)據(jù)(2 G)同時(shí)可以實(shí)現(xiàn)增量checkpoint
實(shí)現(xiàn)方式 :
- 使用設(shè)備ID 作為用戶(hù)標(biāo)識(shí)的, 進(jìn)行keyBy, 設(shè)備ID相同的用戶(hù)會(huì)進(jìn)入到同一個(gè)分區(qū)中 使用BloomFilter 來(lái)判斷是否為新用戶(hù)
- 然后我們定義了一個(gè)OperatorState 保存BloomFilter, 因?yàn)槿绻褂?keyedState 來(lái)保存 一個(gè)設(shè)備ID 就對(duì)應(yīng)一個(gè)BloomFilter 浪費(fèi)資源 需要實(shí)現(xiàn)CheckPointFunction , 這樣子一個(gè)分區(qū)就會(huì)擁有一個(gè)屬于自己分區(qū)的BloomFilter 節(jié)省資源 而且還不會(huì)數(shù)據(jù)傾斜
- 然后在實(shí)現(xiàn)的方法中使用 定義狀態(tài) 狀態(tài)里面保存了BloomFilter 來(lái)一條數(shù)據(jù)判斷該條數(shù)據(jù)的設(shè)備ID 是否已經(jīng)存在, 存在就將該條數(shù)據(jù)置為老用戶(hù), 同時(shí)我們使用了Rocks DB代替 stateBackEnd 來(lái)保存狀態(tài), 這樣子就可以保存更多的狀態(tài)數(shù)據(jù) , 同時(shí)還可以實(shí)現(xiàn)增量checkpoin
- RocksDB 的使用
env.setStateBackend(new RocksDBStateBackend(checkpointPath, true));
- RocksDB 的使用
直播間人氣實(shí)時(shí)統(tǒng)計(jì)
規(guī)則 :
進(jìn)入直播間超過(guò)一分鐘的人氣值 +1 30分內(nèi)連續(xù)進(jìn)入直播間的人氣值不變進(jìn)入間隔超過(guò)30分的人氣值+1下一次進(jìn)入直播間的時(shí)間 - 上一次離開(kāi)直播間的時(shí)間 > 30分鐘 又算一個(gè)人氣值實(shí)現(xiàn)方式 :
- 按照主播ID, deviceID 進(jìn)行 keyBy
- 使用進(jìn)入直播間時(shí)間+1注冊(cè)定時(shí)器 如果下次出去時(shí)間小于一分鐘, 刪除定時(shí)器 如果定時(shí)器觸發(fā) 判斷上次 進(jìn)去時(shí)間 上次時(shí)間為空 人氣值 +1 上次不為空且 這次進(jìn)入- 上次出去 > 30 人氣值 +1
- 計(jì)算好的數(shù)據(jù)在使用直播間號(hào)進(jìn)行keyBy 將數(shù)據(jù)進(jìn)行sum聚合求得最后每個(gè)直播間的人氣值, 最后再將結(jié)果輸出至redis中, 實(shí)時(shí)展示
實(shí)時(shí)統(tǒng)計(jì)直播間 pv , uv , 實(shí)時(shí)在線(xiàn)人數(shù), 以及不同維度下的指標(biāo)
pv uv 實(shí)時(shí)在線(xiàn)人數(shù)使用 flink 計(jì)算然后批量寫(xiě)入至redis中 編寫(xiě)定時(shí)器批量攢數(shù)據(jù)
將處理好的數(shù)據(jù)按批次導(dǎo)入至click house中, 統(tǒng)計(jì)多維指標(biāo)
實(shí)現(xiàn)方式 :
- 將直播數(shù)據(jù)按 直播間ID進(jìn)行keyBy 同一個(gè)直播間的數(shù)據(jù)進(jìn)入同一個(gè)分區(qū)的同一個(gè)組內(nèi)
- 因?yàn)橐M(jìn)行uv , 所以使用 布隆過(guò)濾器 來(lái)進(jìn)行去重, 同時(shí)定義 pv , uv , online , BloomFilter 四個(gè)狀態(tài)來(lái)保存數(shù)據(jù)
- 一條數(shù)據(jù)進(jìn)來(lái) 判斷在布隆過(guò)濾器中是否存在,
- 不存在 那么 uv ++, pv ++ ,online ++
- 存在 pv ++ , online ++ 同時(shí)將數(shù)據(jù)加入至BloomFilter中
- 數(shù)據(jù)出去 online–
- 結(jié)果數(shù)據(jù)最后輸出至redis中實(shí)時(shí)展示, 因此我們定義了一個(gè)計(jì)算器10秒觸發(fā)一次, 將數(shù)據(jù)輸出至 redis 中 具體實(shí)現(xiàn) :
- 使用當(dāng)前時(shí)間 / 10秒 ==> 和10 的差值
- 當(dāng)前時(shí)間 - 差值 +10秒就獲得了10秒后的時(shí)間
- 10內(nèi)進(jìn)入的數(shù)據(jù)每次都會(huì)生成一個(gè)定時(shí)器 但是定時(shí)器的時(shí)間都是一致的 指揮觸發(fā)一次
- 這樣子就實(shí)現(xiàn)了10秒觸發(fā)一次的定時(shí)器
直播期間各個(gè)主播直播收到的禮物分值計(jì)算
需要關(guān)聯(lián)禮物維表 , 根據(jù)禮物維表的數(shù)據(jù)計(jì)算對(duì)應(yīng)禮物的分值
使用廣播狀態(tài), 將業(yè)務(wù)庫(kù)中的禮物表數(shù)據(jù)廣播至狀態(tài)中, 然后connect關(guān)聯(lián)查詢(xún)
Flink中廣播的數(shù)據(jù)可以實(shí)現(xiàn)實(shí)時(shí)的更新
實(shí)現(xiàn)方式 :
- 將維度數(shù)據(jù)連接MySQL查詢(xún)出來(lái) , 整理好之后將維度數(shù)據(jù)廣播到狀態(tài)里
- 將事實(shí)數(shù)據(jù)進(jìn)行整理后 和 廣播的數(shù)據(jù)進(jìn)行connect 關(guān)聯(lián) 然后調(diào)用 process 方法 , 因?yàn)樾枰途S度數(shù)據(jù)進(jìn)行關(guān)聯(lián)處理 , 因此使用 BroadcastProcessFunction
- 需要重寫(xiě)兩個(gè)方法 : processBroadcastElement 處理廣播數(shù)據(jù) 可以將廣播的數(shù)據(jù)進(jìn)行更新 processElement 處理事實(shí)數(shù)據(jù) 可以讀取廣播數(shù)據(jù) 不能修改
- 關(guān)聯(lián)維度數(shù)據(jù)后將最終的數(shù)據(jù)輸出 , 按主播ID 進(jìn)行keyBy 后進(jìn)行sum操作, 再將最終的結(jié)果數(shù)據(jù)輸出值redis中
統(tǒng)計(jì) : 10分鐘內(nèi), 每隔1分鐘統(tǒng)計(jì)一次各個(gè)分類(lèi)、各種事件類(lèi)型的熱門(mén)商品(商品ID)
例 :
[10:00] , [10:10] , 華為 , 瀏覽 , p10 , 20 [10:00] , [10:10] , 華為 , 加入購(gòu)物車(chē) , p10 , 20[10:00] , [10:10] ,華為 , 瀏覽 , p30 , 29 ... [10:00] , [10:10] , 華為 , 加入購(gòu)物車(chē) , p30 , 29 ...實(shí)現(xiàn)方式 :
- 先將數(shù)據(jù)進(jìn)行keyBy(分類(lèi)ID,事件ID,商品ID),劃分窗口 ( 使用滑動(dòng)窗口)
- 然后對(duì)窗口內(nèi)數(shù)據(jù)進(jìn)行增量聚合(效率高,全局聚合效率低,而且占用大量資源)
- 我們?cè)谠隽亢喜⒌臅r(shí)候除了需要獲得到:( 分類(lèi)ID,事件ID,商品ID,次數(shù) ), 還需要獲取窗口的信息(窗口的起始時(shí)間,結(jié)束時(shí)間)
- 因此增量合并使用 aggregate 方法 , 這樣能夠在增量聚合的同時(shí)定義一個(gè)窗口 , 窗口觸發(fā)后可以在這個(gè)窗口中獲取到窗口聚合后的數(shù)據(jù),并且可以得到窗口的起始時(shí)間和結(jié)束時(shí)間 輸出結(jié)果為 : ( 分類(lèi)ID,事件ID,商品ID,次數(shù),窗口起始時(shí)間,結(jié)束時(shí)間 )。
- 將數(shù)據(jù)以(分類(lèi)ID,事件ID,窗口起始時(shí)間,結(jié)束時(shí)間)進(jìn)行keyBy , 然后進(jìn)行排序 :使用ProcessFunction的onTimer定時(shí)器進(jìn)行排序,每來(lái)一條數(shù)據(jù),不直接輸出,而是將數(shù)據(jù)存儲(chǔ)到State(為了容錯(cuò)),再注冊(cè)一個(gè)比當(dāng)前窗口的結(jié)束時(shí)間還要大一毫秒的定時(shí)器。如果下一個(gè)窗口的數(shù)據(jù)觸發(fā)了,那么Water Mark已經(jīng)大于了注冊(cè)的定時(shí)器的時(shí)間,上一個(gè)窗口的數(shù)據(jù)已經(jīng)攢齊了,就可以排序然后輸出。
- 將最終結(jié)果進(jìn)行整理后輸出至redis中
實(shí)時(shí)統(tǒng)計(jì)訂單相關(guān)指標(biāo)
分析的實(shí)時(shí)指標(biāo) :直播間主播帶貨總金額、商品成交( 下單 )數(shù)量
- 直播間主播帶商品各個(gè)分類(lèi)的成交金額、商品成交( 下單 ) 數(shù)量
- 一天內(nèi)中的成交金額
- 各個(gè)分類(lèi)成交金額(維度:省份、操作系統(tǒng)、手機(jī)型…)
實(shí)現(xiàn)方式 :
- 使用雙流 Join
- 將業(yè)務(wù)庫(kù)中的訂單主表和訂單明細(xì)表取出進(jìn)行分析處理 , 業(yè)務(wù)數(shù)據(jù)使用canal讀取過(guò)來(lái)的 , 數(shù)據(jù)是一個(gè)大的JSON串 我要需要的是他里面 data 對(duì)應(yīng)的 一個(gè)小的 JSON 串 將里面的數(shù)據(jù)封裝到一個(gè)bean 里
- 訂單主表:訂單ID、用戶(hù)ID、訂單狀態(tài)、訂單金額、下單時(shí)間、更新時(shí)間
- 訂單明細(xì)表 :訂單主表ID、sku、數(shù)量、單價(jià)、分類(lèi)ID、直播間ID
- 由于業(yè)務(wù)系統(tǒng)可能存在延遲, 我們將訂單明細(xì)表劃窗口, 使用側(cè)流輸出獲取窗口中遲到的數(shù)據(jù)
- 將主流中業(yè)務(wù)訂單明細(xì)數(shù)據(jù)left join 訂單主表 關(guān)聯(lián)上的就輸出 tuple2 < > 關(guān)聯(lián)不上就將關(guān)聯(lián)不上的輸出為null
- 將join后的數(shù)據(jù)和之前側(cè)流輸出的數(shù)據(jù)進(jìn)行union然后將關(guān)聯(lián)不上的和側(cè)流輸出的數(shù)據(jù) 也就是 主表數(shù)據(jù)為null的連接數(shù)據(jù)庫(kù)進(jìn)行查詢(xún)
- 然后將最終的結(jié)果輸出到clickhouse中
總結(jié)
- 上一篇: K线图|K线图分析法简介 |K线图怎么看
- 下一篇: OpenCV切割图片