有讚搜尋系統的架構演進

2022-06-01 13:30:11 字數 3658 閱讀 4133

摘要:有讚搜尋平台是乙個面向公司內部各項搜尋應用以及部分 nosql 儲存應用的 paas 產品,幫助應用合理高效的支援檢索和多維過濾功能,有讚搜尋平台目前支援了大大小小一百多個檢索業務,服務於近百億資料。

在為傳統的搜尋應用提供高階檢索和大資料互動能力的同時,有讚搜尋平台還需要為其他比如商品管理、訂單檢索、粉絲篩選等海量資料過濾提供支援,從工程的角度看,如何擴充套件平台以支援多樣的檢索需求是乙個巨大的挑戰。

elasticsearch 是乙個高可用分布式搜尋引擎,一方面技術相對成熟穩定,另一方面社群也比較活躍,因此我們在搭建搜尋系統過程中也是選擇了 elasticsearch 作為我們的基礎引擎。

時間回到 2015 年,彼時執行在生產環境的有贊搜尋系統是乙個由幾台高配虛擬機器組成的 elasticsearch 集群,主要執行商品和粉絲索引,資料通過 canal 從 db 同步到 elasticsearch:

通過這種方式,在業務量較小時,可以低成本的快速為不同業務索引建立同步應用,適合業務快速發展時期,但相對的每個同步程式都是單體應用,不僅與業務庫位址耦合,需要適應業務庫快速的變化,如遷庫、分庫分表等,而且多個 canal 同時訂閱同乙個庫,也會造成資料庫效能的下降。

另外 elasticsearch 集群也沒有做物理隔離,有一次**活動就因為粉絲資料量過於龐大導致 elasticsearch 程序 heap 記憶體耗盡而 oom,使得集群內全部索引都無法正常工作,這給我上了深深的一課。

我們在解決以上問題的過程中,也自然的沉澱出了有贊搜尋的 2.0 版架構

首先資料匯流排將資料變更訊息同步到 mq,同步應用通過消費 mq 訊息來同步業務庫資料,借資料匯流排實現與業務庫的解耦,引入資料匯流排也可以避免多個 canal 監聽消費同一張表 binlog 的虛耗。

隨著業務發展,我們也逐漸出現了一些比較中心化的流量入口,比如分銷、精選等,這時普通的 bool 查詢並不能滿足我們對搜尋結果的細粒率排序控制需求,將複雜的 function_score 之類專業性較強的高階查詢編寫和優化工作交給業務開發負責顯然是個不可取的選項,這裡我們考慮的是通過乙個高階查詢中介軟體攔截業務查詢請求,在解析出必要的條件後重新組裝為高階查詢交給引擎執行

這裡另外做的一點優化是加入了搜尋結果快取,常規的文字檢索查詢 match 每次執行都需要實時計算,在實際的應用場景中這並不是必須的,使用者在一定時間段內(比如 15 或 30 分鐘)通過同樣的請求訪問到同樣的搜尋結果是完全可以接受的,在中介軟體做一次結果快取可以避免重複查詢反覆執行的虛耗,同時提公升中介軟體響應速度,對高階搜尋比較感興趣的同學可以閱讀另外一篇文章《有讚搜尋引擎實踐(工程篇)》(見技術部落格),這裡不再細述。

通過 flume 收集搜尋日誌儲存到 hdfs 供後續分析,也可以在通過 hive 分析後匯出作為搜尋提示詞,當然大資料為搜尋業務提供的遠不止於此,這裡只是簡單列舉了幾項功能。

這樣的架構支撐了搜尋系統一年多的執行,但是也暴露出了許多問題,首當其衝的是越發高昂的維護成本,除去 elasticsearch 集群維護和索引本身的配置、字段變更,雖然已經通過資料匯流排與業務庫解耦,但是耦合在同步程式中的業務**依舊為團隊帶來了極大的維護負擔。訊息佇列雖然一定程式上減輕了我們與業務的耦合,但是帶來的訊息順序問題也讓不熟悉業務資料狀態的我們很難處理。

除此之外,流經 elasticsearch 集群的業務流量對我們來說呈半黑盒狀態,可以感知,但不可**,也因此出現過線上集群被內部大流量錯誤呼叫壓到cpu佔滿不可服務的故障。

針對 2.0 時代的問題,我們在 3.0 架構中做了一些針對性調整,列舉主要的幾點:

通過開放介面接收使用者呼叫,與業務**完全解耦;

增加 proxy 用來對外服務,預處理使用者請求並執行必要的流控、快取等操作;

提供管理平台簡化索引變更和集群管理 這樣的演變讓有贊搜尋系統逐漸的平台化,已經初具了乙個搜尋平台的架構

作為對外服務的出入口,proxy 除了通過 esloader 提供相容不同版本 elasticsearch 呼叫的標準化介面之外,也內嵌了請求校驗、快取、模板查詢等功能模組。

請求校驗主要是對使用者的寫入、查詢請求進行預處理,如果發現字段不符、型別錯誤、查詢語法錯誤、疑似慢查詢等操作後以 fast fail 的方式拒絕請求或者以較低的流控水平執行,避免無效或低效能操作對整個 elasticsearch 集群的影響。

