Hero Image
- Mark

Log System 系統設計:面試官逐點拆解的五個關鍵取捨

從 sidecar 模式、Ingestion 架構到倒排索引,一次搞懂集中式日誌系統設計的面試重點


最近看了一支 s09g 的系統設計 Mock Interview,受面者設計「集中式日誌系統」,面試官在 45 分鐘內從 Clarify 一路 DeepDive 到查詢層,把每一層的設計決定都翻過一遍。這類「面試官逐點 feedback」的影片,對準備系統設計面試的人特別有價值——比起「如何設計一個 log system」的教學文,它揭露的是真正的 trade-off 與面試官在意什麼

這篇整理影片裡面試官挑出的五個關鍵設計決定,包含他自己的「我會怎麼問」與「為什麼這樣問」。每節都附面試官的質疑點,下次你自己上場時可以避開。

一、Clarify 階段:你花 9 分鐘在錯的問題上

面試一開始面試官就點出一個時間分配問題:受面者光是 Login API 的細節就討論了 9 分鐘。

這個錯誤很常見。受面者很容易陷入「把題目當產品 PRD 在寫」的陷阱,把所有 API 規格、欄位定義都講清楚。但對內部基礎設施(internal infra)的題目來說,public API 的相容性根本不是重點——你內部用,今天跟昨天介面不一樣,沒人會死。

面試官真正的期望是:你把時間花在 non-function requirement,也就是:

  • 寫入量級:每分鐘多少筆 log?平均多大?
  • 儲存量級:保留多久?每天總量?
  • 查詢模式:誰會查?多久查一次?query 的時間區間多大?
  • 錯誤容忍:丟一點 log 可以嗎?

這四個數字決定了後面每一層的技術選型。沒問清楚就畫圖,等於在沙地上蓋房子。

順帶一個小技巧:受面者在講 API 時可以包裝一下——「這個介面我用一個 wrapper 抽象掉,實際呼叫端不需要知道底層是 batch 還是 stream」。一句話帶過,面試官不會再追。

二、Ingestion 層:sidecar + 批次壓縮的真實成本

第一個 deep dive 點:log 怎麼從 service 送到 backend?

受面者原本的設計是一條一條用 JSON stream 推到後端。面試官直接否決——理由很扎實:

  • 一條 log 一次 HTTP request = 一輪 TCP handshake
  • 服務跑在高 QPS 場景時,這些 handshake 是純粹的浪費
  • 還會打爆 backend 的 connection pool

正確的設計是 sidecar 模式

[你的 service] → 寫到本地檔案 (e.g. /var/log/app.log)
       ↑
[sidecar agent]  ← 每 N 秒 batch 讀取 → HTTP POST → centralized log server

這樣做的好處有三層:

  1. QPS 聚合:1000 條 log 變 1 次 HTTP,省掉 999 個 handshake
  2. 故障域隔離:如果 log backend 暫時掛掉,service 不會被拖慢,sidecar 把檔案留在本地,等恢復再補傳
  3. 資源獨立:service 跟 log agent 是兩個 process,log 的資源壓力不會直接打到業務

但面試官點出了真實成本——這些好處不是免費的:

  • 延遲成本:你等一個 batch 才能送一次,log 到達後端的時間會延遲 batch interval(常見 30s~1min)。如果你的 log 系統用於即時告警,這個延遲要納入考量
  • 維運成本:sidecar 是另一個 deployment unit,要有人 maintain、要單獨 roll out。service 跟 agent 打包在同一 pod 是「方便」,但不是「零成本」
  • 故障點:pod 裡多一個 process,就多一個可能出錯的地方

面試官要的不是「sidecar 是好的」這種二元結論,而是你能清楚說出哪些 cost 是 unavoidable、哪些是你選擇承擔的

三、Ingestion 架構:Load Balancer + Kafka 在哪一邊?

第二個 deep dive 點:架構圖長什麼樣?

受面者先畫了一版:Service → Load Balancer → Kafka → Consumer → Storage。後來又改成 Kafka → LB → Service,自己也解釋不清楚為什麼要加 LB、為什麼 LB 在 Kafka 前後的位置要調。

面試官拆得很細:

為什麼要 LB?解的是 noisy neighbor

如果你的 log system 是 multi-tenant(100 個 team 共用),最大的風險是一個 team 吃掉 50% 資源,其他人被拖累。

LB 的真正用途不是「分流量」那麼表面,而是:

  • clientID(team ID)做 sharding
  • 每個 team 路由到固定的 backend shard
  • 再用一層 hash 處理 team 內的進一步分流

單純的 round-robin LB 解不了 noisy neighbor——A team 流量再大都只是多輪幾次,B team 一樣被打擾。只有 sharding 才能資源隔離

Kafka 在前面 vs 後面

受面者把 Kafka 放在 LB 後面,被面試官挑戰:「Kafka 自己不是可以做 partition consumer 嗎?為什麼還要 LB?」

受面者的 defense 是 tolerance:Kafka 當 buffer,上游突然 spike 不會打爆 consumer。

這個論點是 make sense 的——Kafka 的設計本來就是 absorb 寫入尖峰。所以 Kafka 放在 ingestion 第一線沒問題。LB 的角色是「分給哪個 ingestion topic/partition」,不是「做 TCP load balancing」。

面試官會追問的是:你能說清楚 Kafka 跟 LB 在這層各負責什麼嗎? 不要混為一談。

