1. 程式人生 > >狼廠項目實踐:通用檢索框架準實時流的設計與實現

狼廠項目實踐:通用檢索框架準實時流的設計與實現

機制 oop 定期 函數 時也 維護 次數 業務需求 一是

背景

檢索對實時性的要求很高,不僅是對索引建立、結果召回、策略幹擾等核心部分,也包括數據錄入的部分。檢索的數據流主要包括全量數據與增量數據,其中全量數據是在運行前就已經生成好的,在檢索進程運行開始時就直接解析加載了,後面不會再產生,所以不會對錄入有高實時性的需求;而增量數據理論上在整個檢索進程運行過程中隨時都可能新增,新增了就需要錄入。所以,提高增量數據錄入的實時性,對提升整個檢索的性能有重要作用。

設計思路與折衷

目前搜索引擎實現增量更新的方案主要有這幾種:(1)提供寫接口,(2)使用文件,(3)使用消息隊列。

方案1即檢索框架本身提供寫數據的接口,數據發布方直接調用,寫入數據。這種方式應該是單次寫入速度最快的,但會使兩方代碼過於耦合,不易擴展和維護。且檢索框架需要提供數據接收讀取的完整機制,也要消耗很多資源。對於發布方來說,發布操作也必須依賴接收方的進度。如果數據更新頻率很低,數據量很小,可以考慮使用這種方式。

技術分享圖片
方案2主要是通過文件形式,即每次有新數據到來時,都先寫入一個文件中,然後定期將文件配送到檢索進程本地。檢索服務運行時,會監控本地文件夾的inode變化,一旦有文件產生或修改,就執行回調函數,讀取該文件,進行增量加載。這種方式一定程度上實現了數據發布方和接收方的解耦,但代價是要增加對文件的操作,並且實際應用中需要依賴數據配送,這是個很耗時的過程。文件本身的產生,拷貝,讀寫,效率也不算高,尤其在文件內容堆積得很大的時候。所以這種方案,實時性很難保證。
技術分享圖片
方案3是通過消息隊列。數據發布方將數據推到消息隊列中,接收方自己讀取。這種方式很好地實現了雙方業務的解耦,且無需維護對文件的一系列操作,也無需數據配送,實時性大大提升。對於發布方來說,不用再記錄數據到底要發給哪幾個檢索實例,只需發布一份數據到消息隊列中即可,檢索實例的增加、減少也都不需要在發布方進行修改,更加靈活。對於接收方,不用再定期處理堆積得很多的數據,資源使用也更平衡。同時也可以方便地實現流量控制等。不過穩定性需要依賴於消息隊列本身。
技術分享圖片
目前糯米的檢索使用的是方案2,框架成熟,運行穩定,容錯容災也都很完整。但針對糯米本身的業務特點,仍有可以改進的空間。糯米主要是提供生活服務類的檢索,特點就是數據更新頻繁,數據量大。而文件形式的更新,第一是實時性較差,第二是靈活性不高。而這些都可以通過消息隊列的特點進行優化。

消息隊列大都分為隊列模式和訂閱模式,根據業務需求,多個檢索實例都需要相同的一份數據,所以選擇訂閱模式。

針對業務特點,最終選擇方案3,使用消息隊列的訂閱模式,來實現數據的實時加載。

具體實現

糯米現有檢索框架一般都是在一個單獨的線程中監控文件變化,通過回調實現增量數據加載。主線程只需在其時傳入需要的配置以及對數據進行處理的回調函數即可,耦合度很低。所以消息隊列的添加理論上只需對這個線程所做的工作進行相應修改即可。

糯米現有檢索框架中,增量數據加載的工作流程大致如下:

技術分享圖片
首先讀取配置文件信息,包括增量文件的命名規則以及讀到的行數等,這是為了後面打開文件及移動讀指針做準備。這些配置放在本地一個單獨的文件中。之後註冊監控的回調函數,在文件夾inode發生變化時,會觸發raise喚醒wait中的處理線程,從指定行開始逐個字節讀文件,每讀完一條數據就進行一次處理,讀完整個文件後,就wait直到下個文件產生。

可見,整個流程都是圍繞著文件展開的。改為使用消息隊列讀取數據後,這些和文件相關的操作就都不需要了,改為接入相應消息隊列的訂閱相關接口。下面描述一種使用消息隊列(Kafka)的訂閱模式進行數據加載的大致流程:
技術分享圖片
首先添加一個消息隊列的訂閱類,定義實現異步訂閱的基本方法。

init中,主要實現對各個參數的配置,以及訂閱起始點的讀取。這個起始點是由數據發布方給出的,所以要在發起訂閱前就設定好。目前的做法和上面一樣,單獨在本地建一個配置文件,裏面存放了起始點的相關數據,init中直接讀取即可。

StartSubscribe主要包含兩個方法:獲取要訂閱的消息隊列的子通道的數量,然後對每個子通道發起訂閱請求。

之後進入SubscribeMainloop,在while循環中接收、處理數據。接收事件通過epoll_wait,只要有可讀或報錯事件觸發,epoll_wait就會返回,否則會阻塞直到超時或有新事件到來。

epoll_wait返回後,如果包含可讀事件,就調用回調函數進行處理即可。如果包含報錯事件,會根據報錯嘗試重新發起訂閱請求。

這樣一條增量數據的加載就完成了,while循環會一直重復這個流程,直到加載完消息隊列裏最新的一條數據。之後就會阻塞在epoll_wait上,直到有新的數據發布進來。

總結

  本文簡單介紹了一種使用消息隊列的訂閱模式實現通用檢索框架增量數據加載的新方案,及其設計與實現。糯米現有檢索框架文件形式的更新,由於數據配送系統本身的復雜性,需要至少半小時才能更新一次數據。而使用消息隊列更新一條數據的用時在0.5秒以內,更新1000條數據也可在2秒以內完成,實現了準實時流,值得全面推廣在檢索框架的增量數據錄入部分使用。

狼廠項目實踐:通用檢索框架準實時流的設計與實現