AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

轉轉搜推排序服務的響應對象序列化優化

來源: 責編: 時間:2024-09-10 09:51:11 112觀看
導讀1 優化背景為了提升搜索推薦系統的整體工程效率和服務質量,搜索推薦工程團隊對系統架構進行了調整。將原本的單一服務架構拆分為多個專門化的獨立模塊,分別為中控服務、召回服務和排序服務。在新的架構中,中控服務負責統

1 優化背景

為了提升搜索推薦系統的整體工程效率和服務質量,搜索推薦工程團隊對系統架構進行了調整。將原本的單一服務架構拆分為多個專門化的獨立模塊,分別為中控服務、召回服務和排序服務。FZc28資訊網——每日最新資訊28at.com

在新的架構中,中控服務負責統籌協調請求的分發和流量控制,召回服務用于搜索意圖和用戶行為分析并計算返回搜索推薦候選商品集合,而排序服務則進一步對這些候選商品進行精排序,以達到更好的最終展示結果的相關性、點擊率、轉化率等目標。FZc28資訊網——每日最新資訊28at.com

在推薦系統接入新的排序服務過程中,發現與原有邏輯相比,微詳情頁場景的響應時間顯著增加了大約10毫秒,主要問題出現在接口請求和響應的環節上。FZc28資訊網——每日最新資訊28at.com

同樣,搜索系統在接入排序服務時也遇到了類似的情況。與原有邏輯相比,響應時間增加了近20毫秒,導致無法達到上線的性能標準。FZc28資訊網——每日最新資訊28at.com

例如,搜索排序服務在本地執行時的時間為60毫秒,但通過遠程調用時,執行時間卻增加到接近80毫秒,兩者之間的差異接近20毫秒。FZc28資訊網——每日最新資訊28at.com

為了解決這些性能問題,需要對這些延遲的原因進行深入分析和優化。FZc28資訊網——每日最新資訊28at.com

2 問題分析

問題現象是調用方等待耗時和服務方執行耗時相差較大,所以問題主要出現在遠程調用過程,接下來就是分析這個過程FZc28資訊網——每日最新資訊28at.com

遠程調用可以理解為一種實現遠程代碼與本地接口調用相一致體驗的開發模式FZc28資訊網——每日最新資訊28at.com

遠程調用一般通過動態代理實現,通過調用動態方法將調用方法標識和調用參數序列化為字節碼,再通過通信協議請求服務端FZc28資訊網——每日最新資訊28at.com

服務端解析方法標識和反序列化參數字節碼到實體參數對象,再反射的方式調用方法標識對應的方法FZc28資訊網——每日最新資訊28at.com

該方法返回結果(即響應對象)序列化,并返回給調用方,調用房完成反序列化響應對象,返回給代理調用者FZc28資訊網——每日最新資訊28at.com

整個過程較為耗時的部分為序列化/反序列化、網絡IO、本地調用,一般為ms級別。FZc28資訊網——每日最新資訊28at.com

調用動態方法和反射耗時相對不高,一般為us級別。如下圖所示。FZc28資訊網——每日最新資訊28at.com

圖片圖片FZc28資訊網——每日最新資訊28at.com

調用動態方法耗時相比于其他過程一般可忽略不計,服務端本地調用邏輯與原服務已經對齊,也不在本次考慮之內。FZc28資訊網——每日最新資訊28at.com

接下來就是要分析序列化和網絡IO請求開銷在各環節的占比。選擇skynet來定位序列化和網絡環節的耗時FZc28資訊網——每日最新資訊28at.com

skynet是公司架構組提供的分布式鏈路追蹤工具,通過鏈路中攜帶的上下文,可以記錄經過的服務接口的日志信息FZc28資訊網——每日最新資訊28at.com

skynet的基本概念是一次完整請求鏈路稱為trace,一次遠程調用過程稱為spanFZc28資訊網——每日最新資訊28at.com

以推薦微詳情頁某次請求為例,查詢單次請求的調用過程,可以看到下圖所示,排序服務調用過程中的遠程耗時與本地耗時差值約為 4msFZc28資訊網——每日最新資訊28at.com

圖片圖片FZc28資訊網——每日最新資訊28at.com

通過span攜帶的日志,可以看到以下數據FZc28資訊網——每日最新資訊28at.com

指標
FZc28資訊網——每日最新資訊28at.com

耗時
FZc28資訊網——每日最新資訊28at.com

說明
FZc28資訊網——每日最新資訊28at.com

scf.request.serialize.cost
FZc28資訊網——每日最新資訊28at.com

0.242ms
FZc28資訊網——每日最新資訊28at.com

請求序列化耗時
FZc28資訊網——每日最新資訊28at.com

scf.request.deserialize.cost
FZc28資訊網——每日最新資訊28at.com

0.261ms
FZc28資訊網——每日最新資訊28at.com

請求反序列化耗時
FZc28資訊網——每日最新資訊28at.com

scf.response.deserialize.cost
FZc28資訊網——每日最新資訊28at.com

0.624ms
FZc28資訊網——每日最新資訊28at.com

響應反序列化耗時
FZc28資訊網——每日最新資訊28at.com

scf.response.serialize.cost
FZc28資訊網——每日最新資訊28at.com

約0.624ms
FZc28資訊網——每日最新資訊28at.com

響應序列化耗時,skynet未提供,可以認為與反序列化時間差異不大
FZc28資訊網——每日最新資訊28at.com

可見,耗時問題主要集中在響應過程階段。如果要計算遠程耗時與本地耗時的差異為20毫秒的開銷情況,可以結合上述日志數據進行線性計算和整理,得出各個過程的近似耗時及其占比,如下圖所示。FZc28資訊網——每日最新資訊28at.com

搜索與推薦的區別在于,搜索的請求階段不傳輸特征,因此響應過程的耗時占比更高。因此,需要優先考慮減少響應過程的耗時。FZc28資訊網——每日最新資訊28at.com

圖片圖片FZc28資訊網——每日最新資訊28at.com

在整個響應過程中,序列化和網絡 I/O 的耗時各占一半。影響 I/O 耗時的因素之一是網絡環境和機器配置,另一個因素是序列化后對象的長度。FZc28資訊網——每日最新資訊28at.com

