導讀:隨著業務在金融、保險和商城領域的不斷擴展,眾安保險建設 CDP 平臺以提供自動化營銷數據支持。早期 CDP 平臺依賴于 Spark + Impala + Hbase + Nebula 復雜的技術組合,這不僅導致數據分析形成數據孤島,還帶來高昂的管理及維護成本。為解決該問題,眾安保險引入 Apache Doris,替換了早期復雜的技術組合,不僅降低了系統的復雜性,打破了數據孤島,更提升了數據處理的效率。
眾安在線財產保險股份有限公司是中國首家互聯網保險公司,由螞蟻金服、中國平安和騰訊于 2013 年聯合發起設立。眾安專注于應用新技術重塑保險價值鏈,圍繞健康、數字生活、消費金融、汽車四大生態,以科技服務新生代,為其提供個性化、定制化、智能化的新保險。業務和關聯公司的業務包括:眾安保險、眾安醫療、眾安小貸、眾安科技、眾安經紀、眾安國際、眾安銀行等。截至 2023 年中,眾安服務超過 5 億用戶,累計出具約 574 億張保單。
然而,隨著業務在金融、保險和商城領域的不斷擴展,眾安保險面臨用戶數據管理的挑戰。用戶信息來源于公眾號、小程序和 APP 等多個渠道,這些數據不僅碎片化,而且多樣化。同時,運營渠道也涵蓋了自營、聯營和外部投放等多種途徑,導致數據進一步分散。這種數據孤島現象使得眾安保險難以形成完整的用戶融合體系,從而無法實現對用戶的精準識別和實時營銷。
CDP 建設目標及方案
為了解決這一問題,眾安保險建設了 CDP 平臺。該平臺的核心職責是整合所有用戶數據,構建全面的用戶標簽和客群體系,并利用其強大的數據分析能力為自動化營銷提供數據支持。

CDP 平臺的建設目標主要包括以下幾點:
- 快速數據集成: CDP 需支持集成常見的關系性數據庫(如 MySQL、PG 等 )和數據倉庫同(如 Hive、MaxCompute 等),同時還需要整合實時數據流(如 Kafka 等)。
- 精準用戶識別:在復雜的業務體系中,CDP 平臺需能夠靈活整合多種 ID 類型,形成統一的用戶視圖,為下游的實時營銷場景提供支撐。
- 靈活的用戶標簽和強大的分群能力:這是 CDP 平臺的核心建設目標,旨在提供全面、深度的用戶洞察,精準滿足用戶需求。
- 多維度實時分析:支持對用戶畫像、用戶旅程和營銷效果的實時跟蹤與回收。為優化營銷策略和提升用戶參與度提供有力的支持。
基于上述建設目標,眾安保險目前已形成了完整的 CDP 解決方案,該方案包括以下幾個關鍵步驟:

- 全域數據采集:CDP 平臺通過實時和離線數據采集方式,實現對全域數據的整合。利用 Flink 進行實時數據采集,同時建設離線數倉以整合多渠道數據,確保高質量的數據資產沉淀。
- 用戶數據融合:通過 ID Mapping 技術,可將現有的用戶數據進行融合,打破數據孤島。即將用戶手機、用戶身份證、設備指紋、OpenID 等用戶身份進行融合,形成統一的用戶標識(OneID)。
- 標簽和客群管理:CDP 平臺支持多維度標簽的建設,包含用戶屬性、用戶行為、業務交易狀態等。同時,通過規則客群的圈選能力實力客群的精細劃分。
- 用戶數據分析:基于豐富的用戶標簽數據,CDP 平臺提供用戶畫像洞察功能,支持實時效果評估和營銷漏斗分析。
- 用戶數據服務:CDP 平臺提供多維度的數據接口服務能力,包括用戶標簽、客群、分層和實時事件等,賦能用戶全鏈路智能營銷。
CDP 平臺架構的演進歷程
在初步了解了 CDP 平臺的建設初衷和解決方案之后,我們將深入挖掘其演進歷程,探索它如何逐步蛻變為眾安保險統一、高效且不可或缺的核心基礎設施。本文將重點分享 CDP 平臺的建設過程及其在實際生產中的應用實踐。

