![]()
作者 | Sergio De Simone
譯者 | 平川
LinkedIn 的工程師們遇到了 一種短暫且反復出現的故障,即支撐用戶信息流的數據庫會突然不可用,隨后又恢復正常,而且沒有留下任何有用的痕跡。他們不得不設計一種新方法,利用 eBPF 進行離線 CPU 性能分析(off-CPU profiling)來查明根本原因。
正如 LinkedIn 工程師 Pratikmohan Srivastav 所介紹的那樣,調查這些事件尤為困難,因為它們轉瞬即逝,僅持續 10 到 15 秒,而且未留下任何有用的日志。此外,該類事件反復發生,既無明顯規律,也未顯示出明確的外部觸發因素。
通過將這些事件與系統內存行為進行關聯,他們初步發現了一個線索:每個事件都伴隨著內存分配的短暫激增,然后迅速恢復,系統在更高的基準水平上趨于穩定。進一步分析排除了其他常見的原因,包括 CPU 降頻、內存碎片化和壓縮以及文件 I/O。
因此,基于常規監控和指標的分析未能觸及問題的根本原因,這促使 LinkedIn 工程師深入探究了系統凍結期間操作系統和運行時層面的行為。他們轉而采用離線 CPU 性能分析方法來了解當時哪些線程被阻塞了。
我們的解決方案是構建一種監控機制。我們編寫了一個監控腳本,一旦檢測到系統卡死,該腳本就會立即自動進行離線 CPU 性能分析。
該腳本的工作原理如下:
該腳本使用了一個名為 BCC 的 eBPF 工具包,用于持續監控數據庫健康狀況,并在檢測到異常時立即觸發 BCC 的 offcputime.py 分析器,記錄被阻塞或處于休眠狀態的線程在 15 秒鐘內的內核堆棧跟蹤信息。
這使得 LinkedIn 的工程師們能夠在系統實時凍結期間捕獲離線 CPU 性能分析信息:
這是關鍵的突破口。這些事件發生得太過短暫,常規監控無法捕捉其根本原因,因此要觀察根本原因,唯一的方法就是在系統凍結開始時,用已經部署好的性能分析工具獲取當時的信息。
經排查,根本原因在于一次約 3.5 GB 的大規模內存分配,這導致 mmap_lock 信號量在內核級被鎖定,從而阻塞了所有線程。
任何修改進程虛擬地址空間的操作(如大規模的 mmap 分配)都必須以寫模式持有此鎖。在持有寫鎖期間,所有需要進行內存操作的其他線程(包括用于清理的 madvise 以及用于 I/O 的頁面故障處理)都會被阻塞。
進一步分析發現,這次內存分配是由 Rust 內存中的 HashMap(pkey_vs_docref)觸發的。該 HashMap 負責將主鍵映射到內部文檔引用。當條數超過 58,720,256 時,達到了調整大小閾值,進行了翻倍操作。
查明根本原因之后,LinkedIn 工程師便通過預分配 HashMap 的方式迅速地解決了該問題,避免了運行期間的調整操作。這一措施會導致啟動時額外占用約 3 GB 的駐留內存,但事實證明這是一個可以接受的權衡。
Srivastav 指出,這一事件揭示了幾個重要的教訓:預分配大型數據結構有助于防止延遲敏感路徑中出現突發的內存激增;基于 eBPF 的離線 CPU 性能分析是診斷“無聲死機”(這類故障幾乎不留痕跡)的強大工具;對于瞬時性問題,在發生故障時可以自動觸發的自動化監控機制,對于在問題發生時捕獲有意義的診斷信息至關重要。
https://www.infoq.com/news/2026/05/linkedin-kernel-lock-freeze/
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.