通過與運維團隊溝通,我們了解到部分機器使用的是千兆網卡,而我們傳輸的對象長度通常都在 MB 級別,這對耗時有一定的影響。FZc28資訊網——每日最新資訊28at.com

網絡問題可以統一整理后提交給運維團隊調整機器配置來解決,而我們的主要精力應放在優化序列化過程上。FZc28資訊網——每日最新資訊28at.com

接下來是對響應對象的序列化過程分析FZc28資訊網——每日最新資訊28at.com

首先需要了解響應對象數據結構,響應對象是一個泛型類,以支持不同類型的ID,如下所示,包括:FZc28資訊網——每日最新資訊28at.com

  • 狀態值,判斷結果正?;虍惓?/li>
  • RankResult對象

主要存儲約500長度的RankResultItem列表,每個Item對象需要返回商品ID,并以Map的形式返回模型日志、模型打分結果及部分特征FZc28資訊網——每日最新資訊28at.com

請求攜帶的其他信息,如A/B測試實際命中分組名的集合等等FZc28資訊網——每日最新資訊28at.com

  • 異常日志

如以下代碼所示FZc28資訊網——每日最新資訊28at.com

class RankResponse<T> {    int status;    RankResult<T> result;    String errorMsg;} class RankResult<T> {    List<RankResultItem<T>> items;    Map<String, Object> others;} class RankResultItem<T> {    T id;    Map<String, Object> features; // 回傳特征    Map<String, String> metric;     // 模型日志    Map<String, Double> results;  // 模型結果}

優化前,搜索排序服務采用了架構組提供的 SCFV4 序列化方法。FZc28資訊網——每日最新資訊28at.com

SCFV4 是一種最終輸出字節碼的序列化方式,它會對所有被 @SCFSerializable 注解標注的業務數據傳輸對象預編譯序列化和反序列化方法。對于 Java 的基礎類(如 List、Map 等)和基本類型(如 Integer 等),SCFV4 也預設了相應的序列化和反序列化方法。FZc28資訊網——每日最新資訊28at.com

在序列化執行時,SCFV4 根據對象的數據結構層次逐層遍歷,調用每個子成員對象的序列化方法,最終輸出字節碼。反序列化的過程與之類似。FZc28資訊網——每日最新資訊28at.com

SCFV4 序列化的特點如下:FZc28資訊網——每日最新資訊28at.com

  • 與 JSON 相比,反序列化后的類型較為安全,但不能完全保證類型一致性。例如,不論輸入的 Map 是何種類型,反序列化后都會變為 HashMap。
  • 對泛型類型和基本類型的序列化過程進行了優化,對于數據大小在 KB 級別的對象,性能表現良好。
  • 作為一種與SCF框架緊密集成的序列化方法,能夠與框架中的其他模塊無縫協作,從而簡化開發流程,減少開發者的工作量。
  • 在代碼編寫時,需要通過注解的方式對序列化對象類進行預設定,版本只能向后兼容。
  • 有時存在異常處理不夠友好的問題,異常信息無法直接反映業務代碼中的問題,定位序列化問題時,往往需要依賴經驗進行判斷。

下面回到排序響應對象,分析響應對象的序列化過程,將過程梳理到下圖:FZc28資訊網——每日最新資訊28at.com

圖片圖片FZc28資訊網——每日最新資訊28at.com

可以看到,一次序列化過程可能需要對多達 500 次的商品日志 Map、商品得分 Map 和商品 ID 進行序列化。FZc28資訊網——每日最新資訊28at.com

由于日志對象的數據規模遠大于其他類型的對象,因此我們可以假設,序列化的主要開銷來自于序列化特征日志 Map 的耗時。FZc28資訊網——每日最新資訊28at.com

在相關的 MapSerializer 類中可以發現,序列化 Map 時不僅需要解析 Key-Value 的數據類型,還大量調用了 String.getBytes() 方法。FZc28資訊網——每日最新資訊28at.com

假設特征日志的總長度約為 1MB,在本地測試中,getBytes 方法的耗時大約為 10 毫秒,這與我們的預期一致。因此,我們的優化思路應重點放在優化特征日志的序列化過程中。FZc28資訊網——每日最新資訊28at.com

3 設計方案

3.1 優化方案一

首先想到的優化方案是通過不傳輸日志來完全節省日志的序列化時間。針對這一思路,有兩種具體的實現方式:FZc28資訊網——每日最新資訊28at.com

  • 在排序服務中直接打印日志,并由排序服務直接將日志上報到 Kafka。
  • 使用 Redis 緩存日志,從而減少序列化和傳輸的開銷。

如果直接打印日志,每個請求最多需要打印 1000 條日志。經過與數據團隊的討論,我們得出了以下結論:FZc28資訊網——每日最新資訊28at.com