四、Storage 層:Wide-column vs Fixed-column 的真實差異

第三個 deep dive 點:log 要存哪?

受面者展開了兩個 option:

Wide-column(Cassandra 類)

  • 沒 schema,隨便寫新 column
  • 適合「每個 team 有自己的 metadata 欄位」的情境
  • 缺點:分析型 query(aggregate、scan)不優,不是設計目的

Fixed-column(傳統 RDB / 預定義欄位)

  • 預先知道 timestamp、code location、source control info 這些常見 metadata
  • 已知欄位查詢快、有 index 加速
  • 動態欄位要塞 JSON,每次 query 要 out-of-line parse JSON

面試官的反擊很犀利:

「如果我根據 metadata(timestamp、code location)查,兩種都能做。如果我要用 regex 匹配 log 內容,兩種都是全表掃描。這個 trade-off 是不是其實沒打到重點?」

這句話戳到重點——當你的 query pattern 是「全表掃某個 regex」時,schema 怎麼設計根本沒差。所以展開方向錯了。

面試官要的答案是:log 系統的瓶頸在 query 層,不在 schema 設計。換句話說,你應該把時間花在「怎麼讓查詢變快」,而不是「選 wide 還是 fixed」。

五、QA 層:為什麼不能把 Storage 當查詢層用?

第四個 deep dive 點(也是這題的真正魔王):debug 的人怎麼查 log?

受面者直接把 query 丟給 storage 層做全表掃。面試官打槍:

先算讀寫比

  • 寫:所有 service 全天候在寫 log,每分鐘可能數千到數萬行
  • 讀:只有 on-call debug 的人在查,每天可能就 20-30 人

這是典型的 write-many / read-mostly 場景,但讀的總量小但 query pattern 很複雜

Query window 不可預測

跟 metric collection 不一樣——metric collection 的 query window 通常固定(過去 15 分鐘、過去 1 小時),可以預計算。

log debug 不一樣:

  • 我先查過去 1 小時 → 沒定位到 bug
  • 放大到過去 24 小時 → 還是沒有
  • 拉大到過去 7 天甚至 30 天

這代表你不能 pre-compute。每次 query 都是大範圍的即時搜尋。

解法:倒排索引 + 分片並行

這才是這題真正的 DeepDive 重點——面試官要的兩個關鍵設計:

  1. Inverted Index + Posting List:把 log 文本切成 token,每個 token 對應到「出現這個 token 的文件列表」。這樣 query「某個 regex」時,先從 inverted index 縮小範圍
  2. 跨 shard 並行查詢:把 posting list 拆到 N 個 shard,query 同時打 N 個 shard 再合併結果。這樣才能在大資料量下維持查詢延遲

受面者在 storage 層花太多時間在 schema 比較,反而把這題最關鍵的 index 設計跳過了——面試官直接說這是 knowledge gap。

六、面試官最後的時間預算提醒

整場面試 45 分鐘,受面者畫完 high-level diagram 後只剩 18 分鐘。Storage 展開方向錯了,導致最後 1 分鐘根本沒時間 cover analysis 層(query 的進階處理:aggregation、dashboard、anomaly detection)。

面試官最後一句總結很值得記住:

「DeepDive 的重點應該放在 index 上,不是 schema 選型。」

結語:給準備系統設計面試的你

這支影片最珍貴的不是「log system 怎麼設計」的答案,而是面試官怎麼看你的設計決定。整理五個 takeaway:

  1. Clarify 階段:internal infra 的題目,把時間花在 NFR(量級、查詢模式),不要糾結 API 細節
  2. Ingestion:sidecar + batch 是對的,但要有 latency cost、維運成本的心理準備
  3. 架構圖:Kafka 跟 LB 各解什麼問題,要分清楚;noisy neighbor 一定要 sharding,不是 round-robin
  4. Storage:當 query 是 regex 全文搜尋時,schema 比較毫無意義,把時間花在 index
  5. Query 層:log debug 的 query window 不可預測 → 不能 pre-compute → inverted index + posting list + sharding 是標準解

系統設計面試不是考你「會什麼」,是考你「能不能在 45 分鐘內,把 trade-off 講清楚」。把這五個觀念記下,下次上場會穩很多。


參考資料

  • 影片:[系统设计 Mock] Logger System — s09g(2026-08-05)
  • 延伸閱讀:Designing Data-Intensive Applications Chapter 3(Storage)、Chapter 11(Stream Processing)

Other Related Posts:

建一個 Job Scheduler 之前要釐清的 11 個取捨點

建一個 Job Scheduler 之前要釐清的 11 個取捨點

建一個 Job Scheduler 之前要釐清的 11 個取捨點

任務調度系統(Task Scheduler / Job Scheduler)這種東西,看起來每家公司都有,用起來都差不多,但只要你認真去看一次原始碼,就會發現每個團隊的取捨都不一樣。

這篇文章不是要告訴你「任務調度是什麼」。網路上的科普文已經太多了。我要講的是:當我們真的坐下來要畫一張架構圖,每一個節點為什麼要這樣選。參考的影片是 s09g 的《system design — 任務調度系統》(約 29 分鐘),我把裡面 12 個章節的取捨整理成一條線,並加上我自己做後端這些年的看法。

我們的場景先講清楚:假設要替...

17th Aug 2026 - Mark