百度搜尋穩定性問題分析的故事(上)

2022-09-14 19:51:15 字數 3905 閱讀 8488

在大規模微服務系統下,如果故障未發生,應該歸功於運氣好。但是永遠不要指望故障不發生,必須把發生故障當作常態。從故障發生到解除過程遵循的基本模式抽象如下。

複雜的系統,意味著故障現場的資料收集和分析是一項浩大的工程。

pv損失故障:未按時、正確向使用者返回query結果,是最嚴重的故障。

搜尋效果故障:預期網頁未在搜尋結果中展現;或未排序在搜尋結果的合理位置;搜尋結果頁面響應速度變慢。

容量故障:因外部或內部等各種原因,無法保證系統高可用需要的冗餘度,甚至容量水位超過臨界點造成崩潰宕機等情況,未及時預估、告警、修復。

這些種類繁多、領域各異的問題背後,不變的是對資料採集加工的需求和人工分析經驗的自動化抽象。

系統架構如下圖所示。

階段性使命:kepler1.0在於完善搜尋系統的可觀測性,基於開源成熟方案結合公司內元件實現從0到1的建設,快速完成可觀測性能力空白的補齊,具備根據queryid查詢query處理過程的呼叫鏈以及途徑服務例項日誌的能力。引進來:從kepler1.0的架構不難發現,它從資料通路、儲存架構等方面完整的參考zipkin本土化:引進zipkin時資料採集sdk只支援c++,為了滿足對非c++模組的可觀測性需求,兼顧sdk的多語言維護成本以及trace的侵入性,採用了常駐程序通過日誌採集輸出格式和c++ sdk相容的trace資料,即圖中的日誌採集模組。

系統架構如下圖所示。

場景1:拒絕、效果問題

階段性痛點:人工分析強依賴日誌,從海量呼叫鏈、日誌資料中精確檢索出某些特定query,通過ssh掃線上機器日誌效率很低,且對線上服務存在home盤io打滿導致穩定性風險。解決情況:對命中常態隨機抽樣拒絕問題、可復現的效果問題開啟強制抽樣採集,通過queryid直接從平台查詢呼叫鏈及日誌用於人工分析原因,基本滿足了這個階段的trace需求。

場景2:速度問題

階段性痛點:僅有日誌資料,缺乏呼叫鏈的精細時間戳;乙個query激發的呼叫鏈長、扇出度大,日誌散落廣泛,難收集。通過日誌幾乎無法恢復完整的時序過程。這導致速度的優化呈現黑盒狀態。解決情況:補全了呼叫鏈的精細時間戳,使query的完整時序恢復成為可能。通過呼叫鏈可以查詢到程式層面耗時長尾階段或排程層面熱點例項等優化點,基於此,孵化並落地了tcp connect非同步化、業務**阻塞操作解除等改進專案。

場景3:容量問題

雖然kepler1.0和prometheus開啟了可觀測性建設的大門,但是受限於能力,已經難以低成本地獲取更多的使用價值了。

基於開源方案的實現在資源成本、採集延遲、資料覆蓋面等方面無法滿足搜尋服務和流量規模,這影響了穩定性問題解決的徹底性,特別是在搜尋效果問題層面表現尤為嚴重,諸如無法穩定復現搜尋結果異常問題、關鍵結果在索引庫層面未預期召回問題等。穩定性問題是否得到解決永遠是可觀測性建設的出發點和落腳點,毫不妥協的資料建設一直是重中之重。從2023年起,搜尋開始引領可觀測性的創新並將它們做到了極致,使各類問題得以切實解決。

因為搜尋系統規模太龐大,所以kepler1.0只能支援最高10%的取樣率,在實際使用中,資源成本和問題解決徹底性之間存在矛盾。(1)搜尋系統大部分故障都是query粒度的。很多case無法穩定復現,但又需要分析出歷史上某個特定query的搜尋結果異常的原因。讓人無奈的是,當時只有備份下來的日誌才能滿足任一歷史query的資料回溯需求,但它面臨收集成本高的難題;另外,很多query沒有命中kepler1.0的抽樣,其詳細的tracing資料並未有被激發出來,分析無從下手。能看到任一歷史特定query的tracing和logging資訊是幾乎所有同學的願望。(2)公司內部儲存服務價效比較低、可維護性不高,通過擴大取樣率對上述問題進行覆蓋需要的資源成本巨大,實際中無法滿足。對於這個矛盾,業界當時並沒有很好的解決方案。於是,我們通過技術創新實現了kepler2.0系統。系統從實現上將tracing和logging兩種資料解耦,通過單一職責設計實現了針對每種資料特點極致優化,以極低的資源開銷和極少的耗時增長為成本,換取了全量query的tracing和logging能力,天級別數十pb的日誌和數十萬億量級的呼叫鏈可實現秒查。讓大多數故障追查面臨的問題迎刃而解。