  • 數據采集:直接打印日志將導致每天的日志量達到約 15TB。以 15 臺機器的集群計算,每分鐘需要采集 1GB 的數據,這會給日志采集系統和我們的服務 I/O 帶來巨大壓力。
  • 數據存儲:每天新增的數據量將達到 50-60TB。由于每天生成的 15TB 數據需要先采集再清洗,這樣就會產生兩份數據。每份數據有 3 個副本,總共是 6 份數據。最終在 Hadoop 集群中還會有 2 份備份,約 45TB。即使使用 Hive 表和 Parquet+GZ 格式壓縮,數據量也大約在 5-10TB 之間。

經過分析,我們認為改用直接打印日志的方案并不是最優選擇,因此沒有實施。FZc28資訊網——每日最新資訊28at.com

如果將日志異步寫入Redis,并在重排序時從Redis中讀取,就能有效地優化性能。通過設置日志緩存的過期時間為 1 秒,可以滿足排序到重排序之間的時間間隔要求。FZc28資訊網——每日最新資訊28at.com

在這種情況下,Redis的預估使用量為:每請求日志大小 × QPS × 過期時間 = 2MB × 500 × 1秒 = 1GB。FZc28資訊網——每日最新資訊28at.com

由于成本相對可控,因此我們決定嘗試這一方法。FZc28資訊網——每日最新資訊28at.com

圖片圖片FZc28資訊網——每日最新資訊28at.com

如上圖所示,本次方案的目標是將紅色部分的輸入特征日志處理邏輯提前到模型輸入特征處理之后,并引入 Redis 緩存邏輯,同時實現異步執行。FZc28資訊網——每日最新資訊28at.com

然而,這里遇到了一個挑戰:輸入特征集合是由預測框架生成的,其生成時間點只有框架內部知道。因此,日志處理過程必須在預測框架內部執行。FZc28資訊網——每日最新資訊28at.com

在深入討論之前,先介紹一下預測框架和排序框架之間的關系。預測框架的主要職責是管理和執行算法模型,它生成模型所需的輸入特征,并基于這些特征進行預測。排序框架則利用預測框架的輸出,對商品或內容進行排序,以優化最終展示給用戶的結果。FZc28資訊網——每日最新資訊28at.com

雖然預測框架和排序框架在功能上是相互獨立的,但它們之間密切合作。排序框架依賴預測框架提供的預測結果,而預測框架則處理來自排序框架的輸入特征。然而,預測框架的主要任務是執行算法模型,與具體的業務邏輯無關。因此,在預測框架中引入排序框架的業務邏輯會導致相互依賴,這違背了各自的設計初衷,也不利于系統的可維護性和擴展性。FZc28資訊網——每日最新資訊28at.com

因此,我們需要一種方式來解耦兩者,實現日志處理邏輯的同時,不破壞架構設計。FZc28資訊網——每日最新資訊28at.com

如果在預測框架內部執行日志處理,就需要將排序商品列表、排序上下文、日志處理插件、線程池、Redis 客戶端對象、過期時間配置等所有組件都傳遞到預測框架中。這將導致排序框架與預測框架的相互依賴,而這種雙向依賴是不合理的,因為預測框架不僅服務于排序框架,還用于通用推薦和定價框架。FZc28資訊網——每日最新資訊28at.com

為了解決這個問題,我們可以通過傳遞 Consumer 對象來實現解耦。預測框架作為模型輸入特征的生產者,排序框架作為消費者。具體來說,排序框架可以實現一個指定日志處理邏輯的 Consumer 接口。當預測框架生成輸入特征集合后,調用 accept 方法來完成日志處理。FZc28資訊網——每日最新資訊28at.com

為了便于異步處理,我們在排序框架中定義了一個 IFutureConsumer 接口,該接口支持獲取 Future 方法,用于在排序框架中等待日志處理完成。同時,預測框架接收到的仍然是一個標準的 Consumer 接口對象。FZc28資訊網——每日最新資訊28at.com

這種方法確保了預測框架和排序框架之間的解耦,明確了各自的職責,避免了雙向依賴,使系統更加靈活和可擴展。FZc28資訊網——每日最新資訊28at.com

interface IFutureConsumer<T> extend Consumer<T> {    // accpet(T t)     Future<?> getFuture();}

預測框架生成輸入特征并傳遞給排序框架。FZc28資訊網——每日最新資訊28at.com

// 預測框架生成輸入特征T inputFeatures = ...;// 調用排序框架的日志處理邏輯IFutureConsumer<T> consumer = ...; // 由排序框架提供consumer.accept(inputFeatures);

排序框架處理日志。FZc28資訊網——每日最新資訊28at.com

public class HandleLogConsumer<T> implements IFutureConsumer<T> {    private Future<?> future;    @Override    public void accept(T t) {        // 異步處理日志邏輯        this.future = executorService.submit(() -> {            // 處理日志邏輯        });    }    @Override    public Future<?> getFuture() {        return this.future;    }}

整個過程如下圖所示:FZc28資訊網——每日最新資訊28at.com

圖片FZc28資訊網——每日最新資訊28at.com

另外本方案使用了Redis的哈希(hash)數據結構進行存儲,原因是在搜索服務中,每次請求都需要刷新結果緩存,這也意味著需要同時刷新相關的日志緩存。然而,搜索服務并不知道具體有哪些 infoid 已經被存儲,如果使用字符串(string)結構來存儲這些日志數據,很難做到全量刷新,因為無法有效地管理和定位所有存儲的鍵值對。FZc28資訊網——每日最新資訊28at.com

相比之下,使用哈希(hash)結構存儲日志信息有明顯的優勢。我們可以使用 ctr、cvr、info 等作為哈希表的關鍵字前綴,并以請求的 MD5 值作為后綴。這種方式只需要刷新 2~3 個哈希鍵(key),就可以覆蓋所有相關的日志數據。這種方法不僅簡化了緩存刷新操作,而且更高效,因為只需操作少量的哈希鍵即可完成全量刷新,適合搜索服務的需求。FZc28資訊網——每日最新資訊28at.com

推薦側在找靚機微詳情頁場景先行接入了此方案,額外耗時由14ms優化至4msFZc28資訊網——每日最新資訊28at.com

但隨后發現了兩個問題:FZc28資訊網——每日最新資訊28at.com

隨著首頁推薦等主要場景的接入,后處理過程中獲取日志過程耗時達到了7ms以上,原因是寫qps較高(單redis-server節點近7w qps),日志數據又屬于bigkey(1k以上),redis-server極易發生阻塞,擴容后仍在3ms左右水平搜索測試耗時并未明顯下降,讀取和刷緩存過期時間也帶來了額外的成本。FZc28資訊網——每日最新資訊28at.com

總結FZc28資訊網——每日最新資訊28at.com

  • 此方案是對Redis性能過于樂觀,在處理高qps + bigkey的場景性能無法滿足要求,后續需要經常關注單點qps并評估擴容,維護成本也高
  • 業務過多的感知框架實現邏輯,有些操作甚至需要業務干預,如手動刷新過期時間等,接入過程體驗不夠友好,負擔過重

3.2 優化方案二

在本地打印日志和緩存日志的方案不可行后,我們只能重新考慮通過響應對象將日志數據傳回調用方的方案。以下是幾種可行的思路:FZc28資訊網——每日最新資訊28at.com

