基於Clickhouse秒級查詢6億用戶畫像!到底有多6?

 

做者介紹git

楊兆輝,蘇寧科技集團大數據中心高級架構師,ClickHouse Contributor。在OLAP領域、大規模分佈式計算領域有着深厚的技術積累,目前負責數據中臺、標籤平臺相關的架構工做。github

 

背景

 

想作營銷活動,如何找到目標人羣及用戶特徵?人羣的篩選一般離不開用戶畫像。用戶畫像就是根據用戶特徵、業務場景和用戶行爲等信息,構建一個標籤化的用戶模型。sql

 

好比消費者用戶畫像分爲屬性和行爲標籤兩類。這兩類標籤,一個是固定的,一個是可變的。數據庫

 

固定的屬性標籤基本就是買家的性別,年齡段,會員等級,消費水平,購買力等。而可變的行爲標籤基本包括買家的瀏覽,加購物車,購買等行爲。緩存

 

經過多年的建設,蘇寧構建了完整的用戶標籤體系,覆蓋零售、金融、體育等多個產業。服務器

 

同時搭建了標籤服務平臺,經過開放豐富的標籤數據能力,爲廣告、推薦等提供智能化的標籤中臺服務能力。架構

 

隨着數據的日益增多,如何對 6 億+用戶千億級別的標籤數據進行秒級用戶畫像?併發

 

本文將帶來用戶畫像技術的新發展和架構實踐,介紹基於 ClickHouse 定製開發的標籤平臺,真正作到海量標籤數據的快速導入和秒級用戶畫像查詢分析,提供一整套從前期人羣篩選到後期的營銷策略優化的標籤體系。分佈式

 

業務場景介紹

 

「雙 11」到了,假設須要發放 1000 萬張家電類優惠券,那咱們首先須要根據標籤篩選出符合條件的人羣,人數大約爲 1000 萬左右,而後對選擇的人羣進行畫像分析,看是否符合預期的特徵。函數

 

若是人羣符合特徵,系統將一鍵生成進行營銷的人羣包(userid 列表),自動化發佈和營銷。

 

圖 1:業務流程

 

  預估人數

 

用戶選擇標籤及標籤之間的交併差關係,圈選出符合條件的人羣,實時預估出人羣的數量。

 

好比選擇:

 

圖 2:建立人羣

 

上圖的標籤選擇的含義爲:「用戶年齡範圍爲 25-36 歲」而且爲「智能家居特徵」的人羣,排除最近 30 天消費小於 10 元的人羣。

 

表示爲集合運算的公式爲:

{ {用戶年齡 25-36} ∩ {智能家居人羣} } - {30天消費小於10元}

 

技術難點有:

人羣包的個數多。

每一個人羣包的用戶基數較大。

系統實時輸出計算結果,難度大。

 

  畫像分析

 

當篩選出用戶數與規劃的消費券的數量匹配時,須要對人羣進行特徵分析,看看人羣是否符合特徵要求。

 

用戶畫像表的結構舉例以下:

 

 

將篩選出的人羣包與用戶畫像表進行關聯,詳細分析關聯出的畫像特徵。也能夠進一步對畫像特徵進行一些歷史數據分析。

 

咱們以前的解決方案是將用戶標籤存儲在 ElasticSearch 的大寬表中的。大寬表的結構是:一個用戶下掛一堆 tag 的表結構。

 

在向大寬表插入數據時,須要等待業務的數據都準備好後,才能跑關聯表操做,而後將關聯的結果插入到 ES。

 

常常遇到的狀況是:某個業務方的任務延遲,致使插入 ES 的關聯任務沒法執行,運營人員沒法及時使用最新的畫像數據。

 

在 ES 中修改文檔結構是比較重的操做,修改或者刪除標籤比較耗時,ES 的多維聚合性能比較差,ES 的 DSL 語法對研發人員不太友好,因此咱們將標籤存儲引擎從 ES 替換爲 ClickHouse。

 

ClickHouse 是近年來備受關注的開源列式數據庫,主要用於數據分析(OLAP)領域。憑藉優異的查詢性能,受到業界的青睞,各個大廠紛紛跟進大規模使用它。

 

蘇寧大數據已將 ClickHouse 引入並改造,封裝成豐富的 Bitmap 接口,用來支撐標籤平臺的存儲及分析。

 

ClickHouse 集成 Bitmap

 

咱們在 ClickHouse 中集成了 RoaringBitmap,實現了 Bitmap 計算功能集,並貢獻給開源社區。

 

對 userid 進行位圖方式的壓縮存儲,將人羣包的交併差計算交給高效率的位圖函數,這樣既省空間又能夠提升查詢速度。

 

圖 3:ClickHouse 集成 Bitmap

 

