實時計算如何幫助淘寶實現線上「實時選品」?

若有-若無發表於2018-10-29

一、背景介紹

      隨著淘寶內容化的深入發展,實時選品的需求越來越強烈。對於某些實時性要求較高的產品(SPU)而言,運營小二希望自己圈定產品池可以當天實時生效,以供創作者寫文章使用。該需求對選品的實時性要求較高,比較適合流式計算的特點。因此,本文采用Blink實時流計算技術來實現該功能,實際應用中取得較好效果。

二、解決方案

2.1 問題分析

      要實現實時選品的需求,需要解決如下幾個問題:
  • 實時觸發問題:流計算必須要有觸發資料來源,使用者提交的特徵資料儲存在idb中,idb如何與Blink計算流程建立關聯?
  • 中間狀態儲存問題:Blink計算過程中,依據業務場景需要記錄上一次中間計算狀態,如何儲存這些中間狀態,並在需要時實時讀取?
  • 實時生效問題:Blink計算結果需要最終在搜尋引擎生效,Blink如何跟搜尋引擎互動,使計算結果實時生效?
  • 增量問題:如果沒有增量過程,離線全量切換資料期間,會覆蓋部分已更新的資料,入如何增量追資料?
1535089508753-971963be-47df-4129-92d2-3d
     
      針對上述問題,可採用TT+Blink+Hbase+Swift的方式解決。流程中引入TT可解決實時觸發問題,引入Hbase解決中間儲存問題,引入Swift解決實時生效和增量問題。TT、Hbase和Swift介紹如下:
  • TT日誌:阿里日誌採集系統,使用者可以對日誌進行訂閱,TT與idb(資料庫)、Blink有較好支援,是idb和Blink互動的重要媒介。
  • Hbase:開源的非關係型分散式資料庫,與Blink有較好的介面互動,可用於儲存和讀取中間計算狀態。
  • Swift:阿里搜尋事業部自主研發的訊息系統,目前主搜尋實時都是基於該系統進行訊息傳輸的,可基於該系統解決引擎實時生效和增量問題。

2.2 實現流程

      Blink流程被分為“日誌解析節點”、“Query拆分節點”、“請求SP服務節點”、“資料處理節點”、“回寫TT節點”、“Swift訊息節點”6個節點,每次實時計算大致經歷如下幾部分:
1535089790525-80faa00d-4dc6-477b-a0d9-ac
  • 使用者提交選品特徵資料,資料儲存到idb(資料庫)並同步到TT日誌。
  • TT日誌更新會觸發Blink任務,日誌解析節點會先解析TT日誌,獲取選品特徵資料。
  • Query拆分節點先預估SPU數量,然後根據SPU數量確定併發請求數,並拼接Sp引數。
  • 請求Sp服務節點併發請求Sp服務,獲取SPU資訊。
  • 資料計算節點從Hbase中讀取中間狀態資料,根據業務邏輯進行計算。
  • 計算結果回寫Hbase資料庫,用於下次計算使用。
  • 回寫TT節點和Swift訊息節點同時回寫TT和Swift。
  • dump接受Swift訊息,將資料更新至引擎,實現資料實時生效。
  • TT記錄計算結果,回寫ODPS,用於離線全量計算。

2.3 實現細節

      選品功能的實現主要在於Blink任務的開發,開發Blink任務前,需先了解UDF、UDTF、UDAF的概念。
1535090632438-64ca00bd-9300-44be-9e9d-42
      Blink開發主要集中在UDF的實現上,首先根據流計算的過程,劃分出多個計算節點(例如實現流程中的“Query拆分節點”和“請求Sp節點”都是獨立的計算節點),然後針對每個節點的實現邏輯,確定UDF分類,實現UDF類。以“請求Sp節點”為例說明具體實現過程:
  • 節點分析:“請求Sp節點”的業務場景是一個“一對多”的過程,因此採用UDTF型別實現。
  • 封裝UDTF類:該類需要繼承TableFunction,其中T為自己定義的pojo,用於向下個執行節點傳遞。
  • 節點輸出:需要定義自己的Pojo類(上一步提到的T),這樣節點的輸出才能在下個節點中看到。
  • 主函式流程串聯:Blink開發流程需要一個主函式將各個計算節點關聯起來,達到流計算的目的,建議主函式用Scala語言開發,程式碼更加通俗易懂。

2.4 參考程式碼

      以下是“請求Sp節點”的UDTF實現程式碼,基本思路是將請求Sp的返回結果併發輸出到下一級節點上。
public class SearchEngineUdtf extends TableFunction<EngineFields> {

    private static final Logger logger = LoggerFactory.getLogger(SearchEngineUdtf.class);

    /**
     * 請求引擎獲取召回欄位
     * @param params
     */
    public void eval(String params) {
        SpuSearchResult<String> spuSearchResult = SpuSearchEngineUtil.getFromSpuSearch(params);
        if(spuSearchResult.getSuccess()){
            //結果解析
            JSONObject kxuanObj = SpuSearchEngineUtil.getSpResponseJson(spuSearchResult, "sp_kxuan");
            if(null == kxuanObj || kxuanObj.isEmpty()){
                logger.error("sp query: " + spuSearchResult.getSearchURL());
                logger.error(String.format("[%s],%s", Constant.ERR_PAR_SP_RESULT,"get key:sp_kxuan data failed! "));
            }else {
                List<EngineFields> engineFieldsList = SpuSearchEngineUtil.getSpAuction(kxuanObj);
                //併發輸出到資料流
                for(EngineFields engineFields : engineFieldsList){
                    collect(engineFields);
                }
            }
        }else {
            logger.error(String.format("[%s],%s",Constant.ERR_REQ_SP, "request SpuEngine failed!"));
        }

    }
}

2.5 運維釋出

1537953439029-6f3bec9c-3296-4d95-afd5-30
      目前,叢集釋出Blink任務並未完全實現自動化,Blink任務開發完成後,釋出上線流程需要如上幾步完成。任務釋出完成後,可登入yarn上檢視任務節點的執行情況。

三、成果總結

      功能釋出上線後,運營小二圈定的萬級別的SPU選品池,可實現分鐘級生效,對創作者選品效率有很大提升。

四、作者簡介

      作者:崔慶磊,花名:辰昕,阿里巴巴-搜尋事業部-搜尋系統服務平臺-高級開發工程師。
15年加入阿里,主要從事內容化選品服務端開發相關工作,熟悉搜尋引擎服務及流式計算等相關技術
1537952159523-63c9c055-315b-4273-9156-87

如果您有實時報表/實時資料大屏/實時金融風控/實時電商推薦等相關實時化資料處理需求,可以加入如下釘釘交流群!
TB1HzWqB7CWBuNjy0FaXXXUlXXa-157-150.png


相關文章