隨着閒魚業務的發展,用戶規模達到數億級,用戶維度的數據指標,達到上百個之多。如何從億級別的數據中,快速篩選出符合指望的用戶人羣,進行精細化人羣運營,是技術須要解決的問題。業界的不少方案經常須要分鐘級甚至小時級才能生成查詢結果。本文提供了一種解決大數據場景下的高效數據篩選、統計和分析方法,從億級別數據中,任意組合查詢條件,篩選須要的數據,作到毫秒級返回。mysql
從技術角度分析,咱們這個業務場景有以下特色:sql
下面簡單對比下OLTP和OLAP:數據庫
OLTP | OLAP | |
---|---|---|
定義 | 聯機事務處理 | 聯機分析處理 |
應用場景 | 平常業務操做 | 分析決策,報表統計 |
事務要求 | 須要支持事務 | 無需事務支持 |
經常使用數據操做 | 讀/寫高併發 | 查詢爲主,併發要求相對低 |
實時性要求 | 高 | 要求不嚴格 |
DB大小 | MB-GB | GB-TB |
數據行數 | 幾萬到幾百萬 | 億級別甚至幾十億上百億 |
數據列數 | 幾十至上百列 | 百級別至千級別 |
最多見的數據庫,如MySql、Oracle等,都採用行式存儲,比較適合OLTP。若是用MySql等行數據庫來實現OLAP,通常都會碰到兩個瓶頸:性能優化
綜上分析,咱們的應用場景,並不適合採用行存儲數據庫,所以咱們重點考慮列存數據庫。架構
下面簡單對比一下行式存儲與列式存儲的特色:併發
行式存儲 | 列式存儲 | |
---|---|---|
存儲特色 | 同一行數據一塊兒存儲 | 同一列數據一塊兒存儲 |
讀取優勢 | 一次性讀取整行數據快捷 | 讀取單列數據快捷 |
讀取缺點 | 單列讀取,也須要讀取整行數據 | 整行查詢,須要重組數據 |
數據更新特色 | INSERT/UPDATE比較方便 | INSERT/UPDATE比較麻煩 |
索引 | 須要單獨對查詢列建索引 | 每一列均可以做爲索引 |
壓縮特色 | 同一行數據差別大,壓縮比率低 | 一列數據因爲類似性,壓縮比率高 |
行存適合近線數據分析,好比要求查詢表中某幾條符合條件的記錄的全部字段的場景。列存適合用於數據的統計分析。考慮以下場景:一個用於存放用戶的表中有20個字段,而咱們要統計用戶年齡的平均值,若是是行存,則要全表掃描,遍歷全部行。但若是是列存,數據庫只要定位到年齡這一列,而後只掃描這一列的數據就能夠獲得全部的年齡,計算平均值,性能上相比行存理論上就會快20倍。
而在列存數據庫中,比較常見的是HBase。HBase應用的核心設計重點是rowkey的設計,通常要把經常使用的篩選條件,組合設計到rowkey中,經過rowkey的get(單條記錄)或者scan(範圍)查詢。所以HBase比較適合有限查詢條件下的非結構化數據存儲。而咱們的場景,因爲全部字段都須要做爲篩選條件,因此本質上仍是須要結構化存儲,且要求查詢低延遲,所以也沒法使用HBase。
咱們綜合考慮集團內多款列式存儲的DB產品(ADS/PostgreSQL/HBase/HybridDB),綜合評估讀寫性能、穩定性、語法完備程度及開發和部署成本,咱們選擇了HybridDB for MySQL計算規格來構建人羣圈選引擎。高併發
HybridDB for MySQL計算規格對咱們的這個場景而言,核心能力主要有:性能
那麼,HybridDB for MySQL計算規格是如何作到大數據場景下的任意維度組合查詢的毫秒級響應的呢?大數據
綜合來講,HybridDB for MySQL計算規格是以SQL爲中心的多功能在線實時倉庫系統,很適合咱們的業務場景,所以咱們在此之上構建了咱們的人羣圈選底層引擎。優化
在搭建了人羣圈選引擎以後,咱們重點改造了咱們的消息推送系統,做爲人羣精細化運營的一個重要落地點。
消息推送(PUSH)是信息觸達用戶最快捷的手段。閒魚比較經常使用的PUSH方式,是先離線計算好PUSH人羣、準備好對應PUSH文案,而後在次日指定的時間推送。通常都是週期性的PUSH任務。可是臨時性的、須要馬上發送、緊急的PUSH任務,就須要BI同窗介入,每一個PUSH任務平均約須要佔用BI同窗半天的開發時間,且操做上也比較麻煩。本次咱們把人羣圈選系統與原有的PUSH系統打通,極大地改善了此類PUSH的準備數據以及發送的效率,解放了開發資源。
離線數據層:用戶維度數據,分散在各個業務系統的離線表中。咱們經過離線T+1定時任務,把數據彙總導入到實時計算層的用戶大寬表中。
實時計算層:根據人羣的篩選條件,從用戶大寬表中,查詢符合的用戶數量和用戶ID列表,爲應用系統提供服務。
人羣圈選前臺系統:提供可視化的操做界面。運營同窗選擇篩選條件,保存爲人羣,用於分析或者發送PUSH。每個人羣,對應一個SQL存儲。相似於:
select count(*) from user_big_table where column1> 1 and column2 in ('a','b') and ( column31=1 or column32=2)
同時,SQL能夠支持任意字段的多層and/or嵌套組合。
用SQL保存人羣的方式,當用戶表中的數據變動時,能夠隨時執行SQL,獲取最新的人羣用戶,來更新人羣。
閒魚PUSH系統:從人羣圈選前臺系統中獲取人羣對應的where條件,再從實時計算層,分頁獲取用戶列表,給用戶發送PUSH。在實現過程當中,咱們重點解決了分頁查詢的性能問題。
分頁查詢性能優化方案:
在分頁時,當人羣的規模很大(千萬級別)時,頁碼越日後,查詢的性能會有明顯降低。所以,咱們採用把人羣數據增長行號、導出到MySql的方式,來提高性能。表結構以下:
批次號 | 人羣ID | 行號 | 用戶ID |
---|---|---|---|
1001 | 1 | 1 | 123 |
1001 | 1 | 2 | 234 |
1001 | 1 | 3 | 345 |
1001 | 1 | 4 | 456 |
咱們爲"人羣ID"+"批次號"+"行號"建組合索引,分頁查詢時,用索引查詢的方式替換分頁的方式,從而保證大頁碼時的查詢效率。
另外,爲此額外付出的導出數據的開銷,得益於HybridDB強大的數據導出能力,數據量在萬級別至百萬級別,耗時在秒級至幾十秒級別。綜合權衡以後,採用了本方案。
人羣圈選系統爲閒魚精細化用戶運營提供了強有力的底層能力支撐。同時,圈選人羣,也能夠應用到其餘的業務場景,好比首頁焦點圖定投等須要分層用戶運營的場景,爲閒魚業務提供了很大的優化空間。
本文實現了海量多維度數據中組合查詢的秒級返回結果,是一種OLAP場景下的通用技術實現方案。同時介紹了用該技術方案改造原有業務系統的一個應用案例,取得了很好的業務結果,可供相似需求或場景的參考。
人羣圈選引擎中的用戶數據,咱們目前是T+1導入的。這是考慮到人羣相關的指標,變化頻率不是很快,且不少指標(好比用戶標籤)都是離線T+1計算的,所以T+1的數據更新頻度是能夠接受的。後續咱們又基於HybridDB構建了更爲強大的商品圈選引擎。閒魚商品數據相比用戶數據,變化更快。一方面用戶隨時會更新本身的商品,另外一方面,因爲閒魚商品單庫存(售出即下架)的特性,以及其餘緣由,商品狀態會隨時變動。所以咱們的選品引擎,應該儘快感知到這些數據的變化,並在投放層面作出實時調整。咱們基於HybridDB(存儲)和實時計算引擎,構建了更爲強大的「馬赫」實時選品系統。
本文爲雲棲社區原創內容,未經容許不得轉載。