Hero Image
- Mark

即時聊天系統架構:從需求到容量估算的全景筆記

即時聊天系統架構:從需求到容量估算的全景筆記

本文整理自一支系統設計教學影片,加上我自己的筆記與延伸觀點。當作 reference 寫,之後面試或真的要設計即時通訊服務的時候,可以直接回來查。

一、從需求開始:聊天系統到底要解決什麼

聊到聊天系統,第一個反應就是「不就是訊息收發嗎?」但真要展開設計,需求面要先講清楚,否則後面的架構選擇會沒有依據。

Functional Requirements

  • One-on-One Chat:一對一聊天是核心。
  • Online Message Delivery:對方在線時,訊息要即時送到。
  • Offline Message Delivery:對方離線,訊息要存起來等他上線讀。
  • Group Chat:多人聊天,但建議限制人數(微信上限約 200 人,邀請制可到 500 人)。
  • Presence Status:線上狀態顯示,像 QQ 那種頭像亮燈。

Non-Functional Requirements

  • Scalability:假設 10 億使用者註冊(1 Billion Users)。
  • Latency:低於 500ms,最好秒級內。
  • High Consistency:雙方看到的訊息順序要一致;訊息不能丟。
  • Fault Tolerance:不能隨便掛。

Multi-Device 是加分題,不是必答題。影片原話講得很直接:「主要的先解決,剩下的有時間再說。」

二、客戶端與伺服器的三種對話方式

這題我自己在準備面試時,常被問倒。因為一般設計 Twitter、Instagram 是「客戶端主動拉」,但聊天是「雙向推」。伺服器端要主動把訊息丟給客戶端,但網路層的 NAT 讓這件事變得麻煩。

1. Polling(輪詢)

最直覺:客戶端每隔幾秒問伺服器「有新訊息嗎?」

  • 90% 的查詢是空的(浪費資源)
  • 每次查詢都要重新建立 TCP 連線,三次握手成本高
  • 優點:實作簡單,相容性 100%
  • 缺點:伺服器負擔大、延遲高

2. Long Polling(長輪詢)

客戶端掛一個長連線在伺服器上,有訊息就回,沒訊息就 hold 著直到 timeout 再重連。

  • HTTP-based,相容性好
  • 需要管理連線的掛起、超時、喚醒邏輯
  • 比 Polling 節省資源,但伺服器維護大量掛起連線也是成本

3. WebSocket

真正的雙向通訊,伺服器和客戶端都可以主動發訊息。

  • 延遲最低、傳輸效率最高
  • 但需要伺服器和客戶端都支援 WS 協定
  • 舊瀏覽器相容性差

行動端的額外考量

手機 App 才是聊天系統的主戰場。Wi-Fi 切到 4G、基地台換了,IP 就變了,這時候 WebSocket 要重建連線。所以要引入 Client Token 來定位使用者,而不是用 IP。

更進階的選項是 QUIC(Google 提出),原生支援跨網路切換、阻塞控制。問題的時候可以 Fallback 回 WebSocket。

我的取捨建議:如果不是為了面試,現在新專案直接上 WebSocket + Client Token,行動端考慮 QUIC。Long Polling 留給必須相容舊瀏覽器的場景。

三、Session Register:在線狀態與路由基礎

定好通訊方式後,下一個問題是:訊息要送到哪台伺服器?

Heartbeat 機制

使用者登入時,會被分配到一台 Chat Server。客戶端每 10 秒發一次心跳(Heartbeat)。如果伺服器幾分鐘沒收到心跳,就視為離線。

存什麼

用一個 KV Store 存「會話註冊表」(Session Register):

欄位 範例
User ID u_12345
Last Heartbeat 1723891200
Chat Server chat-server-42
Metadata device type, app version

容量估算

  • 每條 Session 記錄約 100 bytes
  • 10 億註冊 × 20% DAU × 25% 在線 = 5000 萬在線
  • 5000 萬 × 100 bytes ≈ 5 GB

一般 KV Store 頂得住。

Presence 通知怎麼推

使用者狀態變化(上下線)時,可以推給他的線上好友。每個使用者在 Chat Server 上有一個「邏輯收件箱」,Presence 通知直接進收件箱。

這類通知對一致性要求不高——你晚幾秒收到「好友上線」的提醒,沒人會在意。

四、訊息投�架構:兩種主要路線

這一段是聊天系統設計的核心。有兩個完全不同的方向:把雙方湊到同一台機器,或讓訊息在機器間跑

方案 A:Session Affinity(會話親和)

把正在聊天的兩個使用者,盡量遷到同一台 Chat Server。

  • 優點
    • 訊息本機投遞,延遲最低
    • 訊息排序簡單(用本地時鐘就好)
  • 缺點
    • 使用者會在伺服器之間不停遷移,造成業務抖動
    • 熱門使用者會造成 Hotspot(rehash、sharding 都得做)

適合:即時性要求極高的場景(例如多人遊戲房間內聊天)。規模小也適用。

方案 B:Message Sync(訊息同步)

每個使用者掛自己的 Chat Server,伺服器之間透過 RPC 或訊息佇列轉發。

  • 優點
    • 水平擴容容易,使用者多就加機器
    • 使用者不需遷移,直接連自己的 Chat Server
  • 缺點
    • 多一層轉發,延遲高
    • Session Register 必須精準(錯了就送不到)
    • 雙端時鐘不同步,訊息順序問題複雜

優化:中心化 Pub/Sub Message Bus

如果你有 N 台 Chat Server,伺服器之間全互聯是 N² 條鏈路,太複雜。

