全鏈路生產(chǎn)遷移及B/C端數(shù)據(jù)存儲隔離
1.業(yè)務背景
榜單在經(jīng)歷了供給量迅速增長及C端分發(fā)場景多樣化等迭代,數(shù)據(jù)量及峰值流量呈十倍百倍增長,這必然帶來數(shù)據(jù)庫的極大存儲壓力和C端查詢性能降低。為滿足未來各類復雜定制化規(guī)則和億萬級數(shù)據(jù)甄選,綜合引導消費者的購物決策,得物商品榜單生產(chǎn)遷移及B/C端數(shù)據(jù)存儲隔離應運而生。
2.概述
得物榜單作為C端核心導購場景之一,通過建立豐富的規(guī)則矩陣,多維度提供用戶購買參考建議,幫助用戶快速決策并完成商詳轉化。目前涵蓋六種類型包括熱銷榜、新品榜、趨勢榜、種草榜、好評榜及回購榜,主要入口包括商詳、品牌主頁、分類tab、瀑布流、會場、頻道等。
2.1 “圈選”+“排序”是核心:
通過圈品條件圈選出一系列商品,再根據(jù)排序規(guī)則排名后取TOP20商品入選榜單。圈品范圍包括類目、品牌、系列、標簽等,通過【6類模型、N項指標因子】綜合計算排序后的總分代表商品的綜合競爭力,分值越大,代表該商品表現(xiàn)越好。得物榜單基于上述算法模型嚴格把控上榜商品品質,從而幫助用戶根據(jù)自身訴求快速決策。
2.2 是否存在更優(yōu)的排序?
通過對榜單排序邏輯優(yōu)化可針對性提升榜單承接效率,探索一套最佳排序規(guī)則公式需要通過不斷的嘗試,因此整個實驗周期較長,在設計上就需要支持實驗的快速推進。
來看下目前如何實現(xiàn)榜單的創(chuàng)建及生產(chǎn)。
涉及表:
- 基礎表:記錄榜單基礎信息;
- 圈品條件表:記錄榜單圈品維度信息包括類目id、品牌id、系列id、標簽id、商品ids集合等;
- 商品集合表:記錄榜單下關聯(lián)的top20商品id,當前榜單B/C端流量都是走了這個表的查詢;
如何綁定圈品范圍?
- 人工榜單通過后臺新增榜單時綁定撈月規(guī)則或人工直接配置商品ids集合,并同步寫榜單圈品條件表;
- 半自動化榜單通過后臺新增榜單時綁定類目id、品牌id、系列id等維度規(guī)則,并同步寫榜單圈品條件表;
- 自動化榜單通過預先設定的規(guī)則批量寫榜單圈品條件表;
數(shù)據(jù)流轉?
商品后臺新增榜單基礎信息至基礎表,將圈品范圍信息(類目、品牌、系列、標簽、spuIds等)保存至圈品條件表,搜索每兩小時定時從庫中撈取圈品條件表數(shù)據(jù),獲取最新數(shù)據(jù)刷到商品集合表中。
- 搜索數(shù)倉H+1/T+1 dump:搜索離線數(shù)倉通過離線計算排序因子數(shù)據(jù),生成離線寬表;
- 搜索離線圈品排序引擎:對照組榜單由搜索生產(chǎn)。每2小時定時調(diào)度,掃描圈品條件表全量數(shù)據(jù),從寬表中篩選商品并進行排序,排序結果通過DTS數(shù)據(jù)同步回流榜單商品集合表;
- 搜索離線圈品排序引擎:實驗組榜單由商品圈品排序引擎生成,底層實現(xiàn)和搜索大致相同。
3.系統(tǒng)缺陷及解決思路
3.1 鏈路強耦合
商品/搜索存在雙寫榜單商品表場景,由于搜索通過dts數(shù)據(jù)同步方式回流數(shù)據(jù),導致數(shù)據(jù)相互覆蓋甚至主鍵沖突,通過id隔離的方式可以暫時解決。
3.2 重復造輪子
目前榜單商品生產(chǎn)鏈路強依賴搜索,由搜索實現(xiàn)商品圈選及排序,搜索榜單商品生產(chǎn)方式單一,無法滿足榜單圈選/排序規(guī)則定制化供給。而「撈月」作為得物核心選品投放平臺,已經(jīng)具備強大的圈品排序能力。
3.2.1 撈月指標體系
海量選品指標維度(商品基礎信息,活動信息,價格與庫存,流量與轉化等)支撐各業(yè)務,分鐘級別選品實時指標數(shù)據(jù);
- odps離線指標數(shù)據(jù):商品/交易指標進行計算產(chǎn)出離線寬表。
- 實時交易指標:如活動期間GMV,買家數(shù)等交易數(shù)據(jù)。
- 離線DUMP:離線數(shù)倉通過離線計算指標對應值經(jīng)由datawork同步任務將指標值同步至撈月B端ES。
- 實時DUMP:業(yè)務系統(tǒng)/實時數(shù)倉或其他對接模式準實時的通過商品Feature(一些業(yè)務邏輯性強的指標)、DB BinLog或其他方式將數(shù)據(jù)通知到撈月指標中心,再由撈月指標中心將數(shù)據(jù)落到撈月B端ES。
3.2.2 撈月實時選品引擎
分鐘級別執(zhí)行引擎更新選品結果。
3.2.3 撈月排序中心
支持個性化、統(tǒng)計字段、自定義權重配比等多維度復雜升降序排序規(guī)則;也支持用戶特征,進行推薦算法個性化排序。
具體細節(jié)不在本文展開,重點關注撈月指標體系、選品及排序能力在本次遷移中的應用。
針對第一個和第二個問題,我們提出榜單遷移撈月——通過復用撈月現(xiàn)有圈選/排序能力,完成榜單商品生產(chǎn)能力搭建,將榜單生產(chǎn)從搜索側遷移至商品側,移除榜單底層能力搭建對搜索的依賴。
3.3 無法支撐海量數(shù)據(jù)的高并發(fā)讀
未來榜單需支撐類目下沉場景,“類目下沉”即針對目前以類目為維度的榜單,再按品牌、系列、標簽等維度進行榜單延伸。如:跑步鞋熱賣榜下,再細分出耐克跑步鞋、入門跑步鞋、透氣跑步鞋等榜單,更多維度擴充包括人群、風格等。按照笛卡爾積生成方式將任意維度與類目進行兩兩組合,將產(chǎn)生百萬級甚至千萬級別海量數(shù)據(jù),造成極大的存儲壓力。同時,榜單從生產(chǎn)到C端分發(fā),經(jīng)歷榜單商品圈定、審批流及其他狀態(tài)控制,最終能夠在C端成功分發(fā)的榜單數(shù)量有限,每次查詢都會觸發(fā)有效數(shù)據(jù)的實時過濾。隨著榜單數(shù)量的快速增長,必然帶來C端查詢性能降低,如大key、索引失效等,存在性能隱患。榜單在商詳分發(fā),必然伴隨著高并發(fā)讀。
針對這個問題,雖然可以盡量地從優(yōu)化 sql、優(yōu)化索引、緩存等等方面進行優(yōu)化,但總會有到達極限的時候。關于海量數(shù)據(jù)的存儲選型已經(jīng)有非常廣泛的案例,該如何進行存儲選型?存儲選型的目的還是為了我們的使用場景和用戶服務,因此在選型前需要回答一些業(yè)務指標&技術指標方面的問題,以便于我們清楚存儲選型的應用環(huán)境:
- 數(shù)據(jù)量及日增數(shù)據(jù)量:數(shù)據(jù)量在可控范圍內(nèi)日增穩(wěn)定;
- 讀寫偏好:榜單狀態(tài)及上榜商品不頻繁變更,讀多寫少;
- 運行性能要求:并發(fā)量峰值商詳、首頁,低谷像一些二級頁面;
- 查詢復雜度:復雜條件查詢、聚合查詢、join查詢;
- 其他性能要求:實時性要求不高;
結合榜單業(yè)務特征以及海量數(shù)據(jù)和高并發(fā)的特點,可能的解決方案不限于
- 使用緩存的方式通過程序代碼將數(shù)據(jù)直接保存到內(nèi)存中,如ConcurrentHashMap、Caffeine等;或使用緩存框架如Redis等;
- 數(shù)據(jù)庫優(yōu)化:數(shù)據(jù)庫優(yōu)化的方式很多,常見的可以分為:數(shù)據(jù)庫表結構優(yōu)化、SQL語句優(yōu)化、分區(qū)、分表、索引優(yōu)化、使用存儲過程代替直接操作等;
- 使用NoSql技術:HBASE、MongoDB等;
- 使用搜索引擎技術:ElasticSearch等;
設計實踐中,要基于需求、業(yè)務驅動架構,無論選用 DB/NoSQL, 一定是以需求為導向,最終數(shù)據(jù)存儲方案必然是各種權衡的綜合性設計:
- 分庫分表:垂直切分適用于表中存在業(yè)務耦合,且拆分后單表數(shù)據(jù)量依舊很大;水平切分的關聯(lián)查詢性能差;
- HBASE:列存儲分布式數(shù)據(jù)庫,適合TB級別數(shù)據(jù)的實時入庫和快速隨機訪問場景,缺點是查詢僅能通過rowkey和range檢索,不支持復雜查詢;
- MongoDB:文檔型NoSql,適合非結構化數(shù)據(jù)存儲,表結構可隨意變更,因此插入效率高,同樣的也是不支持復雜查詢?nèi)缍啾聿樵兊龋?/li>
- ElasticSearch:寫入性能低,實時性低,但是通過為所有字段添加索引可支持復雜的聚合查詢和條件查詢。
綜合考慮,B/C端數(shù)據(jù)存儲隔離成為當下性價比最高的解決方案。
以下將闡述本次實踐的詳細實施點。
4.技術實施點
整體改造將分為兩個階段進行:首先完成鏈路改造,即榜單生產(chǎn)遷移撈月,待數(shù)據(jù)驗證通過進行第二階段的存儲改造,即B/C端數(shù)據(jù)存儲隔離。
4.1 鏈路改造
4.1.1 撈月指標創(chuàng)建
撈月需支持榜單實驗能力,因此在榜單對照組通用指標的基礎上新增實驗組通用指標,同時預留對應的實驗組排序規(guī)則??芍С滞愋桶駟瓮瑫r段進行一項實驗,實驗結束后根據(jù)實驗結果修改通用算法模型。實驗指標可在多次實驗復用,不會造成撈月指標數(shù)量的遞增。
- 對照組熱銷榜分數(shù)指標(best_seller_score) :根據(jù)7日內(nèi)銷量與成交金額計算綜合排序
- 對照組新品榜分數(shù)指標(new_product_score) :根據(jù)上架時間和收藏人數(shù)等指標綜合計算排序
- 對照組趨勢榜榜分數(shù)指標(soare_score) :根據(jù)近7日銷量和收藏人數(shù)等指標綜合計算排序
- 對照組種草榜分數(shù)指標(collect_score) :根據(jù)當日新增商品銷量等指標綜合計算排序
- 對照組好評榜分數(shù)指標(favorite_score) :根據(jù)商品好評率和好評數(shù)等指標綜合計算排序
- 對照組回購榜分數(shù)指標(rebuy_score) :根據(jù)商品年度累計回購人數(shù)等指標綜合計算排序
- 實驗組熱銷榜分數(shù)指標(best_seller_score_test):根據(jù)累計付款人數(shù)和收藏人數(shù)等指標綜合計算排序
- 實驗組新品榜分數(shù)指標(new_product_score_test) :根據(jù)上架時間、點擊、收藏、銷量等指標計算綜合排序
- 實驗組趨勢榜榜分數(shù)指標(soare_score_test) :根據(jù)近7日銷量和收藏人數(shù)等指標綜合計算排序
- 實驗組種草榜分數(shù)指標(collect_score_test) :根據(jù)當日新增商品銷量等指標綜合計算排序
- 實驗組組好評榜分數(shù)指標(favorite_score_test) :根據(jù)商品好評率和好評數(shù)等指標綜合計算排序
- 實驗組組回購榜分數(shù)指標(rebuy_score_test) :根據(jù)商品年度累計回購人數(shù)等指標綜合計算排序
4.1.2 排序規(guī)則創(chuàng)建
- 對照組熱銷榜排序規(guī)則
(sort_best_seller)=best_seller_score * 100% desc - 對照組新品榜排序規(guī)則
(sort_new_product)=new_product_score * 100% desc - 對照組趨勢榜排序規(guī)則
sort_soare)=soare_score * 100% desc - 對照組種草榜排序規(guī)則
(sort_collect)=collect_score * 100% desc - 對照組好評榜排序規(guī)則
(sort_favorite)=favorite_score * 100% desc - 對照組回購榜排序規(guī)則
(sort_rebuy)=rebuy_score * 100% desc - 實驗組熱銷榜排序規(guī)則
(sort_best_seller_test)=best_seller_score_test * 100% desc - 實驗組新品榜排序規(guī)則
(sort_new_product_test)=new_product_score_test * 100% desc - 實驗組趨勢榜排序規(guī)則
(sort_soare_test)=soare_score_test * 100% desc - 實驗組種草榜排序規(guī)則
(sort_collect_test)=collect_score_test * 100% desc - 實驗組好評榜排序規(guī)則
(sort_favorite_test)=favorite_score_test * 100% desc - 實驗組回購榜排序規(guī)則
(sort_rebuy_test)=rebuy_score_test * 100% desc
4.1.3 指標、排序規(guī)則同步ES供后續(xù)選品及排序
改造后全鏈路數(shù)據(jù)流轉如圖所示:
- 榜單創(chuàng)建:圈品條件寫入撈月選品規(guī)則數(shù)據(jù)表;
- 排序規(guī)則:超時中心調(diào)用排序引擎更新每個商品的排序分同步撈月B端es;
- 實時選品:圈品引擎分鐘級別掃描待執(zhí)行的選品規(guī)則數(shù)據(jù),從底表中篩選符合條件的商品并生成選品集id同步撈月B端es;
- 完成綁定:撈月es將選品結果回流到榜單商品表,并將選品集id回流到榜單基礎表,榜單id和選品集id綁定完成;
- 商品更新:監(jiān)聽撈月選品集結果變更消息。
4.2 存儲改造
4.2.1 B端數(shù)據(jù)源-撈月B端ES
在鏈路改造環(huán)節(jié)我們已經(jīng)完成了榜單和撈月集的綁定,因此查榜單下的商品就等同于查撈月集下的商品。
具體邏輯如下:
那么是否完全可以復用撈月存儲結構,釋放榜單商品集獨立存儲的空間?首先根據(jù)B/C查詢場景劃分為正向鏈路和反向鏈路。正向鏈路,也就是從榜單id獲取到撈月集id,從撈月es根據(jù)撈月集id獲取撈月商品結果集,B端查詢方式均為正向鏈路,因此可以復用撈月存儲結構。反向鏈路,即從撈月es根據(jù)商品id獲取其所在的撈月集ids,從撈月集ids查詢榜單ids。由于撈月集id暫無場景打標,只能遍歷撈月集ids判斷是否屬于某一個榜單,查詢成本極高,榜單在C端的核心分發(fā)場景商詳便是滿足了這個鏈路特征,當然我們可以通過建立撈月集場景打標體系、構建榜單商品ES大寬表的方式來解決問題,有沒有性價比更高的解決方式?
4.2.2 C端數(shù)據(jù)源-榜單集合mysql表
針對當前業(yè)務規(guī)模及C端查詢復雜度,考慮采用B/C端查詢隔離的方式進行實現(xiàn)。撈月選品結果變更、榜單顯示/隱藏、審核通過/駁回、生效/失效都會影響榜單的分發(fā)狀態(tài)。最終能在C端分發(fā)的榜單十分有限,為避免在C端做大量數(shù)據(jù)的實時過濾,降低索引失效和大key風險,原B/C端公用數(shù)據(jù)源榜單集合表僅存儲可分發(fā)榜單商品數(shù)據(jù)供C端查詢,實現(xiàn)方式及其簡單:在狀態(tài)變更及撈月結果集變更時觸發(fā)實時更新/刪除榜單集合表即可,整個改造過程無需改動C端代碼,僅通過幾行業(yè)務代碼,就將DB存儲數(shù)據(jù)量量級降至原來的40%,可支撐未來兩至三年數(shù)據(jù)量的穩(wěn)定增長。
4.3 灰度設計
相對于功能完整性,如何實現(xiàn)平滑穩(wěn)定的切流是整個項目中比較重要的一環(huán)。
為了實現(xiàn)用戶無感切換,降低切換過程中可能出現(xiàn)的故障對系統(tǒng)的影響,通過多個灰度讀寫開關保證切流過程的平滑和穩(wěn)定性,整個過程可,做到“隨切隨?!薄Uw灰度分階段逐步推進,采用:
- “增量數(shù)據(jù)維護-數(shù)據(jù)驗證-全量數(shù)據(jù)刷數(shù)-數(shù)據(jù)驗證-灰度切流-數(shù)據(jù)驗證”的方式
- 各個階段均有補償策略或回滾方案,風險可控性較高
即采用先進行增量數(shù)據(jù)維護,待增量數(shù)據(jù)check+fix通過后,進行全量數(shù)據(jù)刷數(shù),待全量數(shù)據(jù)check+fix完成后,實施灰度讀切流,并進行雙讀check,一旦出現(xiàn)問題則開關關閉;寫切流采用先寫臨時表,臨時表數(shù)據(jù)驗證通過后切換寫主表,一旦出現(xiàn)故障或臟數(shù)據(jù),預案啟動,可保證數(shù)據(jù)一小時內(nèi)回滾。具體來說,我們關注以下四點:
4.3.1 數(shù)據(jù)維護
首先進行風險評估,涉及榜單需綁定撈月集數(shù)量為N,以每個撈月集限制M個SPU為準,選品結果集總數(shù)量可達N*M,寫入高流量將造成ES實例整體性能急劇下降。另一方面,數(shù)據(jù)修復成本極高,綁定錯誤只能重新綁定新的撈月集,需全量刪除舊撈月集后再綁定新?lián)圃录?,兩次寫入成本極高。因此先進行增量數(shù)據(jù)維護,待增量數(shù)據(jù)check+fix通過后進行全量數(shù)據(jù)分批刷數(shù)。
4.3.2 讀/寫切流
- 讀切流:讀切流的核心是將B端數(shù)據(jù)源切換到撈月ES。這一步執(zhí)行的節(jié)點十分關鍵,需放在鏈路改造完成,存儲改造開始之前進行。原因是如果先進行了存儲改造再執(zhí)行切流,由于存儲改造完成后rank_list表僅存儲可分發(fā)榜單,那么切流后一旦出現(xiàn)問題應立刻切換回老鏈路,原B/C端公用數(shù)據(jù)源rank_list表數(shù)據(jù)已經(jīng)不完整,完全不能滿足B端使用,無法快速止血,只能快速定位問題并修復上線。確定執(zhí)行時間節(jié)點后,寫好開關并進行雙讀check,發(fā)現(xiàn)問題切換回原鏈路即可。
- 寫切流:搜索更新榜單商品開關關閉后,撈月選品結果全量寫入榜單集合表的風險較大,通過建立榜單集合臨時表,待臨時表數(shù)據(jù)驗證通過后切換主表。
4.3.3 數(shù)據(jù)校驗
雙讀check、不定時全量數(shù)據(jù)check+fix 、增量數(shù)據(jù)check+fix 、應用監(jiān)控、日志告警埋點等;
4.3.4 數(shù)據(jù)訂正
針對灰度過程可能出現(xiàn)的所有數(shù)據(jù)錯誤預備對應數(shù)據(jù)訂正接口。多想一步,如果在寫切流過程中切換寫主表后出現(xiàn)未識別到的數(shù)據(jù)錯誤,如何快速止血?在遷移的過程中我們暫時保留搜索更新榜單商品的能力作為數(shù)據(jù)修復預案,可在一小時內(nèi)完成數(shù)據(jù)修復。
具體灰度切流推進流程如下:
經(jīng)歷兩個星期的灰度,已移除對搜索的依賴實現(xiàn)全鏈路閉環(huán),依照灰度方案通過切流開關及預案等手段確保“隨切隨?!?,上線期間零故障。
5.總結
綜上所述,榜單通過生產(chǎn)遷移徹底解決了一直以來榜單底層能力支撐不足的痛點。完成鏈路合并后,借助撈月圈品排序能力降低未來各類復雜定制化供給場景的維護成本,功能上線后已提升榜單各類業(yè)務迭代效率提升50%以上。并通過B/C端數(shù)據(jù)存儲隔離,以極低的改造成本降低表存儲成本60%。
在這個基礎上,思考是否有更多的發(fā)力點:結合當前系統(tǒng)現(xiàn)狀和未來的可能性,結合業(yè)務規(guī)劃,圍繞用戶對平臺榜單預期,未來將演變出多維度(內(nèi)容、品牌、sku、spu等)榜單通用生產(chǎn)引擎,在供給充足基礎上實現(xiàn)場景化個性化分發(fā)。
以上就是我們在得物商品榜單生產(chǎn)改造探索實踐中的一些經(jīng)驗和總結,分享出來希望對閱讀本文的你有一些幫助!