百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

趙煜楊

百度 | 資深研發(fā)工程師

負(fù)責(zé)手百小程序數(shù)據(jù)產(chǎn)品的工程架構(gòu)工作,從0到1主持設(shè)計(jì)了精細(xì)化用戶(hù)分層系統(tǒng),實(shí)現(xiàn)了百億級(jí)TB量級(jí)小程序用戶(hù)畫(huà)像、行為數(shù)據(jù)秒級(jí)預(yù)估,保障了小程序私域運(yùn)營(yíng)的落地。具有超過(guò)6年在高可用、大數(shù)據(jù)方向的工作經(jīng)驗(yàn),一直專(zhuān)注在數(shù)據(jù)工程架構(gòu)、個(gè)性化推薦工程等工作上,對(duì)技術(shù)團(tuán)隊(duì)管理也比較有經(jīng)驗(yàn),目前個(gè)人專(zhuān)注于大數(shù)據(jù)、個(gè)性化推薦、高可用架構(gòu)等技術(shù)方向。

本文的主題為基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐,將從實(shí)際案例出發(fā)介紹基于 Doris 用戶(hù)分層解決方案,重點(diǎn)分享了項(xiàng)目中的難點(diǎn)和架構(gòu)解決方案,以及怎么使用 Doris做用戶(hù)分層,如何做到秒級(jí)的人數(shù)預(yù)估和快速產(chǎn)出用戶(hù)包。主要內(nèi)容包括:

  • 小程序私域精細(xì)化運(yùn)營(yíng)能力介紹
  • 用戶(hù)分層技術(shù)難點(diǎn)
  • 用戶(hù)分層的架構(gòu)和解決方案
  • 未來(lái)規(guī)劃

01小程序私域精細(xì)化運(yùn)營(yíng)能力介紹

好,現(xiàn)在開(kāi)始。現(xiàn)在首先介紹一下我們小程序當(dāng)前的私域精細(xì)化運(yùn)營(yíng)的能力有哪些。

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

首先我們?yōu)樯兑鏊加蚓?xì)化運(yùn)營(yíng)呢,這起源于兩個(gè)痛點(diǎn):

  • 私域用戶(hù)的價(jià)值不突出比如:我有100萬(wàn)個(gè)用戶(hù),我想給高收入人群去推薦奢侈品的包包,但是我不知道在這100萬(wàn)人里面有多少人是這種高收入人群
  • 缺乏主動(dòng)觸達(dá)的能力

然后針對(duì)這兩個(gè)問(wèn)題,我們產(chǎn)品上面提出了一個(gè)解決方案 — 就是分層運(yùn)營(yíng),它主要分為兩部分:一個(gè)是運(yùn)營(yíng)觸達(dá),還有一個(gè)是精細(xì)化的人群。

舉個(gè)例子:如圖示,從上往下看:當(dāng)運(yùn)營(yíng)想搞一個(gè)活動(dòng)時(shí)(比如 DataFun Talk 這個(gè)活動(dòng)),可以選擇消息、私信、卡券、小程序內(nèi)這四個(gè)通路中的一個(gè)進(jìn)行推送,選完通路之后,就需要選擇需要推送的人群,這時(shí)候就要用到精細(xì)化人群,精細(xì)化人群是基于百度大數(shù)據(jù)平臺(tái)提供的畫(huà)像數(shù)據(jù)、新聞數(shù)據(jù)生成的,最后根據(jù)選擇人群、推送通路完成推送。之后我們還會(huì)提供觸達(dá)效果的分析,主要包括下發(fā)量、點(diǎn)展、到達(dá)之類(lèi)的,另外針對(duì)人群也會(huì)提供整個(gè)用戶(hù)群體更細(xì)致化的分析。

這套解決方案的收益和價(jià)值:

對(duì)于開(kāi)發(fā)者來(lái)說(shuō):

  • 合理地利用私域流量提升價(jià)值
  • 促進(jìn)用戶(hù)活躍和轉(zhuǎn)化

對(duì)于整個(gè)生態(tài)來(lái)講:

  • 提高了私欲利用率和活躍度
  • 激活了開(kāi)發(fā)者主動(dòng)經(jīng)營(yíng)的意愿
  • 促進(jìn)了生態(tài)的良性循環(huán)

以上講的是一個(gè)產(chǎn)品的方案,接下來(lái)跟大家講一下具體的功能

1. 分層運(yùn)營(yíng)-B端視角

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

首先介紹下 B 端視角下分層運(yùn)營(yíng)平臺(tái)是如何工作的,比如說(shuō)我是開(kāi)發(fā)者,我是怎么去做去創(chuàng)建用戶(hù)分層的。