CDP 產品架構如上圖所示。全域數據接入之后,這些數據就可以搭建用戶數據中心、實時事件中心、客群畫像以及營銷流程。用戶數據中心是客群畫像的基石,并與客群畫像、實時事件中心一同支撐營銷流程的數據需求。數據服務層則包括用戶數據服務、客群圈選、營銷策略、實時事件、 AB 實驗和實時效果分析回收在內的全方位數據服務,滿足各業務場景的數據需求。
架構 1.0:多個技術棧,形成數據孤島

CDP 平臺架構 1.0 如上圖所示,離線數據和實時數據的處理流程如下:
- 離線數據:通過 ETL 方式集成各業務線的數據庫數據,包括行為埋點數據、日志數據等,并將這些數據抽取數倉 DWS 層。隨后,利用 Spark 作業將 DWS 層數據抽取到 Impala 中,進行離線的標簽計算和客群的圈選。同時,我們還通過 Spark 抽取 DWS 層業務體系里的用戶點邊關系,并將其集成到 Nebula 圖數據庫中,提供全面的點邊關系計算、邊距計算以及 One ID 計算功能。
- 實時數據:采用 Kafka 實時回收所有的業務線的 Binlog 數據、行為埋點數據以及各業務線的事件上報數據,在 Flink 中實現實時標簽的配置化計算,并通過 Flink Checkpoint 進行復雜的實時指標計算和事件組合。最終將實時標簽存儲在 Hbase 中,以便為各業務線提供點查服務。
然而,從架構圖中可以明顯看出,標簽計算和 ID 圖譜計算這一層涉及了非常多的技術棧,包含 Impala、Spark、Nebula 以及 Hbase。這些過多的組件導致了離線標簽、實時標簽以及圖數據存儲的不統一、各場景數據分散存儲,形成了數據孤島。
在這種情況下,當需進行整體視圖計算或為上層提供服務時,就需要打通所有的數據,這無疑增加了大量數據傳輸和數據重復存儲的成本。此外,由于各類數據存儲方案的差異,還需要使用較大的 CDH 集群和 Nebula 圖數據庫集群,進一步提高了集群資源與維護成本。
架構 2.0:統一技術棧,打破數據孤島
為了解決數據存儲的不一致性和高昂成本問題,我們決定進行架構升級,并選擇 Apache Doris 作為核心組件。我們的升級目標是希望通過引入 Doris 來統一技術棧,實現實時和離線數據存儲和計算的整合,從而打破數據孤島,大幅度降低數據存儲和資源維護的成本。在實際的應用中,Doris 完美地滿足了我們的需求,使得整體架構變得更精簡高效。

對于離線數據,我們采用了 Doris 的 Stream Load 功能,輕松地從離線數倉中將數據抽取到 Doris 中。而對于實時數據,則通過 Flink Connector 與 Stream Load 的結合,將實時事件和實時標簽無縫導入到 Doris 中。基于 Doris 強大的向量化計算引擎,我們不僅實現了 One ID 計算、離線/實時標簽的存儲和計算、客群圈選、實時事件存儲,還支持了實時分析等多樣化需求,真正實現了技術棧的統一。
引入 Doris 后,我們還收獲了以下顯著的收益:
- 架構簡潔,運維成本降低 :引入 Doris 之前,我們需要額外維護 CDH 集群和 Nebula 集群。而現在,僅憑一個 Doris 集群就可以完成所有的工作,顯著降低運維成本。此外,Doris 還提供的完善集群監控設施也極大方便了我們對集群的便捷管理。
- 支持 SQL,快速上手 : Doris 兼容 MySQL 協議,這意味著對于已經熟悉 MySQL 的開發者來說,無需額外的學習成本就能快速上手操作。
- 豐富的數據導入形式 :Doris 提供了豐富且便捷的數據導入方式,使數據庫遷移和數據導入變得高效和方便。用戶可以根據實際需求選擇適合的導入方式,以快速完成數據遷移和導入操作。
Doris for CDP 在業務場景中的實踐
全域數據采集
為滿足不同場景的數據集成需求,CDP 平臺主要分為三個板塊:
- 離線數據導入:針對標簽計算、實時客群預估與圈選,以及標簽和客群多維畫像分析等場景,我們采用 DataX 工具,通過 Stream Load 方式將離線數據高效寫入到 Doris 里。為確保 Stream Load 的穩定性,我們在線上對 30 多個線程并發導入進行測試,結果顯示,每秒 Upsert (寫入或更新) 數量高達 30+ 萬條。對于我們當前的一級用戶量來說,導入效果可以很好滿足我們的需求。
- 部分列更新:在實時寫入場景中,當使用 Flink 實時寫入標簽數據時,需要精確到單個用戶和標簽的實時更新和插入,流程相對復雜。而 Doris Stream Load 可以開啟部分列更新 partial_columns=true 來滿足這一需求,確保每個用戶和標簽都能得到及時、準確的更新。
- 外部數據源對接:在實時分析報表場景中,經常需要跨多個數據源的交叉分析。Doris 的 Multi-Catalog 功能可以更方便對接外部數據目錄,無需進行數據遷移或導入,即可進行外部數據源的聯邦查詢。無論是基于 Hive 或 MaxCompute 的查詢,還是 JDBC 業務線的數據查詢,都能迅速獲得精準的分析結果,極大提升了查詢效率。
OneID
1. 構建 ID 圖譜

