錦禮平臺,作為一家企業級B2B2C電商平臺,同時服務於企業客戶和企業員工,因此需要遵循企業客戶的政策規範,確保商城內商品符合規定,並提升員工購物體驗。然而,這種獨特的運營模式導致錦禮平臺上商品的可見不可售問題較為突出,對最終消費者的購物體驗和平臺的產品和業務產生了較大的負面影響。
如題,之所以說是小技巧,是因為我們並沒有使用一些高精的技術,只是把多種成熟技術結合加入一些演演算法而已。
以下是我們經歷的3個版本的方案迭代,也代表著一個技術人從技術思維到業務思維的轉變
版本1.0:我們嘗試在不可售商品上增加一個遮罩,標註其不可售的原因,以防止客戶誤操作。然而,這種方法並未完全解決問題,因為消費者可能仍然對某些商品為何不可售(例如為何在錦禮平臺無法購買黃金,或為何看到的商品被列入黑名單)感到困惑。
版本2.0:我們努力提升搜尋的效率,加快不可售商品出庫的速度,並優化商品同步的機制,以降低不可售商品的出現頻率。然而,隨著錦禮平臺不可售規則的擴充套件(如定價規則和價格倒掛限制等),這種客製化化的方式對搜尋團隊來說過於複雜。
版本3.0:隨著我們對消費者需求的深入理解,我們逐漸意識到,雖然我們前期的手段降低了不可售的商品的即使平臺上只出現一個不可售商品,也可能會對消費者的購物體驗造成損失。因此,我們需要運用技術手段將這些商品「隱藏」起來。
圖1 二次過濾工具
在進行到3.0的時候,我們首先推演了以下兩種方案:
然而,上述技術方案的缺點也是顯而易見的:
針對前端預載入可能導致前端業務邏輯複雜化、引入後端輪詢可能出現資料同步問題,我們進行了一系列的優化。
我們引入了暫存器和過濾器兩個重要元件,對原始請求進行合理的排程和處理。
首先,暫存器用於臨時儲存商品資料,這樣前端每次只需要從前端傳送請求到暫存器,就可以獲取到最新的商品資料,避免了後端輪詢的重複請求和超時問題。
其次,過濾器則用於對商品資料進行篩選和處理。在獲取到最新的商品資料後,過濾器會根據一定的規則對資料進行篩選,將符合政策規範和使用者需求的商品資料篩選出來,並將其展示給使用者。同時,對於不符合政策規範或存在違規商品的商品資料,過濾器將其隱藏或標記為不可售,以防止使用者誤操作購買違規商品。
通過這樣的優化,我們既避免了前端業務邏輯複雜化的問題,也解決了後端輪詢可能出現的資料同步問題。同時,改造後的介面仍然是一個普通的REST介面,前端和後端都可以輕鬆理解和使用。
圖2 過濾工具的組成
以下是各個環節的職能介紹
原始請求(orgin request)
常見的列表請求有以下三種:
1、第三方提供的查詢服務,RPC分頁請求,比如搜尋商品列表RPC介面、推薦商品列表RPC介面
2、資料庫查詢,mybatis分頁查詢,可以利用自增主鍵id,做後續請求
3、ES搜尋查詢,ES分頁查詢,捲動查詢
入參:PageParams
出參:PageResult
SDK的實現基於泛型開發,呼叫方需要按照規範自定義實現該方法
過濾器( customer filter )
入參:List< R > sourceData,原始的返回結果列表
出參:List< R > targetData,篩選過濾後的結果列表
SDK的實現基於泛型開發,呼叫方需要按照規範自定義實現該方法
暫存器(storage register )
通過快取中介軟體實現,臨時寄存查詢結果,前端請求過來後優先從暫存器獲取。將請求引數通過演演算法壓縮,保證相同的請求引數,可以得到相同的值,來確定是否是同一查詢條件的請求。
暫存器的key結構如下:
scroll_id : pin&actiivtyCode&uid&查詢入參 MD5壓縮演演算法,
另,查詢入參需要排除掉頁碼以及動態變化的引數
儲存內容:快取補齊分頁後剩餘的資料快照、前端請求頁碼、實際後端請求頁碼
協調器( coordinate )
協調器實現資料的補充和暫存器資料快照的查詢、存入和取出,以及分頁相關資料的更新
1、協調器根據原始前端請求,後端實際請求擴大步長,進行後續資料的拉取
2、前後端固定步長進行請求,比如前端每次請求10條,後端每次請求20條,步長比,可以根據實際情況動態調整
3、請求深度和前後端步長比通過ducc進行控制。 例如:前端每頁請求10條資料,步長比為3,則後端每次請求每頁30條資料;請求深度為2,則如果請求兩次如果仍不符合要求則強制停止。客戶維度客製化請求引數
{
"DEFAULT": {
"deep": 2,
"multiple": 3
},
"行銷測試2": {
"deep": 2,
"multiple": 5
},
"呼鐵福利商城採購賬號": {
"deep": 2,
"multiple": 4
}
}
圖3 資料二次過濾流程圖
我們將資料二次過濾拆分為以下四個階段:
Query階段:
接收前端請求,根據暫存器中資料的大小,決定後端介面請求,後端按前端N倍步長進行RPC請求,將命中的結果,在快取中建立一個優先佇列快照,並通過scroll_id(C維度的快取key)指向它,lastPageNo 指向上次存取的頁碼,realPageNo指向真實存取的頁碼
Filter階段:
讀取過濾規則,進行資料過濾的實現,常用的過濾規則,比如:不可售、無貨、價格高於市場價等,不符合規則的資料直接移除掉
Cache階段:
• 如果過濾後資料小於前端請求步長,則繼續進入Query階段,進行優先佇列快照資料補充
• 如果過濾後資料大於等於前端請求步長,則直接返回pageSize的資料列表,剩餘資料放入優先佇列快照中
• 後端請求深度暫設定為2次,如果兩次後端請求,過濾後的資料仍不滿足前端請求步長,則不再繼續請求
• 如果後端請求多次返回失敗,則及時熔斷,返回暫存器內剩餘資料,且返回結果標識非最後一頁
Fetch階段
通過以上兩個階段,我們可以獲取到符合前端請求步長的資料集,補充其他附屬資訊後進行,返回分頁的資料結構
初次之後查詢資料,在Query階段通過scroll_id找到對應的快照,然後用lastPageNo,realPageNo將原來的查詢語句新增查詢條件( pageNo=realPageNo + 1),在快照中找資料。
技改方案上線後,集中觀測中秋流量,日常千萬級的商品過濾次數,平均每次請求過濾3-4個商品
圖4 二次過濾開啟前和開啟後的效果
圖5 中秋期間錦禮平臺流量
圖6 中秋期間商品過濾的次數
圖7 商品搜尋過濾後的介面效能
在產品迭代演進中,我們堅信,技術能夠為我們的業務帶來無限可能。它能幫助我們創新、優化流程、提升效率。同時,我們也明白,技術並非萬能的。但正是對技術的這種深深敬畏,讓我們始終保持謙遜和開放的心態,使我們始終能找到新的突破口,超越自我。
一個小小的技巧,也可以給業務帶來大大的價值!!!
作者:京東零售 毛辰飛
來源:京東雲開發者社群 轉載請註明來源