快取和 esloader 主要是將原先高階搜尋中的通用功能整合進來,使得高階搜尋可以專注於搜尋自身的查詢分析和重寫排序功能,更加內聚。我們在快取上做了一點小小的優化,由於查詢結果快取通常來說帶有源文件內容會比較大,為了避免流量高峰頻繁訪問導致 codis 集群網路擁堵,我們在 proxy 上實現了乙個簡單的本地快取,在流量高峰時自動降級。

這裡提一下模板查詢,在查詢結構(dsl)相對固定又比較冗長的情況下,比如商品類目篩選、訂單篩選等,可以通過模板查詢(search template)來實現,一方面簡化業務編排dsl的負擔,另一方面還可以通過編輯查詢模板 template,利用預設值、可選條件等手段在服務端進行線上查詢效能調優。

為了降低日常的索引增刪、字段修改、配置同步上的維護成本,我們基於 django 實現了最初版本的搜尋管理平台,主要提供一套索引變更的審批流以及向不同集群同步索引配置的功能,以視覺化的方式實現索引元資料的管理,減少我們在平台日常維護上的時間成本。

由於開源 head 外掛程式在效果展示上的不友好,以及暴露了部分粗暴功能

如圖,可以通過點按字段使得索引按指定字段排序展示結果,在早期版本 elasticsearch 會通過 fielddata 載入需要排序的字段內容,如果字段資料量比較大,很容易導致 heap 記憶體佔滿引發 full gc 甚至 oom,為了避免重複出現此類問題,我們也提供了定製的視覺化查詢元件以支援使用者瀏覽資料的需求。

由於 es-hadoop 僅能通過控制 map-reduce 個數來調整讀寫流量,實際上 es-hadoop 是以 elasticsearch 是否拒絕請求來調整自身行為,對線上工作的集群相當不友好。為了解決這種離線讀寫流量上的不可控,我們在現有的 datax 基礎上開發了乙個 eswriter 外掛程式,能夠實現記錄條數或者流量大小的秒級控制。

平台化以及配套的文件體系完善降低了使用者的接入門檻,隨著業務的快速增長,elasticsearch 集群本身的運維成本也讓我們逐漸不堪,雖然有物理隔離的多個集群,但不可避免的會有多個業務索引共享同乙個物理集群,在不同業務間各有出入的生產標準上支援不佳,在同乙個集群內部署過多的索引也是生產環境穩定執行的乙個隱患。

另外集群服務能力的彈性伸縮相對困難,水平擴容乙個節點都需要經歷機器申請、環境初始化、軟體安裝等步驟,如果是物理機還需要更長時間的機器採購過程,不能及時響應服務能力的不足。

當前架構通過開放介面接受使用者的資料同步需求,雖然實現了與業務解耦,降低了我們團隊自身的開發成本,但是相對的使用者開發成本也變高了,資料從資料庫到索引需要經歷從資料匯流排獲取資料、同步應用處理資料、呼叫搜尋平台開放介面寫入資料三個步驟,其中從資料匯流排獲取資料與寫入搜尋平台這兩個步驟在多個業務的同步程式中都會被重複開發,造成資源浪費。這裡我們目前也準備與 paas 團隊內自研的dts(data transporter,資料同步服務)進行整合,通過配置化的方式實現 elasticsearch 與多種資料來源之間的自動化資料同步。

要解決共享集群應對不同生產標準應用的問題,我們希望進一步將平台化的搜尋服務提公升為雲化的服務申請機制,配合對業務的等級劃分,將核心應用獨立部署為相互隔離的物理集群,而非核心應用通過不同的應用模板申請基於 k8s 執行的 elasticsearch 雲服務。應用模板中會定義不同應用場景下的服務配置,從而解決不同應用的生產標準差異問題,而且雲服務可以根據應用執行狀況及時進行服務的伸縮容。

本文從架構上介紹了有贊搜尋系統演進產生的背景以及希望解決的問題

推薦系統實時推薦架構演進

離線推薦存量問題,在feed架構儲存的資料也有比較多,原有設計都是為了避免離線推薦資料消費完無資料可推薦,但這個對於業務的調整都沒感知,比如內容敏感下架,使用者興趣變化 推薦資料不足,離線推薦的資料會很快受到使用者的重新整理過量快速消費完,導致召回源資料不足,多樣性不夠,需要補充引擎 目前解決方式是...

雲時代架構之360推薦系統架構演進

由 amazon 發揚光大的。推薦系統也是現在熱門的人工智慧分支之一,但凡人工智慧類的落地,都需要具備這幾個基本元素才行 資料 演算法 場景 計算力。推薦系統也不例外,而剛好,現在的時代,這些元素的獲得成本相比十年前已經小了很多。未來隨著各種硬體裝置越來越智慧型,萬物互聯得越來越緊密,人們的個性化需...

美團配送系統架構演進讀後感

美團配送自成立以來,業務經歷了多次跨越式的發展。業務的飛速增長,對系統的整體架構和基礎設施提出了越來越高的要求,同時也不斷驅動著技術團隊深刻理解業務 準確定位領域模型 高效支撐系統擴充套件。如何在業務高速增長 可用性越來越高的背景下實現系統架構的快速有效公升級?如何保證複雜業務下的研發效率與質量?本...