圍繞 Bitmap 對象實現了一套完善的計算函數。Bitmap 對象有兩種構建方式,一種是從聚合函數 groupBitmap 構建,另外一種是從 Array 對象構建,也能夠將 Bitmap 對象轉換爲 Array 對象。

 

ClickHouse 的 Array 類型有大量的函數集,這樣能夠更加方便的加工數據。

 

上圖的中間部分是 Bitmap 的計算函數集,有位運算函數、聚合運算函數、求值類運算函數,比較豐富。

 

基於 ClickHouse 的新架構

 

  架構介紹

 

架構圖以下:

 

圖 4:標籤架構

 

ClickHouse Manager 是咱們自研的 ClickHouse 管理平臺,負責集羣管理、元數據管理和節點負載協調。

 

Spark 任務負責標籤數據的生成和導入,當某個業務方的任務跑完後,會馬上調用 tag-generate 生成標籤數據文件,存放到 HDFS,而後在 ClickHouse 上執行從 HDFS 導入到 ClickHouse 的 SQL 語句,這樣就完成了標籤的生產工做。

 

標籤生產是併發跑的,假設某個業務方的數據沒有準備好,不影響其餘業務的標籤生產。

 

用戶畫像平臺經過 Proxy 從 ClickHouse 集羣查詢標籤數據。在查詢前,須要將查詢表達式轉換爲 SQL,咱們對這塊邏輯作了一個封裝,提供一個通用的轉換模塊,叫作:to-ch-sql。

 

業務層基本上不用修改就能夠查詢 ClickHouse 了。

 

  標籤數據表的基本結構

 

相對於 ElasticSearch 的存儲結構,咱們將標籤存儲作了一個行轉列存儲。每一個標籤對應一個 Bitmap 對象。

 

Bitmap 對象中存儲 userid 集合:

 

 

CREATE TABLE ch_label_string

(

 labelname String,   --標籤名稱

 labelvalue String,  --標籤值

 uv AggregateFunction( groupBitmap, UInt64 )  --userid集合

)

ENGINE = AggregatingMergeTree()

PARTITION BY labelname

ORDER BY (labelname, labelvalue)

SETTINGS index_granularity = 128;

 

uv 字段爲 Bitmap 類型的字段,將整形的 userid 存入,每一個 userid 用一個 bit 位表示。

 

主鍵索引(index_granularity)默認爲 8192,修改成 128 或者其餘數值,因爲 Bitmap 佔用的存儲空間比較大,修改成小數值,以減小稀疏索引的讀放大問題。

 

根據標籤值的數據類型劃分爲四種類型的表:

 

  • String

  • Integer

  • Double

  • Date

 

標籤名稱做爲 Partition。經過這樣的設計,增長或者刪除標籤數據都比較方便,只須要修改 Partition 的數據就能夠了。Partition 的管理有相應的 SQL 語句,操做比較方便。

 

  Userid 分片存儲

 

在標籤數據導入時,按照 userid 分片導入,每臺機器僅存儲對應 userid 的標籤數據。

 

每臺機器分別導入分片後的標籤數據,實現了數據並行導入。在咱們的環境上單機導入性能在 150 萬條/秒左右。

 

在根據標籤篩選人羣時,SQL 僅須要在單個 shard 上執行,中間結果不須要返回給查詢節點。

 

在執行「預估人數」計算時,優點特別明顯:每一個 shard 僅須要返回符合條件的人數,在查詢節點作 sum 操做,而後將 sum 結果返回給客戶端。充分挖掘了 ClickHouse 分佈式並行計算的能力。

 

  查詢流程

 

採用 with 語句進行計算出人羣包的 Bitmap 對象,而後用 Bitmap 函數進行交併差的計算。

 

當須要計算的標籤比較多時,標籤查詢的 SQL 比較複雜,將標籤查詢 SQL 包裝到分佈式代理表的 SQL 中,分佈式代理表自己不存儲數據,經過代理表標識到哪些節點上查詢,分佈式代理表所標識的節點上執行標籤查詢 SQL。

 

而後在分佈式代理表上彙總查詢結果。經過 ClickHouse 分佈式表的自身特性,實現了標籤查詢的 colocate 機制。

 

圖 5:查詢流程

 

示例 SQL 以下:

 

-- 本地查詢代理

CREATE TABLE ch_agent_user

(

    agentname String

)

ENGINE = MergeTree()

PARTITION BY agentname

ORDER BY (agentname)

SETTINGS index_granularity = 8192;

 

-- 分佈式代理表

CREATE TABLE ch_agent_dist_user AS ch_agent_user

ENGINE = Distributed('cluster_test', 'test', 'ch_agent_user', cityHash64(agentname))

 

-- 查詢用戶數

SELECT sum(user_number) AS user_number

FROM ch_agent_dist_user