  • 本地緩存日志數據:將日志數據暫時緩存到本地,等待重排序完成后,再請求同一臺機器取出所需的日志數據。
  • 分步返回數據:先返回排序后的模型得分部分,再異步返回日志數據部分。
  • 日志異步轉換和壓縮:在預測階段,將日志數據異步轉換為字節數組并進行壓縮,序列化時直接返回這些字節數據。在整個搜索推薦流程完成后,再將要下發的topN商品的日志數據解壓并轉換回字符串。

經過評估,前兩種方案雖然具有一定的可行性,但需要調用方進行較多的開發支持,實施周期較長。此外,這些方案還需考慮更復雜的容災處理設計,例如應對因重啟或超時導致的日志丟失,以及緩存引起的 GC 問題。為了規避這些風險,我們決定嘗試第三種方案。FZc28資訊網——每日最新資訊28at.com

為了能實現僅在需要時,即取商品列表topN并打印后端日志時,才將日志從bytes轉回String,在響應RankResultItem增加了LazyMetric數據類型,利用延遲加載機制,減少了不必要的數據處理和傳輸開銷,數據結構如下:FZc28資訊網——每日最新資訊28at.com

class RankResultItem {    Map<String, LazyMetric> lazyMetricMap;} class LazyMetric {    byte[] data; // 編碼后的字符串數據    byte compressMethodCode; // 壓縮類型     LazyMetric(String str){        // string2bytes    }      String toString() {        // bytes2string    }}

日志生產及獲取過程調整為:FZc28資訊網——每日最新資訊28at.com

圖片圖片FZc28資訊網——每日最新資訊28at.com

可以看出,String 轉 bytes 的編碼過程耗時已經在模型執行時并行處理中被優化掉了。在從模型預測模塊到 topN 節點的整個執行過程中,系統始終攜帶的是 bytes 類型的數據。只有在 topN 節點完成了所有搜索推薦流程需要準備返回商品時,才會主動調用 toString 方法將 bytes 轉回 String,而其他商品的日志數據則會被直接丟棄。這樣一來,decode 的次數從 500 次減少到了 10 次(假設 N 一般為 10)。整個過程對業務側的集成并不復雜,開啟功能后,排序框架就會自動將日志數據轉存到 LazyMetricMap 中。中控服務隨后可以從每個 Item 的 LazyMetricMap 中取出 LazyMetric 對象,并在合適的時機調用 toString 方法,提升搜索推薦業務整體開發效率。壓縮過程選擇了java自帶的gzip和zlib兩種方法進行測試,測試結果如下:FZc28資訊網——每日最新資訊28at.com

方法
FZc28資訊網——每日最新資訊28at.com

序列化時間
FZc28資訊網——每日最新資訊28at.com

反序列化時間
FZc28資訊網——每日最新資訊28at.com

總時間
FZc28資訊網——每日最新資訊28at.com

數據大小 (bytes)
FZc28資訊網——每日最新資訊28at.com

壓縮比率
FZc28資訊網——每日最新資訊28at.com

【SCFV4】原方法
FZc28資訊網——每日最新資訊28at.com

1.70ms
FZc28資訊網——每日最新資訊28at.com

1.28ms
FZc28資訊網——每日最新資訊28at.com

2.98ms
FZc28資訊網——每日最新資訊28at.com

1,192,564
FZc28資訊網——每日最新資訊28at.com

0.8336
FZc28資訊網——每日最新資訊28at.com

【SCFV4】metric日志直接轉bytes傳輸
FZc28資訊網——每日最新資訊28at.com

1.46ms
FZc28資訊網——每日最新資訊28at.com

0.74ms
FZc28資訊網——每日最新資訊28at.com

2.20ms
FZc28資訊網——每日最新資訊28at.com

1,216,565
FZc28資訊網——每日最新資訊28at.com

0.8504
FZc28資訊網——每日最新資訊28at.com

【SCFV4】metric日志zlib轉bytes傳輸
FZc28資訊網——每日最新資訊28at.com

1.15ms
FZc28資訊網——每日最新資訊28at.com

0.73ms
FZc28資訊網——每日最新資訊28at.com

1.88ms
FZc28資訊網——每日最新資訊28at.com

472,065
FZc28資訊網——每日最新資訊28at.com

0.3300
FZc28資訊網——每日最新資訊28at.com

【SCFV4】metric日志gzip轉bytes傳輸
FZc28資訊網——每日最新資訊28at.com

1.30ms
FZc28資訊網——每日最新資訊28at.com

0.77ms
FZc28資訊網——每日最新資訊28at.com

2.07ms
FZc28資訊網——每日最新資訊28at.com

490,065
FZc28資訊網——每日最新資訊28at.com

0.3425
FZc28資訊網——每日最新資訊28at.com

【Hessian】原方法
FZc28資訊網——每日最新資訊28at.com

2.33ms
FZc28資訊網——每日最新資訊28at.com

3.45ms
FZc28資訊網——每日最新資訊28at.com

5.78ms
FZc28資訊網——每日最新資訊28at.com

1,165,830
FZc28資訊網——每日最新資訊28at.com

0.8149
FZc28資訊網——每日最新資訊28at.com

【Hessian】metric日志直接轉bytes傳輸
FZc28資訊網——每日最新資訊28at.com

1.00ms
FZc28資訊網——每日最新資訊28at.com

3.80ms
FZc28資訊網——每日最新資訊28at.com

4.80ms
FZc28資訊網——每日最新資訊28at.com

1,168,143
FZc28資訊網——每日最新資訊28at.com

0.8165
FZc28資訊網——每日最新資訊28at.com

【Hessian】metric日志zlib轉bytes傳輸
FZc28資訊網——每日最新資訊28at.com

0.61ms
FZc28資訊網——每日最新資訊28at.com

1.46ms
FZc28資訊網——每日最新資訊28at.com

2.07ms
FZc28資訊網——每日最新資訊28at.com

422,513
FZc28資訊網——每日最新資訊28at.com

0.2953
FZc28資訊網——每日最新資訊28at.com

【Hessian】metric日志gzip轉bytes傳輸
FZc28資訊網——每日最新資訊28at.com

0.59ms
FZc28資訊網——每日最新資訊28at.com

1.44ms
FZc28資訊網——每日最新資訊28at.com

2.03ms
FZc28資訊網——每日最新資訊28at.com

440,509
FZc28資訊網——每日最新資訊28at.com

0.3079
FZc28資訊網——每日最新資訊28at.com

可以看到,在不同的序列化方法下,序列化耗時都有所減少,性能最高提升至原來的 35%,序列化后的數據量也減少到原來的 36%,這也預示著網絡 I/O 的開銷會有所下降。FZc28資訊網——每日最新資訊28at.com

接入情況:FZc28資訊網——每日最新資訊28at.com