這里我們提供了自定義配置篩選的功能,可以從用戶(hù)關(guān)注、卡券、交易、活躍行為、性別、年齡等多種維度選擇,同時(shí)提供了預(yù)估人數(shù)的功能,可以實(shí)時(shí)的算出來(lái)你當(dāng)前圈選的用戶(hù)有多少人,方便評(píng)估一下人數(shù)是否 OK,如果 OK 的話(huà),就直接生成人群,如果不 OK 的話(huà),就重新選擇篩選條件。

完成人群篩選之后,會(huì)進(jìn)入分層管理列表,在列表里面可以根據(jù)需要點(diǎn)擊對(duì)應(yīng)的推送按鈕就可以直接推送,推送方式包括私信、群發(fā)。當(dāng)然了,這里也有群體分析功能。

B 端功能入口:

小程序開(kāi)發(fā)者后臺(tái) -> 運(yùn)營(yíng)中心 -> 分層運(yùn)營(yíng) -> 分層管理 -> 自定義篩選

2. 分層運(yùn)營(yíng)-C端視角

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

簡(jiǎn)單展示下 C 端視角下分層運(yùn)營(yíng)的一個(gè)樣式:如圖截取的是百度APP 上通知和私信的樣式。

02用戶(hù)分層技術(shù)難點(diǎn)

1. 分層運(yùn)營(yíng)經(jīng)典案例

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

下面給大家介紹分層運(yùn)營(yíng)的一個(gè)經(jīng)典的案例 — 我們跟汽車(chē)大師的合作案例:

需求是汽車(chē)大師要對(duì)近一周付費(fèi)且活躍的用戶(hù)進(jìn)行一個(gè)評(píng)價(jià)送券的活動(dòng)。圖中截圖展示了這個(gè)活動(dòng)的交互過(guò)程:汽車(chē)大師推送一個(gè)通知(圖中:8/6日通知),然后用戶(hù)在《 百度APP -> 我的 -> 通知 》里面就可以看到汽車(chē)大師的通知消息,點(diǎn)開(kāi)之后跳轉(zhuǎn)到《咨詢(xún)待評(píng)價(jià)頁(yè)面》,然后寫(xiě)完評(píng)價(jià)后系統(tǒng)會(huì)自動(dòng)發(fā)券并通知給用戶(hù);在這個(gè)活動(dòng)中達(dá)成的效果如下:

  • 準(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%

簡(jiǎn)單介紹下一些這里面的基本運(yùn)營(yíng)技巧:

  • 結(jié)合和實(shí)際的業(yè)務(wù)場(chǎng)景,無(wú)中間頁(yè)跳轉(zhuǎn)的折損
  • 拼接消息組件,自動(dòng)發(fā)券場(chǎng)景過(guò)度順轉(zhuǎn)
  • 場(chǎng)景可定期復(fù)用,節(jié)省人力成本。創(chuàng)建完人群之后,可以一直使用,不需要重復(fù)創(chuàng)建
  • “分享和使用” 雙按鈕強(qiáng)強(qiáng)勢(shì)引導(dǎo)

上面的分享主要是讓大家了解用戶(hù)分層運(yùn)營(yíng)給開(kāi)發(fā)者帶來(lái)運(yùn)營(yíng)效率以及轉(zhuǎn)化效果的一個(gè)提升,從而促進(jìn)用戶(hù)增長(zhǎng)。這種看起來(lái)是特別的香,對(duì)不對(duì) ?但是它有沒(méi)有什么技術(shù)難點(diǎn),答案是當(dāng)然有,而且還特別大,不過(guò)沒(méi)關(guān)系,大家不用擔(dān)心了,你們認(rèn)真聽(tīng)完煜楊老師接下來(lái)的分享這些難點(diǎn)就會(huì)變得很 Easy了,用之前一句特別流行的廣告語(yǔ)就是:媽媽再也不用擔(dān)心我的工作了。

2. 分層運(yùn)營(yíng)難點(diǎn)

難點(diǎn)的話(huà),大家可以看下圖,可以看到我把難點(diǎn)跟方法論都放到了一起,其實(shí)最開(kāi)始我是想先講難點(diǎn),然后后面再講方法論的,這樣的話(huà)就可以調(diào)一下大家的胃口??。后來(lái)我又一想,大家都是程序員對(duì)不對(duì),既如此,程序員何苦為難程序員,還是少一些套路,多一些真誠(chéng)比較好。所以最后,我就把難點(diǎn)跟方法論都放到一起了,這樣可以給大家一個(gè)直觀(guān)的一個(gè)認(rèn)識(shí)。

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

首先給大家簡(jiǎn)單介紹遇到的四個(gè)難點(diǎn):

  • TB級(jí)數(shù)據(jù)。數(shù)據(jù)量特別大,前面講到我們是基于畫(huà)像和行為去做的一個(gè)用戶(hù)分層,數(shù)據(jù)量是特別大的,每天的數(shù)據(jù)量規(guī)模是 1T +
  • 查詢(xún)的頻響要求極高,毫秒級(jí)到秒級(jí)的一個(gè)要求。前面介紹 B 端視角功能時(shí)大家有看到,我們有一個(gè)預(yù)估人數(shù)的功能,用戶(hù)只要點(diǎn)擊 ”預(yù)估人數(shù)“ 按鈕,我們就需要從 TB 級(jí)的數(shù)據(jù)量級(jí)里面計(jì)算出篩選出的人群人數(shù)是多少,這種要在秒級(jí)時(shí)間計(jì)算 TB 級(jí)的數(shù)量的一個(gè)結(jié)果的難度其實(shí)可想而知
  • 計(jì)算復(fù)雜,需要?jiǎng)屿o組合。怎么理解?就是現(xiàn)在很多維度我們是沒(méi)辦法去做預(yù)聚合的,必須去存明細(xì)數(shù)據(jù),然后去實(shí)時(shí)的計(jì)算,這個(gè)后面也會(huì)細(xì)講
  • 產(chǎn)出用戶(hù)包的時(shí)效性要求高。這個(gè)比較好理解,如果產(chǎn)出特別慢的話(huà),肯定會(huì)影響用戶(hù)體驗(yàn)

