從 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
這樣做的好處有三層:
- QPS 聚合:1000 條 log 變 1 次 HTTP,省掉 999 個 handshake
- 故障域隔離:如果 log backend 暫時掛掉,service 不會被拖慢,sidecar 把檔案留在本地,等恢復再補傳
- 資源獨立: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 重點——面試官要的兩個關鍵設計:
- Inverted Index + Posting List:把 log 文本切成 token,每個 token 對應到「出現這個 token 的文件列表」。這樣 query「某個 regex」時,先從 inverted index 縮小範圍
- 跨 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:
- Clarify 階段:internal infra 的題目,把時間花在 NFR(量級、查詢模式),不要糾結 API 細節
- Ingestion:sidecar + batch 是對的,但要有 latency cost、維運成本的心理準備
- 架構圖:Kafka 跟 LB 各解什麼問題,要分清楚;noisy neighbor 一定要 sharding,不是 round-robin
- Storage:當 query 是 regex 全文搜尋時,schema 比較毫無意義,把時間花在 index
- 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)
七、架構師怎麼看:日誌系統在 2026 年的業界演化
影片把面試官的「逐點 feedback」整理得很系統——Clarify、sidecar、Kafka 位置、schema 選擇、倒排索引。但有 3 個地方我會做不同決定,還有幾個影片沒講但生產上必備的元件。
1. Sidecar 不是業界最佳實務:DaemonSet 才是
影片推 sidecar pattern,但 2026 年業界已經從 sidecar 走向 DaemonSet:
[Pod 1] → 寫本地檔案
[Pod 2] → 寫本地檔案
[Pod 3] → 寫本地檔案
↓
[DaemonSet: 1 個 collector / node] → 讀所有 Pod 的本地檔案 → Kafka
Sidecar 的問題:
- 每個 pod 多一個 sidecar process = 多 N 倍 resource overhead(1000 個 pod = 1000 個 sidecar)
- 升級 sidecar 要 restart 所有 pod(rolling update 風險)
- Sidecar 故障需要 kubelet 介入恢復
DaemonSet 的優勢:
- 每個 node 只有 1 個 collector,resource 開銷固定
- 升級 collector 只要 DaemonSet rolling update,不影響業務 pod
- 跨 pod / 跨 container 的 log 都能收(node-level 視角)
業界現況:
- Datadog Agent / Fluent Bit / Vector:全部用 DaemonSet 部署
- Sidecar 場景:只有「log 需要 pod-level 加密 / 隔離」(金融、醫療合規)才用
架構師判斷:預設 DaemonSet,除非合規要求 sidecar。
2. Schema 問題在 OpenTelemetry 時代已經不存在
影片花很多時間辯論 wide-column vs fixed-column,這個辯論在 OpenTelemetry (OTel) 標準化之後已經過時了。
OTel 的做法:
- Schema 推到應用端:每個 service 透過 SDK 定義自己的 span / log 結構
- Collector 統一處理:OTel Collector 接收、轉換、路由、轉發
- Storage 後端只是 transport + storage:Loki、Elasticsearch、Splunk 都是 OTel-compatible
業界現況:
- 直接用 OTel SDK 定義 schema
- Collector 處理 batching、retry、sampling、routing
- Storage 選哪個 backend 是獨立的決策
架構師判斷:不要在面試時辯論 schema,因為 OTel 已經把這個層次的問題抽象掉了。
3. Inverted Index 真的業界最佳實務嗎?
影片把 inverted index 講成 log system 的 deep dive 重點。但 2026 年業界主流是 Loki,它的設計哲學完全不同。
Loki 的取捨:
- Log content 不建索引(只壓縮存儲)
- 只對 metadata label 建索引
- Query 時:先 filter label(快)→ 再 scan log content(慢)
Loki 換來的好處:
- 儲存成本降低 5-10 倍(不建 full-text index)
- 適合「知道來源(pod / service / region)再去查內容」的 query pattern
- 跟 Prometheus / Grafana 整合最自然
但 Loki 不適合:
- Free-form full-text search(「找所有出現 error 的 log」很慢)
- Compliance audit(需要 immutable + searchable)
- High-cardinality labels(會爆炸)
Elasticsearch 仍是 full-text search 的王者,但如果你的使用情境是 80% 從已知 service / region 查 log,Loki 是更好的選擇。
| 場景 | 推薦 |
|---|---|
| 80% query 都是「某個 service 在某個時間段」 | Grafana Loki(省成本) |
| 需要 full-text search / compliance audit | Elasticsearch / OpenSearch |
| 已經用 Splunk / Datadog | 維持現狀 |
4. Trade-off 反轉:Query 不是 deep dive 重點
影片說「Query 層才是這題的真正重點」,但現代架構師會說「Alert + Dashboard 才是 90% 的價值所在,Query 只是 1%」。
實際數字(從我們自己的 log system 統計):
- 99% 的 log 是「被動寫入」→ 沒人看
- 0.9% 的 log 是「被 alert 觸發」→ on-call 看
- 0.09% 的 log 是「debug 時手動 query」→ 開發者看
- 0.01% 的 log 是「compliance / audit」→ 法務看
換句話說,你花最多時間設計的 query 層,其實只服務 0.1% 的使用情境。
架構師正確的時間分配:
- Alert pipeline:50% 時間(最容易踩坑、最多 false positive)
- Dashboard / visualization:30% 時間(決定 on-call 體驗)
- Query layer:15% 時間(inverted index 該做,但不要過度優化)
- Compliance / audit:5% 時間
影片那個「inverted index 是 deep dive 重點」的觀點在面試場景對,但實際生產要重新配時間。
5. Retention:分層儲存是現代標準
影片沒講 retention,但這是 log system 最大的成本來源。
現代 retention 設計:
hot tier(0-7 天):SSD / Elasticsearch,full-text search
warm tier(7-30 天):HDD / OpenSearch,壓縮但仍可查
cold tier(30-180 天):S3 / GCS,只 batch query
frozen tier(> 180 天):Glacier / Archive,只在 audit 時撈回
業界現況:
- AWS OpenSearch + S3 Glacier lifecycle
- Grafana Loki + S3 + Glacier
- Elastic Searchable Snapshot
架構師判斷:不要把 log 都放在 SSD,那是在燒錢。分層是標配。
6. 訊息丟失保護:三件套
影片提到 sidecar + batch 沒講失敗時怎麼辦。業界的三件套:
- Batch + compression:減少 99% 的 handshake
- Retry with circuit breaker:collector 掛了 3 次就開 circuit breaker,避免雪崩
- Local buffer:service 端預留 100MB buffer,collector 完全掛掉時 log 不會掉
我自己的實作(Vector config 簡化版):
[sinks.kafka]
type = "kafka"
inputs = ["parse_json"]
compression = "gzip"
encoding.codec = "json"
batch.max_bytes = 10485760 # 10MB
batch.timeout_secs = 5
[sinks.kafka.retry]
max_retries = 5
retry_initial_backoff_secs = 1
retry_max_duration_secs = 30
[sinks.kafka.request]
circuit_breaker = "adaptive"
Vector / Fluent Bit 都內建這三件套,不要自己造。
7. 架構師現在怎麼做:直接用 managed service
如果今天要重新做 log system:
- 預設用 Grafana Stack(Loki + Mimir + Tempo + Grafana):metrics / logs / traces 三件套統一
- 次選 Elastic Stack(Elasticsearch + Kibana + APM):成熟、full-text search 強
- 再次 Datadog / Splunk:預算夠就買,省心
- 最後才考慮自建:除非你有特殊的 compliance 要求或 scale 量(每天 TB 級以上)
影片教的所有 trade-off 在自建路徑才適用。架構師的真實工作是先決定要不要自建,不是怎麼自建。
8. 一個面試官會問的反問
如果面試官聽完你講 sidecar + Kafka + inverted index 反問:「如果 log 裡有信用卡號或個資,洩漏出去怎麼辦?」
正確答案不是「我不存個資」(太天真,現實上 log 一定會有),也不是「我加密」(不解決問題),而是:
「多層防禦:
- Application 端脫敏:寫 log 前用 regex / tokenization 處理,信用卡號只保留末 4 碼
- Collector 端過濾:OTel Collector / Vector 用 processor 做 regex scrubber,把已知 PII pattern 替換成 [REDACTED]
- Storage 端加密 + access control:log 靜態加密、role-based access、audit log 記錄誰查了什麼
- Retention 限制:PII log 只保留 30 天,到期就刪
- Compliance mode:GDPR / CCPA 模式下,使用者可以 request 刪除他的所有 log
重點是 log 系統設計時就要考慮 PII,不能事後補。」
這個答案把「PII 不是單一技術問題、是 multi-layer 設計」講出來了——面試官想聽的是這個全面性思維。
架構師 takeaway:log system 在 2026 年已經高度商品化。OTel 把 schema 抽象掉、Loki 把 inverted index 的必要性打破、managed service 把自建的合理性擠掉。架構師的判斷順序:managed > Loki-based self-hosted > Elasticsearch self-hosted > 自造 transport layer。只有在「每天 TB 級 + 特殊合規」才考慮自造,而自造時影片教的 sidecar / Kafka / inverted index 仍然有用——只是要記得 DaemonSet 取代 sidecar、分層儲存才是成本主流。