技术干货 | 基于 Doris 构建的小程序私域流量增长
作者:趙煜楊? 百度資深研發(fā)工程師? 負(fù)責(zé)手百小程序數(shù)據(jù)產(chǎn)品工程架構(gòu)
本次分享大綱如下:
小程序私域精細(xì)化運(yùn)營(yíng)能力介紹
用戶(hù)分層技術(shù)難點(diǎn)
用戶(hù)分層的架構(gòu)和解決方案
未來(lái)規(guī)劃
小程序目前使用百度云 Palo(Apache Doris 企業(yè)版)承載其精細(xì)化運(yùn)營(yíng)業(yè)務(wù)。
通過(guò)本文可以幫助大家了解在 Doris 中使用全局字典、BITMAP 等功能時(shí)遇到的問(wèn)題、解決思路和優(yōu)化方案。
1.1小程序私域精細(xì)化運(yùn)營(yíng)能力介紹
私域用戶(hù)價(jià)值不突出。比如,我是個(gè)目前有100萬(wàn)用戶(hù)的開(kāi)發(fā)者,想推一款奢侈品包包給用戶(hù)里面的高收入人群。但是我不知道這100萬(wàn)人中,有多少人是高收入人群,是很難將他們找出來(lái)的。
缺乏主動(dòng)觸達(dá)能力,也就是觸達(dá)通路比較少。
針對(duì)這兩個(gè)問(wèn)題,我們產(chǎn)品上提出了一個(gè)解決方案——分層運(yùn)營(yíng)。
分層運(yùn)營(yíng)分成兩部分,運(yùn)營(yíng)觸達(dá)和精細(xì)化人群。
如圖所示,從上往下看,比如我現(xiàn)在要推一個(gè)活動(dòng),運(yùn)營(yíng)同學(xué)會(huì)在消息、私信、卡券和小程序內(nèi)這四個(gè)通路中選擇一個(gè)進(jìn)行推送。選完通路之后,就要選擇人群。
精細(xì)化人群篩選是基于百度的大數(shù)據(jù)平臺(tái)提供的畫(huà)像數(shù)據(jù)和行為數(shù)據(jù)去篩選特定的人群。
整個(gè)流程完成之后,我們會(huì)提供一個(gè)觸達(dá)效果的分析(主要包括下發(fā)量,點(diǎn)展和到達(dá)分析等),和一個(gè)群體分析(對(duì)整個(gè)用戶(hù)群的更細(xì)致化的分析)。
從收益和價(jià)值上來(lái)看,對(duì)于開(kāi)發(fā)者:
-
合理利用私域流量,提升資源價(jià)值
-
促進(jìn)用戶(hù)活躍和轉(zhuǎn)換
對(duì)于整個(gè)生態(tài):
-
提高私域池利用率和活躍度
-
激活開(kāi)發(fā)者主動(dòng)經(jīng)營(yíng)意愿
-
促進(jìn)生態(tài)良性循環(huán)
以上主要講了整個(gè)產(chǎn)品的方案,下面講一下具體的功能。
1.2?分層運(yùn)營(yíng)——B端視角
作為開(kāi)發(fā)者,我要如何去創(chuàng)建用戶(hù)分分層?
入口在小程序開(kāi)發(fā)者后臺(tái)——運(yùn)營(yíng)中心——分層運(yùn)營(yíng)——分層管理——自定義篩選。點(diǎn)擊自定義篩選后會(huì)進(jìn)入自定義篩選頁(yè)面,在這個(gè)頁(yè)面用戶(hù)可以選擇關(guān)注行為、卡券行為、交易行為等維度。選擇完成之后,可以使用“預(yù)估人數(shù)”功能,實(shí)時(shí)計(jì)算一下圈選的人群人數(shù)有多少,如果覺(jué)得所選的人群人數(shù)比較合適就點(diǎn)擊“生成人群”。生成人群之后將會(huì)進(jìn)入分層管理列表,在這里可以發(fā)送消息或私信,還可以進(jìn)行群體分析。
1.3?分層運(yùn)營(yíng)——C端視角
下圖是從C端視角來(lái)分層運(yùn)營(yíng)的功能,這里截取了百度App的通知和私信的樣式。
1.4?分層運(yùn)營(yíng)經(jīng)典案例
百度App在跟汽車(chē)大師合作的時(shí)候,汽車(chē)大師選擇近一周付費(fèi)且活躍用戶(hù)開(kāi)展“評(píng)價(jià)送券”活動(dòng)。
如圖所示,使用場(chǎng)景是在百度App中向用戶(hù)推送一個(gè)通知,用戶(hù)在“我的”里面打開(kāi),填寫(xiě)評(píng)價(jià)之后可以領(lǐng)券。?
這次活動(dòng)的效果是:
-
準(zhǔn)確判斷用戶(hù)需求,活躍用戶(hù)具有較高價(jià)值,頁(yè)面打開(kāi)率達(dá)9.51%
-
用戶(hù)次均使用時(shí)長(zhǎng)提升2.5倍
-
活動(dòng)帶來(lái)新增付費(fèi)轉(zhuǎn)化率達(dá)17.71%?
這里面有幾個(gè)運(yùn)營(yíng)技巧:
-
結(jié)合實(shí)際業(yè)務(wù)場(chǎng)景,無(wú)中間頁(yè)跳轉(zhuǎn)折損
-
拼接消息組件,自動(dòng)發(fā)券場(chǎng)景過(guò)渡順滑
-
場(chǎng)景可定期復(fù)用,節(jié)省人力成本。也就是創(chuàng)建完人群之后,可以一直使用這個(gè)人群。
-
“分享+使用”雙按鈕強(qiáng)勢(shì)引導(dǎo)
從上面分享給大家的案例可以看出,私域流量的用戶(hù)分層運(yùn)營(yíng)其實(shí)可以給開(kāi)發(fā)者帶來(lái)運(yùn)營(yíng)效率和轉(zhuǎn)化效果的提升,進(jìn)而促進(jìn)用戶(hù)增長(zhǎng)。
但是實(shí)現(xiàn)起來(lái)有很大的技術(shù)難點(diǎn)。
2?用戶(hù)分層難點(diǎn)
難點(diǎn)主要有四個(gè):
首先,TB級(jí)數(shù)據(jù),數(shù)據(jù)量特別大。我們基于畫(huà)像和行為做用戶(hù)分層,每天的數(shù)據(jù)量大概有1T+。
第二,查詢(xún)的頻響要求極高,要求毫秒到秒級(jí)的響應(yīng)時(shí)間。比如剛剛提到的“預(yù)估人數(shù)”的功能,用戶(hù)在點(diǎn)擊之后,我們需要在毫秒到秒的時(shí)間內(nèi),從TB級(jí)的數(shù)據(jù)中計(jì)算這個(gè)選定的人群數(shù)量結(jié)果。
第三,計(jì)算復(fù)雜,需要?jiǎng)討B(tài)靜態(tài)組合查詢(xún)。很多維度的數(shù)據(jù)無(wú)法進(jìn)行預(yù)聚合,必須要實(shí)時(shí)計(jì)算明細(xì)數(shù)據(jù),所以計(jì)算是很復(fù)雜的,這點(diǎn)后面會(huì)詳細(xì)展開(kāi)。
第四,產(chǎn)出用戶(hù)包要求實(shí)效性高。
?
針對(duì)上面的四個(gè)難點(diǎn),我們的方法論如下:
難點(diǎn)1:?壓縮存儲(chǔ),降低查詢(xún)數(shù)量級(jí),選擇使用Bitmap存儲(chǔ)。無(wú)論目前市場(chǎng)上主流的OLAP引擎有多厲害,數(shù)據(jù)量越大,查詢(xún)速度就一定越慢,所以我們要降低存儲(chǔ)。
難點(diǎn)2、3:?我們調(diào)研了當(dāng)前開(kāi)源主流OLAP引擎ClickHouse, Doris, Druid等,最后選擇使用基于MPP架構(gòu)的OLAP引擎Doris。在性能上其實(shí)ClickHouse, Doris, Druid都差不多。但是Doris有幾個(gè)優(yōu)點(diǎn),第一,Doris兼容MySQL協(xié)議,學(xué)習(xí)成本非常低,基本上RD都會(huì)用。第二,Doris的運(yùn)維成本很低,基本上是自動(dòng)化運(yùn)維,所以我們最后選擇了Doris。
難點(diǎn)4:?我們調(diào)研對(duì)比了spark,Doris 性能,最終也是選擇使用基于MPP架構(gòu)的OLAP引擎Doris,這點(diǎn)在后面會(huì)詳細(xì)講。
3?用戶(hù)分層的架構(gòu)和解決方案
下面我將會(huì)從架構(gòu)和解決方案上講解上面這些難點(diǎn)是如何解決的。
3.1?分層運(yùn)營(yíng)架構(gòu)
首先介紹一下分層運(yùn)營(yíng)的架構(gòu),分為在線部分和離線部分。
在線部分分為四層,服務(wù)層、解析層、計(jì)算層和存儲(chǔ)層,還有一個(gè)調(diào)度平臺(tái)和一個(gè)監(jiān)控平臺(tái)。
服務(wù)層包含了權(quán)限控制(用戶(hù)權(quán)限和接口權(quán)限),分層管理(是對(duì)用戶(hù)篩選分層的增刪改查的管理),元數(shù)據(jù)管理(對(duì)頁(yè)面元素和ID Mapping的管理)和任務(wù)管理(對(duì)調(diào)度平臺(tái)任務(wù)的增刪改查的管理)
解析層主要是對(duì)DSL的解析。比如,用戶(hù)要在線預(yù)估人數(shù)。走到解析層時(shí),首先要進(jìn)行DSL解析。然后對(duì)DSL優(yōu)化,比如我想找到近7天活躍的用戶(hù)和近7天不活躍的用戶(hù)求一個(gè)交集,顯然結(jié)果是0,那么在優(yōu)化層被優(yōu)化掉,返還給用戶(hù)結(jié)果為0,不會(huì)再往下走到計(jì)算引擎。優(yōu)化之后會(huì)有DSL路由,這個(gè)路由的功能主要是判斷查詢(xún)的維度,路由到SQL模版進(jìn)行模版的拼接。
計(jì)算引擎層主要有Spark和Doris。Spark主要用來(lái)做離線任務(wù)的計(jì)算,Doris用來(lái)做實(shí)時(shí)計(jì)算。
存儲(chǔ)層有MySQL(用來(lái)存用戶(hù)分層的信息),Redis(主要用來(lái)緩存),Doris(存畫(huà)像數(shù)據(jù)和行為數(shù)據(jù))和afs(存產(chǎn)出的用戶(hù)包信息)。
調(diào)度平臺(tái)用來(lái)管理離線任務(wù)的調(diào)度,監(jiān)控平臺(tái)用來(lái)對(duì)整體服務(wù)穩(wěn)定性監(jiān)控。
離線部分主要是對(duì)需要的數(shù)據(jù)源,比如畫(huà)像、關(guān)注、行為等數(shù)據(jù)進(jìn)行ETL清洗,然后做一個(gè)全局字典,完成之后會(huì)寫(xiě)入Doris。
在產(chǎn)出用戶(hù)包之后,會(huì)分發(fā)給小程序B端和百度統(tǒng)計(jì)。小程序B端會(huì)將消息推送到這些用戶(hù)的手機(jī)端;百度統(tǒng)計(jì)會(huì)用這個(gè)用戶(hù)包做群體分析。?
以上就是整體的架構(gòu),圖中標(biāo)紅的部分是針對(duì)之前的難點(diǎn)做的重點(diǎn)改造,下面我將針對(duì)這幾個(gè)重點(diǎn)模塊,依次展開(kāi)講解。
3.1.1?全局字典
全局字典主要是用來(lái)解決難點(diǎn)一——數(shù)據(jù)量大,壓縮存儲(chǔ)的同時(shí)保證查詢(xún)性能。
這里大家可能會(huì)有疑問(wèn),既然用Bitmap存,為什么還需要全局字典?
因?yàn)镈oris 的bitmap功能基于RoaringBitmap實(shí)現(xiàn)的。因此當(dāng)用戶(hù)id 過(guò)于離散的時(shí)候,RoaringBitmap 底層存儲(chǔ)結(jié)構(gòu)用的是Array Container, 而沒(méi)有用到Bitmap Container。Array Container性能遠(yuǎn)遠(yuǎn)差于Bitmap Container,因此我們使用了全局字典將用戶(hù)id轉(zhuǎn)換成連續(xù)遞增id。
下面介紹一下全局字典的邏輯。
畫(huà)像、關(guān)注、行為等數(shù)據(jù)源經(jīng)過(guò)ETL處理之后會(huì)進(jìn)入Spark中。Spark首先會(huì)加載全局字典表,這張表主要用來(lái)維護(hù)用戶(hù)ID和自增ID的映射關(guān)系,會(huì)做一次全量的加載。加載完成后會(huì)判斷用戶(hù)ID是否在這個(gè)全量的字典表中,如果存在則直接將ETL之后的數(shù)據(jù)寫(xiě)入Doris,如果不存在則說(shuō)明這是個(gè)新用戶(hù),使用row_numebr()over產(chǎn)生一個(gè)自增ID與用戶(hù)ID做一次映射,映射完成后會(huì)寫(xiě)入這張表中,同時(shí)將ETL之后的數(shù)據(jù)寫(xiě)入Doris。
3.1.2 Doris
Doris之分桶策略
首先講一下分桶策略,分桶策略主要用來(lái)解決難點(diǎn)二——查詢(xún)頻響要求高。
之前做全局字典是要保證用戶(hù)的連續(xù)遞增,但我們發(fā)現(xiàn)做完全局字典之后Bitmap的查詢(xún)性能并沒(méi)有達(dá)到我們預(yù)期中的速度。后來(lái)我們發(fā)現(xiàn)Doris是一個(gè)分布式的集群,它會(huì)按照某些Key進(jìn)行分桶,也就是說(shuō)分桶之后用戶(hù)ID在桶內(nèi)又是離散的了。
如圖中的例子所示,原始數(shù)據(jù)userid是連續(xù)的,在按照appkey和channel進(jìn)行分桶之后,在桶內(nèi)的userid就不是連續(xù)的了。但是不連續(xù)的話,Bitmap的性能不能很好的發(fā)揮出來(lái)。?
那么在這種情況下如何保證桶內(nèi)的連續(xù)呢?
我們的方案如下:
首先我們?cè)诒碇性黾恿薶id的字段,并且讓Doris用hid進(jìn)行分桶。
hid有一個(gè)算法:
hid?=?V/(M/N),?取整V:?插件式全局字典生成的用戶(hù)ID對(duì)應(yīng)的整數(shù)M:預(yù)估的用戶(hù)總數(shù),后續(xù)不變N:數(shù)據(jù)庫(kù)中設(shè)定的分桶數(shù)如圖,用戶(hù)總數(shù)為6,M=6。分桶數(shù)為3,N=3。
這樣就將userid和hid做了對(duì)應(yīng),在用hid做分桶的時(shí)候,就可以保證桶內(nèi)的連續(xù)。
Doris之用戶(hù)畫(huà)像標(biāo)簽優(yōu)化
以上講到的全局字典和分桶策略是通用的策略,是在做Bitmap時(shí)必須要考慮到的。但是只考慮這兩點(diǎn)還不能達(dá)到性能的最優(yōu),還要結(jié)合實(shí)際的業(yè)務(wù)對(duì)業(yè)務(wù)進(jìn)行優(yōu)化。以下就是我們的具體業(yè)務(wù)——畫(huà)像標(biāo)簽的存儲(chǔ)優(yōu)化。
畫(huà)像標(biāo)簽優(yōu)化也是用來(lái)解決難點(diǎn)二——查詢(xún)頻響要求高。
當(dāng)時(shí)有兩個(gè)方案,方案一是用tag_type和tag_value。tag_value用來(lái)記錄標(biāo)簽的類(lèi)型,tag_value用來(lái)記錄標(biāo)簽的內(nèi)容。方案二是將所有標(biāo)簽放入一個(gè)寬表中。
我們選擇了方案二。因?yàn)榉桨敢皇且粋€(gè)標(biāo)簽對(duì)應(yīng)一個(gè)用戶(hù),如果我想選取“性別男”,地域在“北京”的用戶(hù),就需要把兩部分用戶(hù)做一個(gè)union,有一定的計(jì)算量,會(huì)更耗時(shí)。如果用方案二,可以根據(jù)用戶(hù)常用的查詢(xún),構(gòu)建對(duì)應(yīng)的物化視圖,這樣用戶(hù)查詢(xún)的時(shí)候,命中物化視圖,就可以直接取出結(jié)果,而不必去計(jì)算,可以減少耗時(shí)。
在使用Doris的時(shí)候,大家要盡量命中前綴索引和物化視圖,這樣會(huì)大大提升查詢(xún)效率。
Doris之動(dòng)靜組合查詢(xún)
動(dòng)靜組合查詢(xún)主要是解決難點(diǎn)三——計(jì)算復(fù)雜。
靜態(tài)查詢(xún)是用戶(hù)維度是固定的,可以進(jìn)行預(yù)聚合的。比如“男性用戶(hù)”,這就是一個(gè)固定的群體,無(wú)論怎么查這部分用戶(hù)是不會(huì)變的。動(dòng)態(tài)查詢(xún)是偏向一些行為的,會(huì)根據(jù)用戶(hù)的不同而不同。比如“近30天收藏超過(guò)3次的用戶(hù)”,或“近30天收藏超過(guò)4次的用戶(hù)”,這種查詢(xún)無(wú)法進(jìn)行預(yù)聚合,所以稱(chēng)為動(dòng)態(tài)的查詢(xún)。
?
小程序用戶(hù)分層相比于同類(lèi)型的用戶(hù)分層功能,增加了用戶(hù)行為篩選(這也是小程序產(chǎn)品的特點(diǎn)之一),比如近30天用戶(hù)支付訂單超過(guò)30元的男性,20~30歲用戶(hù)。其中近30天用戶(hù)支付訂單超過(guò)30元用戶(hù)是Bitmap表無(wú)法記錄的,也不能提前預(yù)計(jì)算好,只能在線去算。
這里的難點(diǎn)是,如何進(jìn)行非Bitmap表和Bitmap表的交并補(bǔ)集運(yùn)算?
結(jié)合上面的例子,我們的解決方法是將查詢(xún)查分成四步。
Step1?先查20-30歲的男性用戶(hù),這部分直接查Bitmap表就行。
Step2?查詢(xún)近30天用戶(hù)支付訂單超過(guò)30元用戶(hù),這步需要去查行為表獲取用戶(hù)ID。
Step3?將用戶(hù)ID跟在線Bitmap的轉(zhuǎn)化,Doris提供了一個(gè)bitmap_union(to_bitmap(id)) 功能,可以在線將用戶(hù)id 轉(zhuǎn)換成bitmap。
Step4?是將Step1和Step3的結(jié)果求交集。?
這里的重點(diǎn)是Step3,Doris提供了to_bitmap的功能,幫我們解決了Bitmap表和非Bitmap表的聯(lián)合查詢(xún)的問(wèn)題。
3.1.3?如何快速產(chǎn)出用戶(hù)包
快速產(chǎn)出用戶(hù)包是為了解決難點(diǎn)四——產(chǎn)出用戶(hù)包要求時(shí)效性高。
同樣有兩個(gè)方案,方案一是用調(diào)度平臺(tái)+Spark。分成三步,首先產(chǎn)出分層用戶(hù)cuid,然后產(chǎn)出用戶(hù)uid,最后回調(diào)更新。方案二是用調(diào)度平臺(tái)+solo,執(zhí)行DAG圖是用solo產(chǎn)出cuid、uid和回調(diào),這里的solo是百度云提供的Pingo單機(jī)執(zhí)行引擎,類(lèi)似一個(gè)虛擬機(jī)。
方案一由于spark自身yarn調(diào)度耗時(shí),加上如何隊(duì)列資源緊張需要延遲等待等原因,即使產(chǎn)出0個(gè)用戶(hù),也需要30分鐘才能跑完。方案二我們利用了Doris的SELECT INTO OUTFILE產(chǎn)出結(jié)果導(dǎo)出功能:查出的用戶(hù)直接導(dǎo)出到afs上,百萬(wàn)級(jí)用戶(hù)產(chǎn)出小于3分鐘。
最終我們選擇了方案二,因?yàn)镈oris相比于spark導(dǎo)出結(jié)果到afs更快。
3.2?收益
Doris的用戶(hù)存儲(chǔ)方案還是非常有效的,整體方案的收益如下圖所示:
4 未來(lái)規(guī)劃
首先在產(chǎn)品上:
豐富分層應(yīng)用場(chǎng)景, 拓展強(qiáng)關(guān)系維度, 豐富觸達(dá)形式
探索分層和商業(yè)的結(jié)合模式
在技術(shù)上:
時(shí)效性:交易,訂單, 關(guān)注等行為實(shí)時(shí)化
豐富性:? 接入更多的用戶(hù)畫(huà)像標(biāo)簽及行為
通用性:? 全局字典插件化, 通用到各個(gè)業(yè)務(wù)
期待你的加入
百度開(kāi)發(fā)者中心已開(kāi)啟征稿模式,歡迎開(kāi)發(fā)者登錄developer.baidu.com進(jìn)行投稿,優(yōu)質(zhì)文章將獲得豐厚獎(jiǎng)勵(lì)和推廣資源。
總結(jié)
以上是生活随笔為你收集整理的技术干货 | 基于 Doris 构建的小程序私域流量增长的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 百度单测生成技术如何召回线上服务的异常问
- 下一篇: BML CodeLab重磅更新:在Win