針對(duì)上面的四個(gè)難點(diǎn),我們的解法是:

針對(duì)第一個(gè)難點(diǎn) –> 壓縮存儲(chǔ),降低查詢(xún)的數(shù)量級(jí)。

具體選型就是使用 Bitmap 存儲(chǔ),這解法其實(shí)很好理解,不管現(xiàn)在主流的 OLAP引 擎有多么厲害,數(shù)據(jù)量越大,查詢(xún)肯定會(huì)越慢,不可能說(shuō)數(shù)據(jù)量越大,我查詢(xún)還是一直不變的,這種其實(shí)不存在的,所以我們就需要降低存儲(chǔ)。

針對(duì)第二和第三個(gè)難點(diǎn) –> 選擇合適計(jì)算引擎

我們調(diào)研了當(dāng)前開(kāi)源的包括 ClickHouse, Doris, Druid 等多種引擎,最終選擇了基于 MPP 架構(gòu)的OLAP引擎 Doris。

這里可以簡(jiǎn)單跟大家介紹一下選擇 Doris 的原因,從性能來(lái)說(shuō)其實(shí)都差不多,但是都 Doris 有幾個(gè)優(yōu)點(diǎn):

  • 第一:它是兼容 Mysql 協(xié)議,也就是說(shuō)你的學(xué)習(xí)成本非常低,基本上大家只要了解mysql, 就會(huì)用Doris, 不需要很大的學(xué)習(xí)成本。
  • 第二:Doris 運(yùn)維成本很低,基本上就是自動(dòng)化運(yùn)維。

針對(duì)第四個(gè)難點(diǎn) –>  選擇合適的引擎

通過(guò)對(duì)比 Spark 和 Doris,我們選擇了 Doris ,后面會(huì)詳細(xì)講為什么會(huì)用 Doris。

03用戶(hù)分層的架構(gòu)和解決方案

介紹難點(diǎn)以及解法之后,接下來(lái)從架構(gòu)跟解決方案里面跟大家細(xì)講一下,難點(diǎn)是怎么解決的。

分層運(yùn)營(yíng)架構(gòu):

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

首先介紹一下我們分層運(yùn)營(yíng)的架構(gòu)。架構(gòu)的話(huà)分為兩部分,就是在線(xiàn)部分跟離線(xiàn)部分。

在線(xiàn)部分:

分為了四層:服務(wù)層、解析層、計(jì)算層跟存儲(chǔ)層,然后還有調(diào)度平臺(tái)和監(jiān)控平臺(tái)。

服務(wù)層,主要功能包含:

  • 權(quán)限控制:主要是戶(hù)權(quán)限、接口權(quán)限的控制
  • 分層管理:主要是是對(duì)用戶(hù)篩選的增刪改查
  • 元數(shù)據(jù)管理:主要是對(duì)頁(yè)面元素、ID-Mapping 這類(lèi)數(shù)據(jù)的管理
  • 任務(wù)管理:主要是支持調(diào)度平臺(tái)任務(wù)的增刪改查