  • 推薦系統:在轉轉首頁推薦場景中接入后,與原 Redis 方案相比,性能沒有顯著提升,但減少了 Redis 中間存儲環節,從而降低了特征數據丟失的風險。
  • 搜索系統:在接入并進行壓測后,雖然整體耗時有所減少,但仍然存在大約 13 毫秒的額外耗時(71ms 對比 58ms),尚未完全解決性能問題。

總結:FZc28資訊網——每日最新資訊28at.com

  • 盡管方案在性能上有所提升,但這僅是對原有序列化框架的修補,核心問題在于 SCF 序列化對特定對象的執行效率仍然不高,因此問題并未徹底解決。初步分析表明,可能的原因在于 Map 的序列化過程本身依然較為耗時,并且在反序列化時,需要為 LazyMetric 的字節數組(搜索約 1500 個,推薦約 800 個)分配大量碎片化的內存空間,這導致了額外的耗時。

3.2 優化方案三

根據對 V2 方案的總結,V3 方案的設計原則是:放棄使用 SCF 的通用對象序列化,RPC 層僅通過字節數組進行交互,而排序框架采用自定義的序列化方法。FZc28資訊網——每日最新資訊28at.com

思路一:繼續嘗試接入現有的開源序列化框架,并在此基礎上對排序響應對象進行定制化開發。常見的開源項目包括 protobuf、Kryo、Hessian 等。FZc28資訊網——每日最新資訊28at.com

思路二:自行開發專門適用于排序響應對象的序列化方法。FZc28資訊網——每日最新資訊28at.com

思路一的優勢在于安全性、通用性和高性能方面都表現良好,部分框架也提供一定的定制化能力。然而,這類框架通常為了適應多種業務場景,會包含大量通用代碼和復雜邏輯。以 Kryo 為例,其項目代碼行數超過 2 萬行,這使得短期內很難掌握所有細節,一旦出現問題可能會阻礙開發進度,并且不一定能按期解決序列化問題。不過,開源框架技術成熟,適合作為長期方案。FZc28資訊網——每日最新資訊28at.com

思路二的優勢在于既可以借鑒其他框架的優化策略,又可以低成本地針對特定對象進行定制優化,從而實現更高的序列化效率。雖然在安全性方面,需要通過單元測試來保障,但開發一個針對特定應用場景的序列化方法相對簡單??紤]到排序框架接口的參數對象不經常更改,這種方法可以做到一次開發、長期受益。因此,我們傾向于選擇思路二。FZc28資訊網——每日最新資訊28at.com

整理思路后,序列化開發可以按照以下步驟進行:FZc28資訊網——每日最新資訊28at.com

定義字節數組的序列化數據結構FZc28資訊網——每日最新資訊28at.com

  • 確定如何將對象數據映射到字節數組的格式中,包括字段的順序、類型,以及如何處理可變長度數據。

定義序列化接口并實現具體的序列化類:FZc28資訊網——每日最新資訊28at.com

  • 創建一個通用的序列化接口,用于定義序列化和反序列化的方法。
  • 為每個需要序列化的對象類型實現具體的序列化類,確保符合接口的要求。

定義序列化過程的數據緩沖類:FZc28資訊網——每日最新資訊28at.com

  • 開發一個用于在序列化和反序列化過程中暫存數據的緩沖類,以便有效管理字節數組的讀寫操作。

實現各對象的具體序列化方法:FZc28資訊網——每日最新資訊28at.com

  • 為每個對象類型實現具體的序列化和反序列化方法,將對象數據轉換為字節數組或從字節數組重構對象。

序列化結果最終要存儲在字節數組(byte[])中,因此定義如何存儲是我們的首要任務。FZc28資訊網——每日最新資訊28at.com

一個排序對象包含許多內容。為了簡化存儲過程并便于編寫代碼,我們采用了一種類似樹狀的存儲結構,與其他序列化方式大致相同。這種結構將排序對象的整體作為根節點,然后按照對象的層次結構逐級展開存儲。FZc28資訊網——每日最新資訊28at.com

與其他序列化方式不同的是,我們考慮到排序過程中對所有商品都會執行相同的操作,因此商品類的特征 Map、結果 Map 和日志 Map 的存儲鍵集合在實際應用中是保持一致的。由于這些鍵是可以復用的,我們將其提取出來并統一存儲在 items_common 中。這樣一來,Map 的值可以按照固定的順序進行鏈式存儲,這種方法不僅節省了空間,還提升了存儲效率。FZc28資訊網——每日最新資訊28at.com

圖片FZc28資訊網——每日最新資訊28at.com

為了進一步降低代碼復雜度,還需要定義統一的接口,再將各個成員序列化過程分解到多個具體實現類中FZc28資訊網——每日最新資訊28at.com

自定義序列化方法接口定義如下:FZc28資訊網——每日最新資訊28at.com

public interface IRankObjSerializer<T> {     int estimateUsage(T obj, RankObjSerializeContext context);     void serialize(T obj, RankObjSerializeContext context) throws Exception;     T deserialize(RankObjDeserializeContext context) throws Exception;}

方法的含義如下:FZc28資訊網——每日最新資訊28at.com

estimateUsage:快速評估序列化對象的長度。FZc28資訊網——每日最新資訊28at.com

  • 在序列化過程中,如果字節數組的容量不足,就需要創建一個新數組,其大小為當前大小的兩倍,并復制已有數據。這一過程需要進行 log(最終大小) - log(初始大小) 次擴容操作。estimateUsage 方法通過快速評估一個稍大于或接近最終大小的初始容量,來減少擴容次數,提高效率。

serialize:用于序列化對象。FZc28資訊網——每日最新資訊28at.com

  • 序列化過程中,context 包含一個 Output 對象,用于處理字節數據的輸出,同時還包括 metricMap、resultMap 等公共的 keySet,這些 keySet 用于統一管理序列化過程中的鍵集合。

deserialize:用于反序列化對象。FZc28資訊網——每日最新資訊28at.com

  • 反序列化過程中,context 包含一個 Input 對象,用于處理字節數據的輸入,此外,還包括 metricMap、resultMap 等公共的 keySet,以確保反序列化時使用的鍵集合與序列化時一致。

通過這些方法,可以更有效地管理對象的序列化和反序列化過程,提升整體性能和資源利用率。FZc28資訊網——每日最新資訊28at.com

根據響應對象的數據層次,序列化過程需要針對不同的類型進行拆解,并為每種具體類型設計相應的序列化類。以下是各類序列化器的設計:FZc28資訊網——每日最新資訊28at.com

GeneralObjSerializer:FZc28資訊網——每日最新資訊28at.com