我們在現有系統中配置了 ID 圖譜的點關系,這些關系以用戶為中心,形成了復雜的網絡結構。舉例說明:假設某用戶在體系 A 擁有用戶 ID,并且綁定的公眾號,這樣就形成了 Open ID 綁定關系。隨著用戶的使用,他可能注冊了手機號,那么手機號跟體系 A 用戶 ID 之間便建立了綁定關系。如果用戶在體系 A 也進行了實名,那么身份證和注冊手機號也會建立綁定關系。
隨著時間的推移,該用戶可能進入到體系 B 中,并注冊體系 B 賬戶。這時,與該用戶相關的體系 A 用戶 ID、手機號、身份證和體系 B 賬戶之間都會形成關聯。在如上圖右側系統里,我們可以配置用戶 ID、OpenID、手機號、身份證這些點的屬性、物理表及關聯關系,形成 ID 圖譜。那么結合 ID 圖譜,就可以基于 Doris 進行 OneID 的構建。
2. 構建 OneID

基于用戶各個業務線之間點和邊的關系,我們會將用戶在不同業務線中的信息全部抽取出來,放入一張大表里面進行 Union All 操作。這張表包含了手機號、體系 A 用戶 ID、體系 B 用戶 ID、身份證號和 Open ID 關鍵信息。OneID 的構建流程如下:
- 首先,利用 Doris 提供的
row number窗口函數生成完整的全局行順序。然后對所有 ID 關系數據進行 Union All 操作。 - 接著,使用窗口函數
dense rank和row number的復數生成為空/不為空時的首列 Rank 值。 - 最后,通過循環迭代計算每一列最小距離,并不斷迭代 Rank 值,直到當前列與上一迭代結果全局匹配。當所有數據連續匹配滿 5 次后,就以最終 Rank 值為準進行用戶分組,從而得用戶唯一標識 OneID。
結合上圖以及構建流程,可以得出結論: 1 - 4 行是用戶 1,5 - 6 行是用戶 2。
標簽體系
我們的標簽體系由實時標簽和離線標簽兩部分組成,目前該體系擁有超過 2000 個標簽,涉及 50 余張來源表,服務用戶量已達億級。

在標簽體系中,有一些簡單的配置規則:
- 離線標簽:在 Doris 中抽象出三種業務類型表,分別是用戶數據表、業務明細表和行為事件表。根據上方標簽配置規則,通過 DSL 動態語義生成 SQL,然后在 Doris 中進行計算,并將計算結果存儲在 Doris 中,形成一張離線標簽寬表。
- 實時標簽:基于 Flink 接收 Kafka 、 CDC 消息,并根據實時標簽配置元數據,在 Flink 中計算出實時標簽,并將最終結果寫入 Doris 的實時標簽寬表中。