更好的做法是引入一個中心化的 Pub/Sub 訊息匯流排

  1. 訊息先寫到中心訊息佇列
  2. 接收方的 Chat Server 訂閱屬於自己的 topic
  3. 訊息一體化處理:持久化 + 排隊 + 轉發
  • 持久化、訊息排隊、轉發整合在一起
  • 鏈路複雜度降低(從 N² 變成中心 fan-out)
  • Chat Server 可獨立彈性擴容

風險:中心化架構容易出 Hotspot。實務上要做 sharding、多佇列切分。

五、容量估算的具體數字

系統設計面試最容易被問倒的不是架構圖,而是「你的數字哪裡來的?」

訊息量

  • 峰值在線:50M(5 千萬)
  • 高峰時段:每 5 秒一條訊息 = 0.2 msg/sec/user
  • 總訊息量:50M × 0.2 = 每秒 1000 萬條訊息

單訊息大小

欄位 大小
Message ID 8 bytes
From (User ID) 8 bytes
To (User ID) 8 bytes
Content(200-300 漢字 UTF-8) 600-800 bytes
Timestamp 8 bytes
小計 < 1 KB

壓縮後約 0.5 KB/條

總流量

10M msg/sec × 0.5 KB = 每秒 5 GB

現代資料中心吃得下。

Chat Server 數量

兩種情境差很多:

  • WhatsApp 等級(單機 200 萬並發):50M ÷ 2M = 25 台就夠
  • 普通機器(單機 5 萬並發):50M ÷ 50K = 1000 台

WhatsApp 2012 年的技術部落格講過,他們單機能撐 200 萬連線,用的是 Erlang + Actor 模型,這是特例不是常態。

地理親和的假設

聊天對象大概率是身邊的人(同事、家人、朋友),地理相近會被分到同一個資料中心。

  • 同機率假設 20%
  • 80% 訊息走跨服轉發

單機轉發量估算:

2M users × 0.2 msg/sec × 0.5 KB × 80% 轉發 = 每台 160 MB/s

加上雙向(1-1 chat 兩邊都要送),約 320 MB/s

普通機器或 Kafka 都能扛。如果走 Kafka,10 台 broker 處理 5 GB/s 完全沒問題。

六、群聊、離線訊息與隱私

群聊實作

群聊訊息 Schema 和一對一類似:

group_id | message_id | user_id | content | timestamp
約 0.5 KB/條

需要一個 Group Registration,記錄每個群成員分散在哪些 Chat Server。

範例:500 人群分散在 10 台 Chat Server → 訊息要複製 10 份跨服。但伺服器內部可以用同機路由減少跨服開銷。

離線訊息

對方不線上時,訊息進 Offline Storage

  • 2 億 DAU × 每天 40 條 × 15% 離線 × 0.5 KB = 0.6 TB/day
  • 保留 30 天 ≈ 18 TB

實作選擇:

  • 簡單場景:檔案系統,每個使用者一個資料夾,log file append-only
  • 高吞吐:NoSQL / KV Store,水平擴容友善

離線訊息對延遲不敏感,技術選型可以保守。

隱私 vs 資料安全

影片最後一段我覺得蠻有意思的:

「如果不是很必要,我們應該盡可能少保存聊天資料。一旦 message deliver 後就從記憶體刪掉,既保護使用者,又降低洩漏風險,同時降低系統複雜度。」

企業用的 IM(Slack、Teams)需要長期保存聊天記錄沒問題,但面向一般消費者的產品,這個權衡要重新思考。GDPR、隱私法規、使用者信任——這些都不是技術問題,但會影響你的架構選擇。

結語

聊天系統架構沒有「標準答案」。每一個選擇都是延遲、複雜度、可靠性的三角權衡。

WhatsApp 用 Actor 模型 + Erlang 做到單機 200 萬並發,這是特例不是常態。大部分團隊會落在「中心化訊息佇列 + 多 Chat Server 轉發」的甜蜜點,並靠 sharding 和多佇列切分避免中心瓶頸。

面試時把 trade-off 講清楚,比背架構圖更重要。數字記得有把握(5 GB/s、25 台、200 萬連線),這是基本功。

之後如果要真正實作,重點會落在三件事:

  1. 訊息順序保證(單調遞序 ID vs 邏輯時鐘)
  2. 訊息投遞保證(ack、重試、exactly-once 語意)
  3. 離線訊息同步(增量同步、last-read cursor、conflict resolution)

這幾個題目之後再寫一篇。


參考資料

  • YouTube 影片:「Design a Chat System」系統設計教學
  • WhatsApp Engineering Blog(2012 單機 200 萬連線案例)
  • C10M Challenge(單機 1000 萬並發連線目標)

Other Related Posts:

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

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

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


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

這篇整理影片裡面試官挑出的五個關鍵設計決定,包含他自己的「我會怎麼問」與「為什麼這樣...

17th Aug 2026 - Mark
支付系統設計:訂單、支付、對帳的一致性與冪等

支付系統設計:訂單、支付、對帳的一致性與冪等

支付系統設計:訂單、支付、對帳的一致性與冪等

這篇文章是看了 s09g 在 YouTube 上發的「system design — payment system」(19:47)之後的整理筆記。

我必須先承認一件事:我在寫金流的時候,第一次看這種題目也是先翻 Stripe 文件、把 SDK 串起來、看到 payment_intent.succeeded 就覺得「啊我會接金流了」。但 s09g 影片一開始就潑了一盆冷水——你沒有金融牌照,你拿什麼去划帳?

金流系統設計的本質,不是「怎麼呼叫 PSP」,而是「怎麼把一筆支付的事實記下來,並且保證它永遠對」。這才是後端工程師真正要扛...

17th Aug 2026 - Mark