解析層,是對(duì)DSL的一個(gè)解析、優(yōu)化、路由以及Sql模板:

比如要查在線(xiàn)預(yù)估人數(shù),首先會(huì)在解析層做一個(gè) DSL 的解析,之后根據(jù)不同情景做 DSL 的優(yōu)化,比如選擇了近七天活躍且近七天不活躍的用戶(hù),這種要七天活躍和七天不活躍的交集顯然就是零了,對(duì)不對(duì)?像這樣情況在優(yōu)化層直接將結(jié)果 0 返回給用戶(hù)就不會(huì)再往下走計(jì)算引擎,類(lèi)似還有很多其他優(yōu)化場(chǎng)景。然后優(yōu)化完之后會(huì)使用 DSL 路由功能,根據(jù)不同查詢(xún)路由到不同的 Sql 模板進(jìn)行模板的拼接。

計(jì)算層,計(jì)算引擎我們使用 Spark 和 Doris:

  • Spark:離線(xiàn)任務(wù)
  • Doris:實(shí)時(shí)任務(wù)

存儲(chǔ)層:

  • Mysql:主要用來(lái)存用戶(hù)分層的一些用戶(hù)信息
  • Redis:主要用作緩存
  • Doris:主要存儲(chǔ)畫(huà)像數(shù)據(jù)和行為數(shù)據(jù)
  • AFS:主要是存儲(chǔ)產(chǎn)出的用戶(hù)包的一些信息

調(diào)度平臺(tái):

  • 主要是離線(xiàn)任務(wù)的調(diào)度

監(jiān)控平臺(tái):

  • 整個(gè)服務(wù)穩(wěn)定性的監(jiān)控

離線(xiàn)部分:

離線(xiàn)部分的話(huà)主要是對(duì)需要的數(shù)據(jù)源(比如說(shuō)畫(huà)像、關(guān)注、行為等數(shù)據(jù)源)做 ETL 清洗,清洗完之后會(huì)做一個(gè)全局字典并寫(xiě)入 Doris。任務(wù)最終會(huì)產(chǎn)出用戶(hù)包,并會(huì)分發(fā)給小程序 B 端跟百度統(tǒng)計(jì):

  • 小程序 B 端:推送給手機(jī)端用戶(hù)
  • 百度統(tǒng)計(jì):拿這些用戶(hù)包做一次群體分析

以上就是一個(gè)整體的架構(gòu)。

圖中大家可以看到有幾個(gè)標(biāo)紅的地方,同時(shí)也用數(shù)字 1、2、3 做了標(biāo)記,這幾個(gè)標(biāo)紅是重點(diǎn)模塊,就是針對(duì)于上面提到的四個(gè)難點(diǎn)做的重點(diǎn)模塊改造,接下來(lái)會(huì)針對(duì)這三個(gè)重點(diǎn)模塊一一展開(kāi)進(jìn)行講解。

1. 全局字典

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

首先講解全局字典這個(gè)模塊,全局字典的目的主要是為了解決難點(diǎn)一:數(shù)據(jù)量大,需要壓縮存儲(chǔ)同時(shí)壓縮存儲(chǔ)之后還要保證查詢(xún)性能。

為啥要用全局字典:

這里大家可能會(huì)有一個(gè)疑問(wèn),就是說(shuō)我用 BitMap 存儲(chǔ)為啥還要做全局字典?這個(gè)主要是因?yàn)?Doris 的 BitMap 功能是基于  RoaringBitmap 實(shí)現(xiàn)的,因此假如說(shuō)用戶(hù) ID 過(guò)于離散的時(shí)候,RoaringBitmap 底層存儲(chǔ)結(jié)構(gòu)用的是 Array Container 而不是 BitMap Container,Array Container 性能遠(yuǎn)遠(yuǎn)差于 BitMap Container。因此我們要使用全局字典將用戶(hù) ID 映射成連續(xù)遞增的 ID,這就是使用全局字典的目的。

全局字典的更新邏輯概況:

