1.hive SQL的分組topN問題,成績(jī)表S,字段sid,cid,score,求每門課程的前2名與后2名sid。
2.ES中游標(biāo)和快照有什么區(qū)別?
3.用戶畫像、推薦系統(tǒng)、Flink實(shí)時(shí)數(shù)倉(cāng)、準(zhǔn)實(shí)時(shí)數(shù)倉(cāng)中,遇到的棘手的問題都有什么?
4.用戶畫像系統(tǒng)中遇到的比較難的問題是什么?
5.如何構(gòu)建用戶的稠密向量的問題?
答案區(qū)
1.下面是我的做法,求個(gè)更好的
select sid from
(select sid,
rank() over(partition by cid order by score) as RA
from S) as A
union
(select sid,
rank() over(partition by cid order by score DESC) as RB
from S) as B
where RA<3 and RB<3
2.它們兩個(gè)沒有什么可比性, 在深分頁場(chǎng)景下我們不能使用(from+size)的方式查詢ES,因?yàn)樾阅芴?from+size 方式會(huì)從每個(gè)分片取出from+size大小的數(shù)據(jù),讓后在協(xié)調(diào)節(jié)點(diǎn)做Merge返回,分頁越深協(xié)需要處理的數(shù)據(jù)量越大)。一般使用`scroll`方式解決深分頁問題,`scroll`在初始化階段會(huì)對(duì)查詢數(shù)據(jù)生成`快照(不可變的數(shù)據(jù)集,不受索引的更新,刪除的影響,單維護(hù)這個(gè)快照是需要耗費(fèi)資源的)`,之后的查詢都會(huì)對(duì)快照數(shù)據(jù)根據(jù)`scroll_id`進(jìn)行遍歷查詢。
3.用戶畫像
我們?cè)谶x擇如何存儲(chǔ)用戶標(biāo)簽時(shí),遇到了問題(標(biāo)簽查詢速度慢,并且構(gòu)建不夠靈活,標(biāo)簽更新和刪除比較麻煩),比如之前用HDFS或者ES存儲(chǔ),后來切換為ClikcHouse,并用BitMap存儲(chǔ),原因如下:
針對(duì)標(biāo)簽的表示形式,存儲(chǔ)方式有很多,結(jié)構(gòu)為`寬表,BitMap` 都可以,存儲(chǔ)選擇`HDFS,ES,ClickHouse 等` 也都可以,需要衡量的有兩點(diǎn):
1)標(biāo)簽構(gòu)建的靈活性和構(gòu)建速度
2)標(biāo)簽的查詢效率 ` `HDFS [Presot,Impala]:` 標(biāo)簽的增加,刪除,更新不友好, 一個(gè)小變動(dòng),要重寫整個(gè)`Parquet`, 寫放大問題。 查詢效率還可以,但是不夠優(yōu)秀。 支持查詢并發(fā)較小。 `ES:`標(biāo)簽的構(gòu)建的寫入速度一般, 新增和修改標(biāo)簽需要對(duì)ES文檔結(jié)構(gòu)更新,ES的DSL語法不友好,有一定學(xué)習(xí)成本。查詢效率還算優(yōu)秀,同時(shí)支持高并發(fā)。 ES資源占用高,需要較好的硬件配置。 `ClickHouse[BitMap]` 標(biāo)簽可以并行構(gòu)建,查詢效率優(yōu)秀,標(biāo)簽的增加非常方便,標(biāo)簽的更新和刪除可以實(shí)現(xiàn),但是并不高效,并發(fā)查詢支持比Presto,Impala要好,但同樣不支持高并發(fā),能夠滿足大部分場(chǎng)景需求。注意兩點(diǎn):
a. BitMap存儲(chǔ)的是用戶ID
b. BitMap使用了RoaringBitMap, 解決BitMap空間占用問題,不然1億這一個(gè)數(shù)也要占用11.9M空間`
如何構(gòu)建用戶的稠密向量的問題?
如果我們直接將用戶的標(biāo)簽轉(zhuǎn)換為稀疏向量來存儲(chǔ),對(duì)于類別標(biāo)簽使用`one-hot`編碼,但這樣會(huì)出現(xiàn)維度爆炸的問題,向量過于稀疏,向量之間的余弦相似度計(jì)算結(jié)果基本沒有意義,根本無法實(shí)現(xiàn)用戶相似度的計(jì)算。所以就開始思考如何將用戶表示為轉(zhuǎn)換為稠密向量,經(jīng)過調(diào)研發(fā)現(xiàn),Word2Vec可以將詞轉(zhuǎn)換為稠密向量,同時(shí)借助Word2Vec思想,也可以將物品轉(zhuǎn)換為向量Item2Vec,比如將一個(gè)Session內(nèi),用戶購(gòu)買的物品或者點(diǎn)擊的物品列表,看成是一句話,每個(gè)物品看成是一個(gè)單詞,就可以借助Word2Vec的思想將物品轉(zhuǎn)換為稠密向量表示。(這里注意如果是文章,可以使用分詞,然后抽取關(guān)鍵詞,將詞通過Word2Vec轉(zhuǎn)換為向量的方式) ,我們?cè)賹⒂脩酎c(diǎn)擊或者購(gòu)買的物品列表中物品向量加和求平均,就可以得到用戶的稠密向量。后來發(fā)現(xiàn)通過ALS模型`矩陣分解`的方式也可以得到用戶的稠密向量,兩者`表達(dá)的用戶向量含義`是不同的,一個(gè)是有濃重的物品屬性特征的,一個(gè)是有協(xié)同特征的向量。但是都可以作為用戶的向量表示方式。
推薦系統(tǒng)
1)SparkML Pipline 訓(xùn)練模型通過PMML跨平臺(tái)部署時(shí)字符串轉(zhuǎn)向量的問題
由于我們通過Pipline訓(xùn)練出來的排序模型,模型的輸入是之前存入HBase中向量(用戶和物品)字符串,當(dāng)我們使用`jpmml-sparkml` 這個(gè)類庫(kù)去生成PMML模型,進(jìn)行擴(kuò)平臺(tái)部署時(shí),發(fā)現(xiàn)無法正常生成PMML。 原因是因?yàn)閷?duì)于字符串轉(zhuǎn)向量這種`transformer操作` jpmml沒有支持,我們參照jpmml源碼的實(shí)現(xiàn)方式,做了自定義transformer的實(shí)現(xiàn)。原理是先自定義一個(gè)Spark ML的transform,然后再擴(kuò)展一個(gè)jpmml對(duì)應(yīng)的converter即可。
2)特征向量Load到HBase慢的問題
我們構(gòu)建出來的用戶特征向量和物品特征向量,最終是存儲(chǔ)到HBase中的,最初是使用HBase API寫入數(shù)據(jù),但是太慢了,整個(gè)數(shù)據(jù)的寫入要耗費(fèi)5~6個(gè)小時(shí),之后我們`使用了bulkLoad的方式`,直接通過使用Spark生成將數(shù)據(jù)`生成HFile文件`寫入到HDFS,然后使用blukLoad直接生成好的HFile文件mv過去即可,15分鐘完成。 更具體點(diǎn),首先我們把我們將要寫入hbase的rdd,按照設(shè)定的行鍵排序,之后將行鍵和值構(gòu)造一個(gè)HFile的KeyValue結(jié)構(gòu),設(shè)定outputformat 為HFileOutputFormat2,將生成的hfile數(shù)據(jù)寫入到hdfs,之后通過doBulkLoad方法將寫到HDFS上hfile數(shù)據(jù)移動(dòng)到hbase目錄中。(這些項(xiàng)目的代碼中都有)
3)多路召回結(jié)果如何如何統(tǒng)一排序的問題
因?yàn)槲覀儾捎昧硕喾N召回算法,比如ItemCF,ALS, 基于熱門,基于地域 等召回算法。 沒有召回算發(fā)的結(jié)果集我們是無法直接排序的,因?yàn)楦鱾€(gè)召回算法表達(dá)的含義是不同的,最開始不知道該怎么做,因此就是各個(gè)召回算法設(shè)定一個(gè)人為比例去取。 之后學(xué)習(xí)了解到可以加`一個(gè)排序模型`做這個(gè)事情,原理就是用戶向量和物品向量作為基礎(chǔ)特征,用戶是否點(diǎn)擊物品作為標(biāo)簽,訓(xùn)練一個(gè)排序模型(LR),只有將各路召回策略輸入排序模型重新排序即可。 # 注意如果你同時(shí)說1,3問題,注意順序
數(shù)倉(cāng)問題
1)Flink Watermark激增的問題
從這上面的我舉的例子,你應(yīng)該知道這種情況發(fā)生的原因,是因?yàn)槲覀兂槿∈录录苯訙p去延遲時(shí)間造成,解決方式就是我們?cè)俪槿atermark時(shí),判斷一下事件中的時(shí)間和上次watermark的時(shí)間,如果兩者時(shí)間相差很大,我們就不更新watermark或者將watermark加上一個(gè)小值就可以了,一般選擇不更新。
2)實(shí)時(shí)作業(yè)和離線作業(yè)的資源競(jìng)爭(zhēng)問題
因?yàn)槲覀兘y(tǒng)一用Yarn做資源調(diào)度,實(shí)時(shí)作業(yè)Flink(Spark Streaming)和離線作業(yè)會(huì)調(diào)度到同一個(gè)機(jī)器上,集群相對(duì)空閑時(shí)沒什么問題,但是當(dāng)集群負(fù)載較高時(shí),尤其是晚上大批離線任務(wù)啟動(dòng),就會(huì)造成我們實(shí)時(shí)作業(yè)的某些Container所在機(jī)器負(fù)載過高,同時(shí)我們實(shí)時(shí)作業(yè)中如果有重計(jì)算邏輯,F(xiàn)link計(jì)算不過來,背壓產(chǎn)生,Kafka消費(fèi)延遲,數(shù)據(jù)積壓。解決這個(gè)問題的方法是,YARN Label,給YARN管理的機(jī)器打上標(biāo)簽,離線和實(shí)時(shí)分開,提交作業(yè)時(shí)指定Lable。
3)實(shí)時(shí)作業(yè)調(diào)度集中的問題
問題產(chǎn)生的背景是,當(dāng)提交一個(gè)作業(yè)時(shí)(Flink,Spark),作業(yè)不大,YARN上申請(qǐng)10個(gè)Container,發(fā)現(xiàn)10個(gè)Container都調(diào)度到一個(gè)節(jié)點(diǎn)上,或者大部分調(diào)度到一個(gè)節(jié)點(diǎn)上,幾個(gè)調(diào)度到另一個(gè)節(jié)點(diǎn),資源分配傾斜。 這樣造成如果我的作業(yè)是一個(gè)重計(jì)算的作業(yè),10Container都在一個(gè)節(jié)點(diǎn)上,CPU load過高,計(jì)算延遲。 當(dāng)時(shí)出現(xiàn)這個(gè)問題,比較苦惱,不知道什么原因,也沒有search到解決方案,最后只能去看源碼了(我們用的是Fair調(diào)度器),發(fā)現(xiàn)Container的分配策略是在一個(gè)NodeManger心跳中盡可能多的分配Container,這是為了提升調(diào)度的吞吐,但是源碼中有參數(shù)可以控制,是否一個(gè)心跳允許分配多個(gè)Container,以及一次心跳最大分配多少個(gè)Container給當(dāng)前的NodeManager.這個(gè)參數(shù)Yarn已經(jīng)暴露給用戶了`yarn.scheduler.fair.assignmultiple` 默認(rèn)是true。`yarn.scheduler.fair.max.assign` 默認(rèn)是-1,就是無限制。 解決的方式是`yarn.scheduler.fair.max.assign` 設(shè)置為一個(gè)較小的值,比如2.
4.我們?cè)谶x擇如何存儲(chǔ)用戶標(biāo)簽時(shí),遇到了問題(標(biāo)簽查詢速度慢,并且構(gòu)建不夠靈活,標(biāo)簽更新和刪除比較麻煩),比如之前用HDFS或者ES存儲(chǔ),后來切換為ClikcHouse,并用BitMap存儲(chǔ),原因如下:
針對(duì)標(biāo)簽的表示形式,存儲(chǔ)方式有很多,結(jié)構(gòu)為`寬表,BitMap` 都可以,存儲(chǔ)選擇`HDFS,ES,ClickHouse 等` 也都可以,需要衡量的有兩點(diǎn):
1)標(biāo)簽構(gòu)建的靈活性和構(gòu)建速度
2)標(biāo)簽的查詢效率
`HDFS [Presot,Impala]:` 標(biāo)簽的增加,刪除,更新不友好, 一個(gè)小變動(dòng),要重寫整個(gè)`Parquet`,寫放大問題。 查詢效率還可以,但是不夠優(yōu)秀。 支持查詢并發(fā)較小。
`ES:`標(biāo)簽的構(gòu)建的寫入速度一般, 新增和修改標(biāo)簽需要對(duì)ES文檔結(jié)構(gòu)更新,ES的DSL語法不友好,有一定學(xué)習(xí)成本。查詢效率還算優(yōu)秀,同時(shí)支持高并發(fā)。 ES資源占用高,需要較好的硬件配置。
`ClickHouse[BitMap]` 標(biāo)簽可以并行構(gòu)建,查詢效率優(yōu)秀,標(biāo)簽的增加非常方便,標(biāo)簽的更新和刪除可以實(shí)現(xiàn),但是并不高效,并發(fā)查詢支持比Presto,Impala要好,但同樣不支持高并發(fā),能夠滿足大部分場(chǎng)景需求。
注意兩點(diǎn):
1. BitMap存儲(chǔ)的是用戶ID
2. BitMap使用了RoaringBitMap, 解決BitMap空間占用問題,不然1億這一個(gè)數(shù)也要占用11.9M空間`
5.如果我們直接將用戶的標(biāo)簽轉(zhuǎn)換為稀疏向量來存儲(chǔ),對(duì)于類別標(biāo)簽使用`one-hot`編碼,但這樣會(huì)出現(xiàn)維度爆炸的問題,向量過于稀疏,向量之間的余弦相似度計(jì)算結(jié)果基本沒有意義,根本無法實(shí)現(xiàn)用戶相似度的計(jì)算。所以就開始思考如何將用戶表示為轉(zhuǎn)換為稠密向量,經(jīng)過調(diào)研發(fā)現(xiàn),Word2Vec可以將詞轉(zhuǎn)換為稠密向量,同時(shí)借助Word2Vec思想,也可以將物品轉(zhuǎn)換為向量Item2Vec,比如將一個(gè)Session內(nèi),用戶購(gòu)買的物品或者點(diǎn)擊的物品列表,看成是一句話,每個(gè)物品看成是一個(gè)單詞,就可以借助Word2Vec的思想將物品轉(zhuǎn)換為稠密向量表示。(這里注意如果是文章,可以使用分詞,然后抽取關(guān)鍵詞,將詞通過Word2Vec轉(zhuǎn)換為向量的方式) ,我們?cè)賹⒂脩酎c(diǎn)擊或者購(gòu)買的物品列表中物品向量加和求平均,就可以得到用戶的稠密向量。后來發(fā)現(xiàn)通過ALS模型`矩陣分解`的方式也可以得到用戶的稠密向量,兩者`表達(dá)的用戶向量含義`是不同的,一個(gè)是有濃重的物品屬性特征的,一個(gè)是有協(xié)同特征的向量,但是都可以作為用戶的向量表示方式。
更多關(guān)于大數(shù)據(jù)培訓(xùn)的問題,歡迎咨詢千鋒教育在線名師,如果想要了解我們的師資、課程、項(xiàng)目實(shí)操的話可以點(diǎn)擊咨詢課程顧問,獲取試聽資格來試聽我們的課程,在線零距離接觸千鋒教育大咖名師,讓你輕松從入門到精通。