查詢時,將inode、offset、length傳送給索引ip所在的機器(即原始日誌所在機器),通過機器上日誌讀取模組,可根據inode、offset、length以o(1)的時間複雜度定點查詢返回日誌原文,避免了對檔案的scan過程,減少了不必要的cpu和io消耗,減小了日誌查詢對生產環境服務穩定性的影響。同時,除了支援location索引以外,我們還支援了靈活索引,例如將檢索詞、使用者標識等有業務含義的字段為二級索引,方便問題追查時拿不到queryid的場景,可支援根據其他靈活索引中的資訊進行查詢;在索引的使用方式上,除了用於日誌查詢以外,我們還通過索引推送方式構建了流式處理架構,用於支援對日誌流式分析的應用需求。這裡還有乙個問題:查詢某一query的日誌時,是不是仍然需要向所有例項廣播查詢請求?答案是:不會。我們對查詢過程做了優化,方法是:通過下文介紹的callgraph全量呼叫鏈輔助,來確定query的日誌位於哪些例項上,實現定點傳送,避免廣播。

3.2.2 全量呼叫鏈

3.2.2.1 span_id推導式生成演算法

說明:下圖中共有兩個0和1兩個span,每個span由client端和server端兩部分構成,每個方框為向trace系統的儲存中真實寫入的資料。左圖:kepler1.0隨機數演算法。為了使得乙個span的client和server能拼接起來並且還原出多個span之間的父子關係,所有span的server端必須儲存parent_span_id。因此兩個span實際需要向儲存中寫入4條資料。右圖:kepler2.0推導式演算法,span_id自根節點從0開始,每呼叫一次下游就累加該下游例項的ip作為其span_id並將其傳給下游,下游例項遞迴在此span_id上繼續累加,這樣可以保證乙個query所有呼叫的span_id是唯一性。例項只需要儲存自己的span_id和下游的ip,即可根據演算法還原出乙個span的client端和server端。由此可見,只需要寫入2條資料且資料中不需要儲存parent_span_id,因此儲存空間得到了節省,從而實現了全量呼叫鏈的採集能力。右圖中ip1:port1對ip2:port的呼叫鏈模擬了對同乙個例項ip2:port2訪問多次的場景,該場景在搜尋業務中廣泛存在(例如:乙個query在融合層服務會請求同乙個排序服務例項兩次;排程層面上游請求下游異常重試到同乙個例項等),推導式演算法均可以保證生成span_id在query內的唯一性,從而保證了呼叫鏈資料的完整性。

3.2.2.2 資料壓縮

3.2.3.1 時光穿越:歷史上任一特定query的關鍵結果在索引庫層面未預期召回問題

3.2.3.2 鏈式分析:有狀態服務導致「誤中副車」型效果問題

百度搜尋的「黑」與「白」

搜尋一直以來都是乙個動態化發展的過程,每隔一定週期,對方都會推出各種演算法,調整搜尋線上的狀態,目的只有乙個 提供更優質的搜尋服務,快速解決潛在訪客的搜尋需求。但,道生一,一生二,二生三,三生萬物,有 正 亦有 邪 有 黑 既有 白 對於搜尋而言的seo,亦是如此。於是白帽seo講黑帽你是違規的 作...

乾淨的百度搜尋 思路

再一搜 笑死,原來被查了。2,正規表示式,或xpath等搜尋對應元素。可參考 nlp 獲取相似詞 2.提取相似詞 原理都是一樣的。3,用flask做乙個伺服器,並且有個簡單的介面。我做了乙個 系列教程a.從零開始前後端react flask 可能會用到一些知識。我一般的創作內容,都是基於實際需求的,...

百度搜尋引擎蜘蛛ip分析

123.125.68.這個蜘蛛經常來,別的來的少,表示 可能要進入沙盒了,或被者降權。220.181.68.每天這個ip 段只增不減很有可能進沙盒或k站。121.14.89.這個ip段作為度過新站考察期。203.208.60.這個ip段出現在新站及站點有不正常現象後。210.72.225.這個ip段...