這里是使用 Spark 程序來(lái)實(shí)現(xiàn)的,首先加載經(jīng)過(guò) ETL 清洗之后各個(gè)數(shù)據(jù)源(畫(huà)像、關(guān)注、行為這些數(shù)據(jù)源)和全局字典歷史表(用來(lái)維護(hù)維護(hù)用戶(hù) ID 跟自增 ID 映射關(guān)系),加載完之后會(huì)判斷 ETL 里面的用戶(hù)ID 是否已經(jīng)存在字典表里面,如果有的話(huà),就直接把 ETL 的數(shù)據(jù)寫(xiě)回 Doris 就行了,如果沒(méi)有就說(shuō)明這是一個(gè)新用戶(hù),然后會(huì)用 row_number 方法生成一個(gè)自增 ID ,跟這個(gè)新用戶(hù)做一次映射,映射完之后更新到全局字典并寫(xiě)入 Doris。

2. Doris

接下來(lái)介紹第二個(gè)重點(diǎn)模塊 Doris。

2.1 Doris 分桶策略

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

分桶策略的目的是為了解決難點(diǎn)二:查詢(xún)頻響要求高。

為啥要做分桶策略:

我們之前使用了全局字典保證用戶(hù)的連續(xù)遞增,但是我們發(fā)現(xiàn)用了全局字典之后,BitMap 的查詢(xún)性能其實(shí)并沒(méi)有達(dá)到我們預(yù)期的那樣絲滑般柔順的感覺(jué),哈哈哈。。。對(duì),還是特別慢,然后我們就特別郁悶了,開(kāi)始懷疑 BitMap 并不像傳說(shuō)中的那么快,難道童話(huà)都是騙人的嗎?我們就在想怎么解決這個(gè)問(wèn)題,后來(lái)我們發(fā)現(xiàn) Doris 其實(shí)是分布式的一個(gè)集群,它會(huì)按照某些 Key 進(jìn)行分桶,也就是分桶之后用戶(hù)ID 在桶內(nèi)就不連續(xù),又變成零散的了。

舉個(gè)例子,如圖中左側(cè)原始數(shù)據(jù),可以看到 appkey 有A1、A2,channel 有C1、C2、C3,然后 userid 是0、1、2、3、4、5 六個(gè)連續(xù)的 userid 。我們按照 appkey 和 channel 進(jìn)行分桶,這樣的話(huà)分完桶之后的結(jié)果就是右邊這張圖:桶一 key 是A1、C1,userid 就是0、2;桶二 key 是 A1、C2,userid 就是 1、4;桶三 key 是A2、C3,userid 是3、5;大家能比較直觀(guān)地看到在桶中 userid 已經(jīng)不連續(xù)了,不連續(xù)的話(huà),BitMap  的性能就沒(méi)法發(fā)揮出來(lái)的,它會(huì)走 Array Container 去存儲(chǔ),它的性能會(huì)比較差。

解決方式:

這里,其實(shí)我想問(wèn)一下大家,這種怎么去保證桶內(nèi)的連續(xù)?大家如果有想法,可以私下一起討論下,現(xiàn)在大家不要給自己加戲啊, 今天的star是我啊, 大家要focus on me 身上啊。開(kāi)個(gè)玩笑啊, 活躍下直播間氣氛。

接下來(lái)我會(huì)跟大家分享一下我們的一個(gè)方案,對(duì)了,給大家五秒鐘的時(shí)間,大家可以現(xiàn)在記筆記了,真的,這個(gè)方案是我們經(jīng)歷了無(wú)數(shù)個(gè)日日夜夜跟無(wú)數(shù)根頭發(fā)總結(jié)出來(lái)的,非常有實(shí)戰(zhàn)意義。

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

好,現(xiàn)在講一下我們的方案,我們的方案是在表里面增加了一個(gè) hid 的字段,然后讓 Doris 按照 hid 字段進(jìn)行分桶,這里 hid 生成算法是:

hid  = V/(M/N) 然后取整

其中:

  • V:全局字典的用戶(hù)ID 對(duì)應(yīng)的整數(shù)
  • M:預(yù)估的用戶(hù)總數(shù)
  • N:分層數(shù)

還是結(jié)合上面的例子,大家可以看一下:userid 是六個(gè)即 0~5,所以 M= 6;分為三個(gè)桶,N = 3;因此 M 除以 N 就等于二。這樣的話(huà)我就要用 userid 去除以二,然后取整作為 hid??梢钥匆幌?,比如說(shuō) userid  是零,0÷2 取整為 0 ,userid 是一的話(huà),hid 還是這樣,因?yàn)?1÷2 的整數(shù)部分是零;同理 2÷2 、3÷2 是一,4÷2、5÷2 是二,這樣的話(huà)就把 userid 跟 hid 做對(duì)應(yīng),然后再根據(jù) hid 做分層。大家可以看到分層結(jié)果,hid = 0 時(shí) userid 是0、1,hid = 1 時(shí) userid 是2、3,hid = 2時(shí) userid 是 4、5,這樣就保證了桶內(nèi)連續(xù)。