Apache Doris 在標簽體系中的應用主要包含以下四個方面:
1.離線標簽處理: 由于擁有 2000+ 較大量級的標簽一級用戶,當遇到高峰期并發寬表寫入時,全量更新所有列可能會出現內存不足的問題。為避免該問題,我們利用 Doris 的 Insert Into Select 功能,在 session 變量中打開部分列更新開關,只更新目標表中需要修改的列,這樣可顯著減少內存消耗,以提升全量導入的穩定性。
set enable_unique_key_partial_update=true;
insert into tb_label_result(one_id, labelxx)
select one_id, label_value as labelxx
from .....
2.實時標簽處理: 在實時標簽寫入時,不同的實時標簽字段更新時間不一樣,而部分列更新能力可以滿足此更新需求。只需打開 Partial Column,并將其設置為 True,就可以實現實時標簽的部分列更新。
curl --location-trusted -u root: -H "partial_columns:true" -H "column_separator:," -H "columns:id,balance,last_access_time" -T /tmp/test.csv http://127.0.0.1:48037/api/db1/user_profile/_stream_load
3.標簽點查: 隨著線上業務量的不斷增長,我們面臨著處理超過 5000 QPS 標簽請求的挑戰。為滿足這一需求,我們采用多種策略來確保高效的點查性能。首先,通過利用 PrepareStatement 技術,預編譯和執行 SQL 查詢,從而提高查詢效率。其次,精細調整了 Backend(BE)參數和表參數,以優化數據存儲和查詢性能。同時,我們打開了行存,進一步提升系統在高并發場景下的處理能力。
- 在 be.conf 中調整 BE 參數:
disable_storage_row_cache = false
storage_page_cache_limit=40%
- 在建表時調整表屬性:
enable_unique_key_merge_on_write = true
store_row_column = true
light_schema_change = true
4.標簽計算:為了滿足用戶對于標簽配置的靈活需求,系統允許在 DSL 生成的語義中進行多表 Join 操作,而這就可能會涉及十幾張表的 Join 操作。為了確保標簽計算性能最優,我們充分運用 Doris Colocation Group 策略,對所有分桶列的類型、數量和副本進行統一,并優先滿足 Colocation Join 和本地的 Hash Join。在線上環境中,也可以打開Colocate With開關,指定一個 Group,確保全局表的分片與副本策略一致。
客群圈選

在架構 1.0 中,客群服務先生成動態 SQL,然后將其傳輸到 Impala 中進行客群圈選。完成圈選后,結果集需被重新讀取回客群服務,并由其上傳到對象存儲中。這一連串的操作使得數據處理鏈路相對冗長,影響了整體效率。而在架構 2.0 中,我們可以在 Doris 中使用基于 Select 語句的結果集,并通過 Select Into Outfile 功能,將數據無縫導入到 S3 協議的對象存儲中,這種方式極大縮短了數據處理鏈路。
在實際的業務中,線上約有 100 萬個客群,單個客群生成所需時間從 50 秒縮短至 10 秒,極大提升了客群圈選效率。 若需要進一步提高性能,可以選擇打開并發導出開關,進一步提高數據導出性能。
客群歸屬

在我們的業務系統中,客群歸屬扮演著至關重要的角色,特別是在實時智能營銷和千人千面的識別場景中。我們經常需要判斷某個用戶是否隸屬于特定的客群,或者確定其屬于哪些客群。這種全局性的判斷有助于我們深入理解多個客群之間的用戶重疊關系。
為了滿足這一需求,我們可以借助 Bitmap 來實現。在 Bitmap 中,使用 Bitmap Contains 可以快速識別某個用戶是否存在于特定客群中,也可以通過 Bitmap OR、Bitmap Intersect 或 Bitmap XOR 來實現客群全量、多版本之間的交并叉分析,從而提供更為精準和高效的營銷策略。
總結與展望
在架構 1.0 中采用了復雜的技術組合,以實現標簽、客群以及 OneID 的計算。這一架構組件眾多,導致數據處理鏈路冗長、造成數據孤島,且有著較高的管理和維護成本。通過引入 Apache Doris ,替換了 Spark + Impala + Hbase + Nebula,成功實現存儲與計算的統一,簡化了數據處理的流程,不僅降低了系統的復雜性,更提升了數據處理的效率,滿足了更豐富的數據處理需求。 隨著業務的發展,實時營銷場景對實時性的要求日益提升。未來,我們計劃在 3.0 版本中,實現離線標簽和實時標簽的混合圈選功能,并依托 Doris 進行 OneID 實時計算。這將使我們能夠更快速、準確地識別增量的用戶,并在多用戶體系中實現精準的用戶識別,以滿足不斷變化的業務需求,推動實時智能營銷和個性化識別場景的持續創新與發展。 最后,我們衷心感謝 SelectDB 技術團隊 所提供的技術支持,未來我們期待與社區更緊密的合作,為社區貢獻力所能及的力量,共同推動技術的發展與進步。