RIGHT JOIN 

(

    WITH 

        (

            SELECT groupBitmapState(userid) AS users0

            FROM ch_label_string

            WHERE labelname = 'T'

        ) AS users0

    SELECT 

        'agent' AS agentname, 

        bitmapCardinality(users0) AS user_number

) USING (agentname) settings enable_scalar_subquery_optimization = 0;

 

ch_agent_user 表自己不存儲數據,當與 with 語句進行 right join 關聯查詢時,因爲是右關聯查詢,查詢結果以 with 語句的結果集爲準。

 

各個節點的查詢結果返回給查詢節點,查詢節點進行彙總計算。參數 enable_scalar_subquery_optimization = 0 表示 with 語句的查詢結果不作優化,每一個節點都須要執行。

 

默認狀況,在 ClickHouse 中 with 語句的結果做爲標量進行緩存,會將查詢節點的標量分發到其餘服務器,當發現已經存在標量時,就不會在本地節點執行 with 語句。

 

咱們指望 with 語句在每一個節點都執行,因此將這個參數設置爲 0。

 

  用戶畫像

 

用戶畫像對性能要求比較高,查詢平均響應時間不能大於 5 秒。用戶在界面上任意圈選人羣,而後實時對圈選後的人羣進行畫像分析。

 

用戶畫像技術進行了三次架構重構:

 

1)V1:大寬表模式

 

最先的方案是建立一張 userid 爲主鍵的畫像表,表的其餘字段爲畫像的特徵字段,將圈選的人羣與畫像表進行 in 操做,而後 group by 操做。

 

這種設計帶來兩個比較嚴重的問題:

 

  • 當增長或者刪除特徵字段時,畫像表的表結構須要修改;

  • 當圈選的人羣數量比較大時,涉及到大記錄集的 group by 運算,性能差。

 

2)V2:Bitmap 模式

 

將一個特徵值下的 userid 集合作爲 Bitmap 對象存儲到一條記錄中,一條記錄的內容以下:

 

 

用戶圈選的人羣 Bitmap 對象與畫像表的 Bitmap 對象進行與(AND)操做,返回圈選人羣的畫像信息。

 

經過這樣設計,基本上知足了性能要求,平均時間小於 5 秒,可是一些大的人羣包,畫像的性能仍是差,在 10 秒左右。

 

畫像表的記錄數據量不大,但畫像表的 Bitmap 字段在計算時須要從磁盤上反序列化出來。有的 Bitmap 對象佔用幾百兆的空間,致使了性能的降低。

 

3)V3:Join 表引擎模式

 

ClickHouse 的 Join 表引擎能夠將數據常駐到內存。當插入數據時,數據先寫入內存,而後刷到磁盤文件,系統重啓時,自動把數據加載回內存。Join 表引擎能夠說是常駐內存的帶持久化功能的表。

 

咱們把畫像表的數據保存到 Join 表引擎,畫像表的 Bitmap 字段就常駐內存了,當圈選的人羣 Bitmap 對象進行與(AND)操做時,兩個內存中已經加載的 Bitmap 對象之間的計算就很是快。

 

經過此次優化平均查詢時間優化到 1 到 2 秒,千萬級人羣畫像分析不超過 5 秒。

 

總結

 

經過 ClickHouse 集成 Bitmap 功能,以及 Join 表引擎的應用,對架構進行了一系列優化後,極大的提高了標籤平臺的數據分析能力。

 

新的架構主要有如下優點:

 

  • 標籤數據能夠並行構建,加快標籤數據生產速度;

  • HDFS 文件併發導入 ClickHouse,加快標籤數據的就緒速度;

  • 查詢請求平均響應時長在 2 秒如下,複雜查詢在 5 秒如下;

  • 支持標籤數據準實時更新;

  • 標籤表達式和查詢 SQL 對用戶來講比較友好,提高系統的易維護性;

  • 相對於 ElasticSearch 的配置,能夠節約一半硬件資源。

 

將來規劃:

 

  • 目前 ClickHouse 採用 RoaringBitmap 的 32 位版本,準備增長 64 位版本;

  • ClickHouse 查詢的併發性較低,增長更加智能的 Cache 層;

  • 支持 ClickHouse 數據文件離線生成,進一步提示標籤的就緒速度。

 

>>>>

參考資料

 

  • ClickHouse 官網:https://clickhouse.tech/

  • ClickHouse 中文社區:http://www.clickhouse.com.cn/

  • Bitmap PR:https://github.com/ClickHouse/ClickHouse/pull/4207

 

做者丨楊兆輝 來源丨51CTO技術棧(ID:blog51cto) dbaplus社羣歡迎廣大技術人員投稿,投稿郵箱: editor@dbaplus.cn  
相關文章
相關標籤/搜索