2.2 doris之用戶(hù)畫(huà)像標(biāo)簽優(yōu)化

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

前面給大家講了分桶與全局字典這兩個(gè)通用的策略,就是說(shuō)大家要做 BitMap 的話(huà),這兩個(gè)東西肯定是要考慮的,但是只考慮這兩個(gè)東西,還并不能說(shuō)達(dá)到性能的最優(yōu),還要結(jié)合自己的實(shí)際業(yè)務(wù)去做針對(duì)性的優(yōu)化,這樣才能達(dá)到一個(gè)性能的最優(yōu),接下來(lái)我會(huì)給大家介紹我們的具體業(yè)務(wù)優(yōu)化:畫(huà)像標(biāo)簽的優(yōu)化。

畫(huà)像標(biāo)簽優(yōu)化解決的難點(diǎn)也是難點(diǎn)二:查詢(xún)頻響要求高。這個(gè)問(wèn)題當(dāng)時(shí)是有兩個(gè)方案。

方案一:

tag_type, tag_value 。tag_type 是用來(lái)記錄標(biāo)簽的類(lèi)型,tag_value  是用來(lái)記錄標(biāo)簽的內(nèi)容。

如圖所示:比如說(shuō) tag_type  是性別,tag_value  可能是男或女,bitmap 這里就是存儲(chǔ)所有性別是男的用戶(hù) id 列表。

同樣對(duì)于 tag_type 是地域、tag_value   是北京,bitmap 存儲(chǔ)的是所有地域在北京的用戶(hù) id 列表。

方案二:

大寬表,使用大寬表在一行記錄了所有的標(biāo)簽,然后使用 bitmap 記錄這個(gè)標(biāo)簽的用戶(hù) id 列表。

最終我們選擇了方案二,為什么沒(méi)有選方案一呢 ?因?yàn)榉桨敢凰且粋€(gè)標(biāo)簽對(duì)應(yīng)一個(gè)用戶(hù) bitmap,當(dāng)我想查一個(gè)聯(lián)合的結(jié)果就比較耗時(shí),比如我想查詢(xún)性別是男且區(qū)域是北京的所有用戶(hù),這樣的話(huà)我需要取出 “男” 的用戶(hù)和 “北京“ 的用戶(hù),兩者之間做一個(gè)交集,對(duì)吧?這種的話(huà)肯定會(huì)有計(jì)算量會(huì)有更多的時(shí)間消耗,但是如果用大寬表去做存儲(chǔ)的話(huà),就可以根據(jù)用戶(hù)常用的查詢(xún)?nèi)?gòu)建一個(gè)物化視圖,當(dāng)用戶(hù)的查詢(xún)(比如在北京的男性)命中了物化視圖,就可以直接去取結(jié)果,而不用再去做計(jì)算,從而降低耗時(shí)。

這里還有一個(gè)知識(shí)點(diǎn)跟大家分享一下:在使用 Doris 的時(shí)候,一定要盡量去命中它的前綴索引跟物化視圖,這樣會(huì)大大的提升查詢(xún)效率。

2.3 doris之動(dòng)靜組合查詢(xún)

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

好,用戶(hù)標(biāo)簽講完之后繼續(xù)講下一個(gè)難點(diǎn)的解決方案:動(dòng)靜組合查詢(xún),對(duì)應(yīng)的難點(diǎn)是難點(diǎn)三:計(jì)算復(fù)雜。

首先介紹一下什么叫動(dòng)靜組合查詢(xún):

  • 靜態(tài)查詢(xún):我們定義為用戶(hù)維度是固定的,就是可以進(jìn)行預(yù)聚合的查詢(xún)?yōu)殪o態(tài)查詢(xún)。比如說(shuō)男性用戶(hù),男性用戶(hù)個(gè)就是一個(gè)固定的群體,不管怎么查用戶(hù)肯定不會(huì)變,就可以提前進(jìn)行預(yù)聚合的。
  • 動(dòng)態(tài)查詢(xún):主要偏向于一些行為,就是那種查詢(xún)跟著用戶(hù)的不同而不同。比如說(shuō)查近30天收藏超過(guò)三次的用戶(hù),或者還有可能是近30天收藏超過(guò)四次的用戶(hù),這種的話(huà)就很隨意,用戶(hù)可能會(huì)查詢(xún)的維度會(huì)特別的多,而且也沒(méi)法沒(méi)辦法進(jìn)行一個(gè)預(yù)聚合,所以我們稱(chēng)之為動(dòng)態(tài)的一個(gè)查詢(xún)。