  • 負責序列化和反序列化 Java 的基本數據類型(如 int、float、double 等)以及字符串 (String) 類型。
  • 提供方法將基本數據類型和字符串轉換為字節數組,并在反序列化時將字節數組轉換回相應的基本類型或字符串。

GeneralMapSerializer(用于基本 Map 類型,按順序存儲鍵值對):FZc28資訊網——每日最新資訊28at.com

  • 負責序列化和反序列化 Map 對象。該類按特定順序存儲 Map 的鍵值對(key-value),確保在反序列化時可以恢復 Map 的原始狀態。
  • 支持常見的 Map 實現(如 HashMap、TreeMap 等),并處理可能的空鍵或空值。

GeneralListSerializer(FZc28資訊網——每日最新資訊28at.com

  • 負責序列化和反序列化 List 對象,能夠將 List 轉換為字節數組,并在反序列化時恢復 List 的原始結構和內容。
  • 適用于各種 List 實現(如 ArrayList、LinkedList 等),并處理列表中的空元素。

GeneralSetSerializer:FZc28資訊網——每日最新資訊28at.com

  • 負責序列化和反序列化 Set 對象,將 Set 中的元素序列化為字節數組并按序恢復。
  • 支持常見的 Set 實現(如 HashSet、TreeSet 等),并確保在反序列化后保持 Set 的無序性和唯一性。

RankResultSerializer:FZc28資訊網——每日最新資訊28at.com

  • 負責序列化和反序列化 RankResult 對象,處理與排序結果相關的數據結構和字段。
  • 該類將 RankResult 的復雜對象和嵌套結構序列化為字節數組,并在反序列化時重構完整的 RankResult 對象。

RankResultItemSerializer:FZc28資訊網——每日最新資訊28at.com

  • 專門用于序列化和反序列化 RankResultItem 對象,處理單個排序結果項的序列化。
  • 負責將每個 RankResultItem 的各個字段(包括特征、結果和日志等)轉換為字節數組,并在反序列化時恢復其內容和結構。

RankResponseSerializer:FZc28資訊網——每日最新資訊28at.com

  • 用于序列化和反序列化 RankResponse 對象,管理整個排序響應的序列化過程。
  • 該類負責將完整的響應數據,包括所有 RankResultItem,序列化為字節數組,并在反序列化時重建整個 RankResponse 對象。

序列化過程中依次將寫入到一段足夠長的byte數組里,序列化完成時再一次性讀出所有寫入數據,定義Output類作為序列化過程中的數據緩沖(同樣有Input類作用于反序列化,實現類似)FZc28資訊網——每日最新資訊28at.com

class Output {    byte[] data;    int offset;     Output(int estimateUsage) {        data = new byte[estimateUsage];        offset = 0;    }          void writeInt(int);    void writeLong(long);    void writeFloat(float);    void writeBytes(byte[]);    ...}

data:作為序列化數據的緩沖區,為了寫入效率最高,緩沖區是連續且足夠長的byte數組,足夠長由入參estimateUsage來保證FZc28資訊網——每日最新資訊28at.com

offset:是下一個要寫入數據的位置,如果offset >= 數組長度,則需要擴容,擴容每次按兩倍擴容FZc28資訊網——每日最新資訊28at.com

estimateUsage的準確性影響了擴容次數,進而影響序列化效率,經測試從以32為起始容量初始化并逐漸擴容到所需容量與直接使用estimateUsage初始化,序列化耗時相差20%左右FZc28資訊網——每日最新資訊28at.com

writeInt、writeLong:整型和長整型的寫入是可變長的,雖然int和long分別使用了32bit和64bit的空間,但如1、2、8、64等較小的數字只是用了前8bit的空間,一般可變長序列化采取的做法是將每8bit為一組,低7位存儲真實數據,高位存儲標識符,表明更高位是否仍存在更多數據,可變長編碼下整型需要1~5byte,長整型則需要1~10byte,存儲數字值越小時,可變長的壓縮效果越好。讀取時再從低位依次向高位讀取,直到標識符表明數據讀取完畢,當緩沖區剩余長度不足可變長的最大長度時,需要調用readInt_slow或readLong_slow方法,逐個byte讀取并判斷是否越界FZc28資訊網——每日最新資訊28at.com

writeFloat、writeDouble:這兩種類型不能直接寫入,需要調用Float.floatToRawIntBits和Double.doubleToRawLongBits轉為Integer型和Long型。我們的特征由于特征默認值等原因存在大量0.0、-1.0、1.0等數值,但在可變長存儲下,轉int后實際占用位數很長,優化方式是轉換前先判斷了它是否為整型數字,如是整型就取整后直接存為整型,可將原本需要5~10位的存儲空間節省到1位,一個較為快速的判斷方式為:FZc28資訊網——每日最新資訊28at.com

void checkDoubleIsIntegerValue(double d) {    return ((long)d == d);}

多數序列化實現按待序列化的各個成員類型依次調用對應序列化方法即可FZc28資訊網——每日最新資訊28at.com

Item間的共享數據處理,是本次序列化優化最核心的優化點,對序列化效率提升有決定性影響,如特征/結果/日志Map的keySet的存儲復用,具體做法是FZc28資訊網——每日最新資訊28at.com

讀取第一個Item的所有keySet并保存在序列化上下文中,作為基準數據,后續每個Item都與第一個的keySet判斷,完全相同就按第一個item的相同順序將values依次取出,按隊列存儲,快速的判斷方式如下:FZc28資訊網——每日最新資訊28at.com

private static boolean isNotEqualSet(Set<String> set1, Set<String> set2) {        return set1 == null || set2 == null || (set1.size() != set2.size()) || !set1.containsAll(set2); }

當任意商品不滿足keySet一致性的要求時,Item序列化方法會向上拋出異常,排序框架會捕獲到該異常,并將返回的壓縮響應對象(CompressedRankResponse)退化為普通響應對象(RankResponse)FZc28資訊網——每日最新資訊28at.com

異常行為會根據用戶的選擇上報給監控平臺,或需要排查問題時選擇打印到本地文件FZc28資訊網——每日最新資訊28at.com

上游服務無需關心排序服務返回了哪種響應對象,這是因為普通響應對象和序列化后的壓縮響應對象實現了同一接口FZc28資訊網——每日最新資訊28at.com

即原RankResponse對象和新CompressedRankResponse對象實現了IRankResponse接口,CompressedRankResponse是RankResponse的裝飾器對象FZc28資訊網——每日最新資訊28at.com

CompressedRankResponse對象在用戶調用任意方法,且當內置RankResponse對象為空時完成反序列化,如下段代碼中的getStatus方式所示FZc28資訊網——每日最新資訊28at.com

后續再調用其他方法在使用體驗上是與未壓縮對象一致的,這種與直接返回byte數組相比,業務使用更友好,異常時可以快速降級,也沒有太多帶來額外成本FZc28資訊網——每日最新資訊28at.com

IRankResponse rank(RankRequest request); class RankResponse implements IRankResponse; class CompressedRankResponse implements IRankResponse {    byte[] bytes; // 排序服務返回的數據         RankResponse response = null; // 調用任意方法后反序列化生成的數據         public int getStatus() {        if(response == null) {            // 執行反序列化            response = this.doDeserilize();        }        return response.getStatus();    }}

模擬搜索500個商品,測試2000次,序列化前大小1430640FZc28資訊網——每日最新資訊28at.com

第一次測試:實驗組為V3優化,對照組為無優化FZc28資訊網——每日最新資訊28at.com

方法
FZc28資訊網——每日最新資訊28at.com

序列化時間
FZc28資訊網——每日最新資訊28at.com

反序列化時間
FZc28資訊網——每日最新資訊28at.com

總時間
FZc28資訊網——每日最新資訊28at.com

數據大小 (bytes)
FZc28資訊網——每日最新資訊28at.com

壓縮比率
FZc28資訊網——每日最新資訊28at.com

SCFV4 序列化原方法
FZc28資訊網——每日最新資訊28at.com

1.86ms
FZc28資訊網——每日最新資訊28at.com

1.19ms
FZc28資訊網——每日最新資訊28at.com

3.05ms
FZc28資訊網——每日最新資訊28at.com

1,188,961
FZc28資訊網——每日最新資訊28at.com

0.8310
FZc28資訊網——每日最新資訊28at.com

框架自定義序列化方法
FZc28資訊網——每日最新資訊28at.com

0.32ms
FZc28資訊網——每日最新資訊28at.com

0.17ms
FZc28資訊網——每日最新資訊28at.com

0.49ms
FZc28資訊網——每日最新資訊28at.com

392,127
FZc28資訊網——每日最新資訊28at.com

0.2741
FZc28資訊網——每日最新資訊28at.com

優化降低
FZc28資訊網——每日最新資訊28at.com

82.80%
FZc28資訊網——每日最新資訊28at.com

85.71%
FZc28資訊網——每日最新資訊28at.com

83.93%
FZc28資訊網——每日最新資訊28at.com

67.02%
FZc28資訊網——每日最新資訊28at.com

67.02%
FZc28資訊網——每日最新資訊28at.com

第二次測試:實驗組為V3優化,對照組為V2優化FZc28資訊網——每日最新資訊28at.com

方法
FZc28資訊網——每日最新資訊28at.com

序列化時間
FZc28資訊網——每日最新資訊28at.com

反序列化時間
FZc28資訊網——每日最新資訊28at.com

總時間
FZc28資訊網——每日最新資訊28at.com

數據大小 (bytes)
FZc28資訊網——每日最新資訊28at.com

壓縮比率
FZc28資訊網——每日最新資訊28at.com

框架自定義序列化方法
FZc28資訊網——每日最新資訊28at.com

0.41ms
FZc28資訊網——每日最新資訊28at.com

0.20ms
FZc28資訊網——每日最新資訊28at.com

0.61ms
FZc28資訊網——每日最新資訊28at.com

393,001
FZc28資訊網——每日最新資訊28at.com

0.274
FZc28資訊網——每日最新資訊28at.com

帶日志 byte 壓縮 + SCF 序列化方法
FZc28資訊網——每日最新資訊28at.com

3.10ms
FZc28資訊網——每日最新資訊28at.com

1.00ms
FZc28資訊網——每日最新資訊28at.com

4.10ms
FZc28資訊網——每日最新資訊28at.com

503,961
FZc28資訊網——每日最新資訊28at.com

0.35
FZc28資訊網——每日最新資訊28at.com

優化降低
FZc28資訊網——每日最新資訊28at.com

-
FZc28資訊網——每日最新資訊28at.com

-
FZc28資訊網——每日最新資訊28at.com

85.12%
FZc28資訊網——每日最新資訊28at.com

21.7%
FZc28資訊網——每日最新資訊28at.com

21.7%
FZc28資訊網——每日最新資訊28at.com

可見V3對序列化過程的執行效率提升明顯FZc28資訊網——每日最新資訊28at.com

以下是業務接入情況 FZc28資訊網——每日最新資訊28at.com

搜索側接入:測試接入排序服務耗時于未服務化時持平,滿足上線要求FZc28資訊網——每日最新資訊28at.com

推薦測接入:序列化過程在2ms左右完成,場景接入后耗時均有明顯下降,符合預期FZc28資訊網——每日最新資訊28at.com

場景
FZc28資訊網——每日最新資訊28at.com

優化前
FZc28資訊網——每日最新資訊28at.com

優化后
FZc28資訊網——每日最新資訊28at.com

提升時間FZc28資訊網——每日最新資訊28at.com

百分比
FZc28資訊網——每日最新資訊28at.com

找靚機微詳情頁推薦
FZc28資訊網——每日最新資訊28at.com

69ms
FZc28資訊網——每日最新資訊28at.com

64ms
FZc28資訊網——每日最新資訊28at.com

5ms
FZc28資訊網——每日最新資訊28at.com

7.24%
FZc28資訊網——每日最新資訊28at.com

轉轉 B2C 詳情頁
FZc28資訊網——每日最新資訊28at.com

97ms
FZc28資訊網——每日最新資訊28at.com

94ms
FZc28資訊網——每日最新資訊28at.com

3ms
FZc28資訊網——每日最新資訊28at.com

3.09%
FZc28資訊網——每日最新資訊28at.com

轉轉 C2C 詳情頁
FZc28資訊網——每日最新資訊28at.com

92ms
FZc28資訊網——每日最新資訊28at.com

87ms
FZc28資訊網——每日最新資訊28at.com

5ms
FZc28資訊網——每日最新資訊28at.com

5.43%
FZc28資訊網——每日最新資訊28at.com

轉轉首頁推薦 3C 頁
FZc28資訊網——每日最新資訊28at.com

112ms
FZc28資訊網——每日最新資訊28at.com

106ms
FZc28資訊網——每日最新資訊28at.com

6ms
FZc28資訊網——每日最新資訊28at.com

5.36%
FZc28資訊網——每日最新資訊28at.com

轉轉首頁推薦默認
FZc28資訊網——每日最新資訊28at.com

130ms
FZc28資訊網——每日最新資訊28at.com

128ms
FZc28資訊網——每日最新資訊28at.com

2ms
FZc28資訊網——每日最新資訊28at.com

1.54%
FZc28資訊網——每日最新資訊28at.com

4 總結

本項目旨在解決搜索推薦服務化過程中因日志傳輸引起的序列化額外耗時問題。經過三次版本迭代和測試,最終方案成功落地。FZc28資訊網——每日最新資訊28at.com

結論FZc28資訊網——每日最新資訊28at.com

本地測試:FZc28資訊網——每日最新資訊28at.com

  • 與優化前相比,排序響應對象的序列化過程節省了約 83% 的序列化開銷,網絡開銷減少了約 67%。搜索:
  • 有效降低了排序服務響應中的序列化過程對搜索接口整體耗時的影響,使得新的搜索排序服務在性能上達到了上線要求。推薦:
  • 在推薦排序服務化后,接入本項目方案,在多個展位實現了接口整體耗時絕對值降低 2ms 到 6ms 的性能提升。

思考FZc28資訊網——每日最新資訊28at.com

從問題發現到解決上線,項目歷時近一個月。雖然問題定位較為迅速,但在確定最終方案和落地時經歷了較長的周期。方案設計過程中有兩點需要注意:FZc28資訊網——每日最新資訊28at.com

方案評估要更細致:FZc28資訊網——每日最新資訊28at.com

  • 不要急于實施方案,要及時暴露性能瓶頸。例如,前期如果發現日志上報超出了 Redis 單節點 10 萬 QPS 的瓶頸,在考慮實施 V1 方案時會更加謹慎。

方案設計要更具全局性:FZc28資訊網——每日最新資訊28at.com

  • 不應僅將視角局限于字符串序列化過程,而是從整個序列化過程的角度出發。這樣可以更快地跳過 V2 方案,直接進入更高效的 V3 方案。

后續工作FZc28資訊網——每日最新資訊28at.com

廢棄遺留代碼:FZc28資訊網——每日最新資訊28at.com

  • 遺留代碼增加了開發的不確定性和風險性,因此需要廢棄 SCF 原生序列化方法和 V1 方法。

召回框架的序列化優化:FZc28資訊網——每日最新資訊28at.com

  • 召回服務框架的序列化優化尚未啟動,預計也能獲得顯著的性能提升。然而,與排序框架相比,召回框架涉及的傳輸對象類型更多,優化難度更高,因此方案需要在排序優化的基礎上進一步調整。

本文鏈接:http://www.tebozhan.com/showinfo-26-112793-0.html轉轉搜推排序服務的響應對象序列化優化

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 我嘗試重現 React 的 useState() Hook 并失去了工作機會

下一篇: 微服務為什么要容器化?

標簽:
  • 熱門焦點
  • 紅魔電競平板評測:大屏幕硬實力

    前言:三年的疫情因為要上網課的原因激活了平板市場,如今網課的時代已經過去,大家的生活都恢復到了正軌,這也就意味著,真正考驗平板電腦生存的環境來了。也就是面對著這種殘酷的
  • 7月安卓手機性價比榜:努比亞+紅魔兩款新機入榜

    7月登場的新機有努比亞Z50S Pro和紅魔8S Pro,除了三星之外目前唯二的兩款搭載超頻版驍龍8Gen2處理器的產品,而且努比亞和紅魔也一貫有著不錯的性價比,所以在本次的性價比榜單
  • 6月iOS設備好評榜:第一蟬聯榜首近一年

    作為安兔兔各種榜單里變化最小的那個,2023年6月的iOS好評榜和上個月相比沒有任何排名上的變化,僅僅是部分設備好評率的下降,長年累月的用戶評價和逐漸退出市場的老款機器讓這
  • 跑分安卓第一!Redmi K60至尊版8月發布!盧偉冰:目標年度性能之王

    8月5日消息,Redmi K60至尊版將于8月發布,在此前舉行的戰略發布會上,官方該機將搭載搭載天璣9200+處理器,安兔兔V10跑分超177萬分,是目前安卓陣營最高的分數
  • 摸魚心法第一章——和配置文件說拜拜

    為了能摸魚我們團隊做了容器化,但是帶來的問題是服務配置文件很麻煩,然后大家在群里進行了“親切友好”的溝通圖片圖片圖片圖片對比就對比,簡單對比下獨立配置中心和k8s作為配
  • 分布式系統中的CAP理論,面試必問,你理解了嘛?

    對于剛剛接觸分布式系統的小伙伴們來說,一提起分布式系統,就感覺高大上,深不可測。而且看了很多書和視頻還是一臉懵逼。這篇文章主要使用大白話的方式,帶你理解一下分布式系統
  • Flowable工作流引擎的科普與實踐

    一.引言當我們在日常工作和業務中需要進行各種審批流程時,可能會面臨一系列技術和業務上的挑戰。手動處理這些審批流程可能會導致開發成本的增加以及業務復雜度的上升。在這
  • 一個注解實現接口冪等,這樣才優雅!

    場景碼猿慢病云管理系統中其實高并發的場景不是很多,沒有必要每個接口都去考慮并發高的場景,比如添加住院患者的這個接口,具體的業務代碼就不貼了,業務偽代碼如下:圖片上述代碼有
  • 2022爆款:ROG魔霸6 冰川散熱系統持續護航

    喜逢開學季,各大商家開始推出自己的新產品,進行打折促銷活動。對于忠實的端游愛好者來說,能夠擁有一款夢寐以求的筆記本電腦是一件十分開心的事。但是現在的
Top