然后小程序用戶(hù)分層,相比于同類(lèi)型的用戶(hù)分層功能增加了用戶(hù)行為篩選,這也是小程序產(chǎn)品的特點(diǎn)之一。比如說(shuō)我們可以查近 30 天用戶(hù)支付訂單超過(guò) 30元的男性, 這種 ”近 30天用戶(hù)支付訂單超過(guò) 30元“ 的查詢(xún)是沒(méi)辦法用 bitmap 做記錄的,也沒(méi)辦法說(shuō)提前計(jì)算好,只能在線(xiàn)去算。這種就是一個(gè)難點(diǎn),就是說(shuō)我怎么用非 bitmap 表和  bitmap 做交并補(bǔ)集的運(yùn)算,為了解決這個(gè)問(wèn)題,我們結(jié)合上面的例子把查詢(xún)拆分為四步:我要查近30天用戶(hù)支付訂單超過(guò)30元的男性,且年齡在 20 ~30 歲的用戶(hù)(具體查詢(xún)語(yǔ)句參考 PPT 圖片)

第一步我先查 20~30歲的男性用戶(hù)。因?yàn)槭潜容^固定,這里可以直接查 bitmap 表,

第二步我要查近30天用戶(hù)支付訂單超過(guò)30元的用戶(hù)。這種的話(huà)就沒(méi)辦法去查 bitmap 表了,因?yàn)?bitmap 沒(méi)有辦法做這種聚合,只能去查行為表。

第三步就是要做用戶(hù)ID 跟在 線(xiàn) bitmap 的一個(gè)轉(zhuǎn)化。Doris 其實(shí)已經(jīng)提供了這樣的功能函數(shù):to_bitmap,可以在線(xiàn)將用戶(hù) id 轉(zhuǎn)換成 bitmap。

第四步是求交集。就是第一步和第四步的結(jié)果求交集。

然后,請(qǐng)大家要注意一下,整篇的核心其實(shí)是在第三步:Doris 提供了 to_bitmap 的功能,它幫我們解決了非 bitmap 表和  bitmap 聯(lián)合查詢(xún)的問(wèn)題。講到這里,我其實(shí)想給大家表現(xiàn)出那種Doris特別驚艷、特別帥那種感覺(jué),但是我線(xiàn)下練習(xí)了好多遍都無(wú)法表演出來(lái), 你們看我現(xiàn)在的表演 有點(diǎn)太浮夸了, 用力過(guò)猛了。誰(shuí)讓我是個(gè)程序員,不是個(gè)演員呢,沒(méi)有辦法演出那種感覺(jué)、那種感情。所以我只能把我想表達(dá)的感情跟大家說(shuō)出來(lái),大家一定要懂我,對(duì),就是那種很驚艷的感覺(jué),大家一定要懂我~

以上是我們基于 Doris 用戶(hù)分層方案的一個(gè)講解,基于上述方案整體的性能收益是:

  • 95分位耗時(shí)小于一秒
  • 存儲(chǔ)耗降低了9.67倍
  • 行數(shù)優(yōu)化了八倍

說(shuō)明了基于 Doris 的用戶(hù)存儲(chǔ)方案還是特別有效果的, 希望我們的經(jīng)驗(yàn)?zāi)芙o大家能有所幫助。

3. 如何快速產(chǎn)出用戶(hù)包

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

現(xiàn)在講一下第三部分:用戶(hù)包。這部分主要是用來(lái)解決難點(diǎn)四:產(chǎn)出用戶(hù)包要求時(shí)效性高。這個(gè)其實(shí)我們也有兩個(gè)方案:

方案一:調(diào)度平臺(tái) + spark。

這個(gè)其實(shí)比較容易理解,因?yàn)槟阋茈x線(xiàn)任務(wù)很容易就想到了 spark。在這個(gè)調(diào)度平臺(tái)里面用了 DAG 圖,分三步:先產(chǎn)出用戶(hù)的 cuid,然后再產(chǎn)出用戶(hù)的 uid,最后是回調(diào)一下做一次更新。

方案二:調(diào)度平臺(tái) + solo。

  • 執(zhí)行的 DAG 圖的話(huà)就是:solo 去產(chǎn)出 cuid,uid,還有回調(diào)。
  • solo:是百度云提供的 Pingo 單機(jī)執(zhí)行引擎,大家可以理解為是一個(gè)類(lèi)似于虛擬機(jī)的產(chǎn)品,這個(gè)其實(shí)是公有云:《百度智能云》里面已經(jīng)有的功能,大家感興趣的可以去登錄百度智能云官網(wǎng) 去看一下。

最終的方案選型我們是選用了 Doris,因?yàn)?Doris 比 Spark 更快,為啥快?

首先介紹下方案一,方案一使用的是 Spark ,它存在幾個(gè)問(wèn)題:比如 Yarn 調(diào)度比較耗時(shí),有時(shí)候也會(huì)因?yàn)殛?duì)列的資源緊張而會(huì)有延遲,所以有時(shí)候會(huì)出現(xiàn)一個(gè)很極端的情況就是:我產(chǎn)出零個(gè)用戶(hù),也要30分鐘才能跑完,這種對(duì)用戶(hù)的體驗(yàn)度非常不好。

方案二的話(huà)就是我們利用了 Doris 的 SELECT INTO OUTFILE 產(chǎn)出結(jié)果導(dǎo)出功能,就是你查出的結(jié)果可以直接導(dǎo)出到 AFS,這樣的效果就是最快不到三分鐘就可以產(chǎn)出百萬(wàn)級(jí)用戶(hù),所以 Doris 性能在某些場(chǎng)景下比 Spark 要好很多。

最后大家可以看到其實(shí)我這里敘述的時(shí)候語(yǔ)氣依然是比較平淡的,是吧?沒(méi)有帶什么感情,但是我其實(shí)還想表達(dá)出那種驚嘆和喜悅的感情,就是 Doris 性能在某些場(chǎng)景下比 Spark 還要好,但是大家要懂我,我畢竟是個(gè)程序員不是一個(gè)演員,沒(méi)法表達(dá)出那種感覺(jué),但是你們一定要懂我啊,哈哈,開(kāi)個(gè)玩笑,活躍一下直播間氣氛。

04未來(lái)規(guī)劃

百度工程師趙煜楊:基于Doris的小程序用戶(hù)增長(zhǎng)實(shí)踐

未來(lái)的規(guī)劃:

首先在產(chǎn)品上我們會(huì)繼續(xù)的豐富分層的應(yīng)用場(chǎng)景,拓展關(guān)系維度豐富觸達(dá)的形式,然后探索分層和商業(yè)的結(jié)合模式。

在技術(shù)上我們會(huì)從時(shí)效性豐富性跟通用性上做文章:

  • 時(shí)效性:我們會(huì)把交易,訂單,關(guān)注等行為時(shí)實(shí)化
  • 豐富性:我們會(huì)接入更多的用戶(hù)畫(huà)像,標(biāo)簽和行為
  • 通用性:我們會(huì)把全局字典插件化,然后通用到各個(gè)業(yè)務(wù)上

這就是我們的未來(lái)規(guī)劃。后面有機(jī)會(huì)再根大家從 Doris 的架構(gòu)方面跟大家介紹下 Doris 的性能為何如此強(qiáng)悍。今天的分享就到這里,謝謝大家。

—— 歡迎在線(xiàn)投稿 ——

特別提示:關(guān)注本專(zhuān)欄,別錯(cuò)過(guò)行業(yè)干貨!

PS:本司承接 小紅書(shū)推廣/抖音推廣/百度系推廣/知乎/微博等平臺(tái)推廣:關(guān)鍵詞排名,筆記種草,數(shù)據(jù)優(yōu)化等;

咨詢(xún)微信:139 1053 2512 (同電話(huà))

首席增長(zhǎng)官CGO薦讀:

更多精彩,關(guān)注:增長(zhǎng)黑客(GrowthHK.cn)

增長(zhǎng)黑客(Growth Hacker)是依靠技術(shù)和數(shù)據(jù)來(lái)達(dá)成各種營(yíng)銷(xiāo)目標(biāo)的新型團(tuán)隊(duì)角色。從單線(xiàn)思維者時(shí)常忽略的角度和高度,梳理整合產(chǎn)品發(fā)展的因素,實(shí)現(xiàn)低成本甚至零成本帶來(lái)的有效增長(zhǎng)…

本文經(jīng)授權(quán)發(fā)布,不代表增長(zhǎng)黑客立場(chǎng),如若轉(zhuǎn)載,請(qǐng)注明出處:http://allfloridahomeinspectors.com/cgo/user/37464.html

(1)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
上一篇 2021-05-10 10:47
下一篇 2021-05-10 11:05

增長(zhǎng)黑客Growthhk.cn薦讀更多>>

發(fā)表回復(fù)

登錄后才能評(píng)論
特別提示:登陸使用搜索/分類(lèi)/最新內(nèi)容推送等功能?>>