Day 21 我們設計了 Notification System。Day 22 來設計另一個經典 System
Design:
Chat System(聊天系統 / 即時訊息系統)
今天的規則仍然一樣:
每個新名詞都先解釋完整英文、中文意思、它是什麼、為什麼需要、簡單例子,再放進
Architecture。
Chat System(聊天系統 / 即時訊息系統):
讓 Users 可以透過 Network 傳送與接收 Messages 的 System。
最簡單:
Alvin
↓
"Hello"
↓
Server
↓
Bob
大型 Chat System 還需要:
One-to-One Chat
Group Chat
Message History
Online / Offline
Delivered Status
Read Status
Multiple Devices
Offline Messages
Message Ordering
Reconnect
One-to-One Chat(一對一聊天):
兩個 Users 之間的 Conversation。
Alvin ↔ Bob
Group Chat(群組聊天):
多個 Users 共同參與同一個 Conversation。
例如:
Group: CSYE6200
Members: Alvin, Bob, Charlie, David
Alvin 發一則 Message,其他 Members 都可能需要收到。
這會產生:
一個 Message
↓
很多 Recipients
後面會介紹 Fan-out(扇出 / 一對多擴散)。
Conversation(對話 / 會話):
一組 Users 之間持續交換 Messages 的邏輯空間。
conversation_id = C123
Members:
Alvin
Bob
Messages:
M1 → Hello
M2 → Hi
M3 → How are you?
ID = Identifier
Identifier → 識別碼
Message ID(訊息識別碼):
唯一識別某一則 Message 的值。
M1001 → Hello
M1002 → Hello
雖然 Content 一樣,但 Message ID 不同,所以 System 知道它們是不同
Messages。
Message ID 可以協助:
Deduplication
Ordering
Delivery Tracking
Read Receipt
Real-Time Communication(即時通訊):
Real-Time → 即時 / 非常接近事件發生的時間
Communication → 通訊
意思:
Message 發生後,希望 Recipient 在很短時間內收到。
Alvin sends → 10:00:00.000
Bob receives → 10:00:00.150
大約 150 ms。
Real-Time 不代表一定是 0 ms,而是 Latency 足夠低,讓 User
感覺互動接近即時。
Latency(延遲):
一個 Operation 從開始到得到結果所花的時間。
Chat:
Alvin Send
↓
Server
↓
Bob Receive
如果 100 ms,User 通常感覺很快;如果 10 seconds,Chat Experience
就很差。
HTTP = Hypertext Transfer Protocol
Hypertext → 超文字
Transfer → 傳輸
Protocol → 協定
中文:
超文字傳輸協定
Protocol(協定):
兩個 Systems 溝通時共同遵守的一組規則。
一般 HTTP 常見:
Client
↓
Request
↓
Server
↓
Response
↓
Client
Client(客戶端):
主動使用 Server 提供服務的 Software / Device。
例如:
Browser
iPhone App
Android App
Desktop App
Server(伺服器):
接收 Client Requests、處理工作並提供服務的 Computer / Software。
Bob 想知道 Alvin 有沒有新 Message,最簡單可以一直問:
GET /messages
↓
Nothing
2 seconds later
↓
GET /messages
↓
Nothing
這叫:
Polling(輪詢)
Client 固定一段時間向 Server 詢問:「有沒有新的資料?」
問題:
很多 Requests
↓
其實沒有新 Message
可能浪費 Network、Server CPU 與其他 Resources。
Long Polling(長輪詢):
Client 發 Request 後,如果沒有新資料,Server
不立即回覆,而是先等待一段時間。
Bob
↓
GET /messages
↓
Server waits...
↓
Alvin sends "Hello"
↓
Server returns "Hello"
如果一直沒資料,最後 Timeout,Client 再建立新的 Request。
它比普通 Polling 減少無意義 Requests,但仍是:
Request → Wait → Response → New Request
WebSocket 是一種 Network Communication Protocol。
可以先理解成:
Client 和 Server 建立一條可以長時間保持,而且雙方都能主動傳送 Data 的
Connection。
Bob
↕
WebSocket
↕
Chat Server
建立後,Server 有新 Message 時可以直接透過 Connection 傳給 Bob,不需要
Bob 每兩秒問一次。
Connection(連線):
兩個 Network Endpoints 之間建立的通訊關係。
例如:
Bob's Phone
↕
Chat Server
Persistent = 持續存在的
Persistent Connection(持久連線 / 長連線):
Connection 建立後不會在一次 Message 完成後立刻關閉,而是維持較長時間。
Connect
↓
Keep Connection Open
↓
Message
↓
Message
↓
Message
這很適合 Chat。
Bidirectional Communication(雙向通訊)
Bi → Two / 兩個
Directional → 方向
Communication → 通訊
意思:
Client 和 Server 都可以主動傳送 Data。
Client → Server
Server → Client
Full-Duplex Communication(全雙工通訊):
雙方可以同時向彼此傳送 Data。
可以想成電話:
Alvin ↔ Bob
雙方都可以說話與接收。
初學階段先記:
WebSocket
→ Persistent Connection
→ Bidirectional Communication
→ 適合 Real-Time Chat
方法 概念 Server 可主動傳資料? Connection
Polling Client 一直問 不直接 多次 Request
Long Polling Server 等到有資料才回 間接 Request 結束後重建
WebSocket 保持雙向連線 可以 Persistent
Chat 的 Real-Time Delivery 很適合 WebSocket。
但 Login、Load History、Create Group 等功能仍然可以使用普通 HTTP API。
Alvin Client
↕
WebSocket
↕
Chat Server
↕
WebSocket
↕
Bob Client
流程:
Alvin sends "Hello"
↓
Chat Server receives
↓
Find Bob's connection
↓
Send to Bob
Users 變成 Millions 時,一台 Server 不可能管理全部 Connections。
Connection Server(連線伺服器):
專門維護大量 Client Connections,接收與傳送 Real-Time Messages 的
Server。
Alvin → Connection Server A
Bob → Connection Server B
Concurrent = 並發的 / 同時存在的
Concurrent Connections(並發連線):
同一時間保持中的 Connections 數量。
例如:
10M Users Online
≈ 10M Concurrent Connections
這和:
10M Requests/day
不是同一件事。
Horizontal Scaling(水平擴展):
增加更多 Servers / Machines 共同處理 Traffic。
Connection Server #1
Connection Server #2
Connection Server #3
...
如果一台安全處理 100K Connections,而 Peak 有 10M
Connections,就需要多台 Servers。
新問題:
Alvin → Server A
Bob → Server B
Server A 怎麼知道 Bob 在 Server B?
需要:
Connection Mapping(連線對應)
記錄 User / Device 現在連在哪一台 Connection Server。
Alvin → Server A
Bob → Server B
Carol → Server C
Registry = 登錄表 / 註冊資訊
Connection Registry(連線登錄資訊):
保存 User / Device 與 Connection Server 對應關係的資料。
User 123
→ Device A
→ Server B
→ Connection XYZ
Routing(路由 / 分流):
決定 Data 應該送到哪個 Destination。
recipient = Bob
↓
Lookup Registry
↓
Bob → Server B
↓
Route to Server B
可以有 Message Router(訊息路由器) 負責這件事。
Online(在線):
User / Device 目前有可用 Connection,或近期仍被視為 Active。
Offline(離線):
User / Device 目前沒有可用的 Real-Time Connection。
但 Online Status 不一定瞬間完全準確,因為 Network 可能突然消失,而
Server 需要時間才能發現。
Presence(在線狀態 / 活躍狀態):
描述 User 現在是否 Online、Offline、Away 等。
Alvin → ONLINE
Bob → OFFLINE
Carol → AWAY
可以建立:
Presence Service(在線狀態服務)
負責管理這些狀態。
Server 怎麼知道 Client Connection 還活著?
Heartbeat(心跳訊號):
Client / Server 定期傳送小型 Signal,表示 Connection / Process
仍然正常。
像人的心跳:
持續有心跳
→ 還活著
System:
Client → PING
Server → PONG
Ping:
用來確認對方是否仍然可連線的小型訊號。
Pong:
對 Ping 的回覆。
PING → Are you alive?
PONG → Yes.
如果很久沒有收到 Pong,Server 可以判斷 Connection 可能已經失效。
Offline Message(離線訊息):
Recipient Offline 時仍被 System 保存,等 User 重新連線後再傳送的
Message。
10:00 Alvin → Hello
Bob Offline
↓
Message stored
10:30 Bob reconnects
↓
Deliver "Hello"
Persistent Storage(持久化儲存):
Process / Machine Restart 後,Data 仍可以保留下來的 Storage。
Chat Messages 通常不能只放 RAM:
Server Crash
↓
RAM Data lost
因此需要 Database / Durable Storage 保存 Message History。
Message Storage(訊息儲存層):
專門保存 Chat Messages 的 Database / Storage。
例如:
message_id
conversation_id
sender_id
content
created_at
sequence_number
Message History(聊天紀錄):
Conversation 過去保存的 Messages。
User 打開 Chat:
Load latest 50 messages
可以透過 HTTP API:
GET /conversations/C123/messages
如果 Conversation 有 1M Messages,不能一次全部傳回。
Pagination(分頁):
把大量 Data 分成小批、小頁讀取。
Latest 50
Previous 50
Previous 50
...
Cursor(游標):
用一個位置標記,告訴 Server 下一次應從哪裡繼續讀。
例如:
GET /messages?before=M1000&limit=50
意思:
給我 M1000 之前的 50 則 Messages
Message Ordering(訊息順序):
確保 Messages 以合理的先後順序呈現。
Alvin:
M1: Hello
M2: How are you?
Bob 不希望看到:
How are you?
Hello
Distributed System 中可能:
M1 → Server A → slow
M2 → Server B → fast
結果:
M2 arrives first
M1 arrives later
所以 Arrival Order 不一定等於 Sender 原本的 Order。
Timestamp(時間戳記):
記錄某件事情發生的時間。
M1 → 10:00:00.100
M2 → 10:00:00.200
看起來可以排序,但不同 Machines 的 Clocks 不一定完全一致。
Clock = 時鐘
Skew = 偏差
Clock Skew(時鐘偏差):
不同 Machines 的 Clock 顯示時間存在差異。
所以不能盲目假設所有 Servers 的 Timestamp 都能提供完美 Global Ordering。
Sequence Number(序號 / 順序號):
用遞增 Number 表示 Message 在某個 Conversation 裡的順序。
C123:
M1 → sequence 101
M2 → sequence 102
M3 → sequence 103
即使 M2 比 M1 更早到 Client,也可以按照 Sequence Number 排成:
101 → 102 → 103
Global Ordering(全域順序):
整個 System 所有 Messages 都有唯一完整的先後順序。
這通常很昂貴,而且 Chat 不一定需要。
Per-Conversation Ordering(每個 Conversation 內的順序):
只要求同一個 Conversation 裡的 Messages 有合理順序。
Conversation A:
1 → 2 → 3
Conversation B:
1 → 2 → 3
A 和 B 誰先通常不重要。
常見:
SENDING
SENT
DELIVERED
READ
Client 正嘗試傳給 Server,Server 還沒確認。
可以定義成 Server 已成功接受並保存 Message。
Message 已到達 Recipient Device / Client。
Recipient 已查看 Message。
實際 Product 可以有不同定義,因此 Interview 中要先說清楚 Status
Semantics。
ACK = Acknowledgement
Acknowledgement → 確認 / 確認收到
意思:
接收方告訴發送方:「我已收到 / 處理這筆資料。」
Client
↓
M1001
↓
Server
Server
↓
ACK M1001
↓
Client
Delivery ACK(送達確認):
Recipient Device 告訴 Server:Message 已經到達。
Server → Bob Device → M1001
Bob Device → Server → ACK M1001
Server:
M1001 → DELIVERED
Receipt = 回執 / 確認紀錄
Read Receipt(已讀回執):
Recipient 告訴 System 某個 Message 已經被閱讀。
Bob reads M1001
↓
READ_RECEIPT
↓
Server
↓
Alvin sees "Read"
因此:
SENT ≠ DELIVERED ≠ READ
Network Failure 時:
Client sends Hello
↓
Server receives it
↓
Response lost
Client 不知道 Server 到底有沒有收到,因此 Retry,可能產生兩則 Hello。
可以讓 Client 先建立:
Client Message ID(客戶端訊息識別碼)
client_message_id = ABC123
Retry 時仍使用:
ABC123
Server 就知道:
same logical message
Idempotency(冪等性):
同一個 Operation 重複執行時,不應產生不必要的重複結果。
ABC123 → Hello
ABC123 → Hello
ABC123 → Hello
Server 最後只建立一個 Logical Message。
Deduplication(去重)
De- → 去除
Duplication → 重複
意思:
辨認並忽略重複的 Message / Request。
ABC123 already processed
↓
Do not create another message
Reconnect(重新連線):
Connection 中斷後,Client 再建立新的 Connection。
Mobile User 可能:
Wi-Fi
↓
Elevator
↓
No Signal
↓
5G
WebSocket 很容易因 Network Change 中斷。
Reconnect 期間可能漏掉 Messages。
Synchronization(同步 / 狀態同步):
讓 Client 補回缺少的 Data,最後恢復到最新正確狀態。
例如:
Client last sequence = 100
Server latest = 105
Server 補:
101
102
103
104
105
Sync = Synchronization
中文:
同步
Chat Context 裡的 Message Sync:
把缺少或更新的 Messages 同步到 Client。
Recovery(恢復):
Failure 發生後,讓 System / Client 回到正確可用狀態。
Connection Failure
↓
Reconnect
↓
Sync missing messages
↓
Recovery
Multi-Device(多裝置):
同一個 User 在多個 Devices 使用同一 Account。
Alvin
├── iPhone
├── Mac
└── Browser
所以:
1 User ≠ 1 Connection
Device ID = Device Identifier
Device → 裝置
Identifier → 識別碼
中文:
裝置識別碼
可以用來區分 User 的不同 Devices。
Alvin 在 iPhone 傳:
Hello Bob
Alvin 的 Mac 也應該看到這則 Message。
所以除了 Recipient Delivery,還可能需要:
Multi-Device Synchronization(多裝置同步)
Group 有 1,000 Members:
Alvin sends 1 message
↓
999 recipients
這叫:
Fan-out(扇出 / 一對多擴散)
一個 Message / Event 產生多個 Delivery Tasks。
Fan-out on Write(寫入時扇出):
Fan-out → 一份資料擴散成多份 Delivery Work
on Write → 寫入時就執行
1 Group Message
↓
Create delivery work for many recipients
優點:
Recipient delivery can be fast
缺點:
Large Group
→ Lots of write work
Write Amplification(寫入放大):
一個 Logical Write 最後造成多次實際 Writes / Work。
1 Group Message
↓
999 Delivery Records
就是 Write Amplification 的例子。
Fan-out on Read(讀取時扇出 / 讀取時組合):
寫入時先保存較少資料,User Read 時再找出自己應該看到的 Messages。
Write:
Store group message
Read:
User opens group
↓
Query relevant messages
Trade-off:
Less write amplification
but
Read path may be more expensive
Trade-off(取捨):
得到某個好處時,通常需要付出另一種 Cost。
所以不是:
Fan-out on Write 永遠最好
或:
Fan-out on Read 永遠最好
要看:
Group Size
Message Frequency
Latency Requirement
Read Pattern
Storage Cost
Messages 成長到 Billions:
Partitioning(分區):
把大型 Dataset 分成多個較小部分。
例如:
Conversation A → Partition 1
Conversation B → Partition 2
Conversation C → Partition 3
Partition Key(分區鍵):
用來決定某筆 Data 應放在哪個 Partition 的 Key。
Chat 可以考慮:
conversation_id
因為同一 Conversation 的 Messages 常一起被查詢。
Sharding(資料分片):
把 Dataset 水平切開,並分散到多個 Database Servers。
簡單記:
Replication
→ Copy Data
Sharding
→ Split Data
如果一個超熱門 Group 每秒有大量 Messages,而且全部落在同一 Partition:
Hot Partition(熱分區):
某個 Partition 承受遠高於其他 Partitions 的 Traffic / Load。
這是一種 Hotspot(熱點):
Work 過度集中在某個 Component / Data Range。
Chat System 也可能使用:
Message Queue(訊息佇列)
Message → 訊息
Queue → 排隊隊伍 / 佇列
用途可能包括:
Decoupling
Traffic Buffering
Asynchronous Delivery
Retry
Fan-out
但不要因為是大型 System 就無腦加入 Queue。
先問:
Queue 解決什麼 Problem?
Bob Offline:
No WebSocket
Chat System 可以:
Persist Message
↓
Notification System
↓
Push Notification
↓
Bob Phone
例如:
Alvin sent you a message.
APNs = Apple Push Notification service
Apple → Apple
Push Notification → 推播通知
service → 服務
中文:
Apple 推播通知服務
用來把 Push Notification 傳到 Apple Devices。
FCM = Firebase Cloud Messaging
Firebase → Google 的 App Development Platform 名稱
Cloud → 雲端
Messaging → 訊息傳遞
中文可理解為:
Firebase 雲端訊息服務
常用於 Mobile Push Messaging。
Authentication(身分驗證):
確認「你是誰」。
例如:
Login
↓
Access Token
↓
Open WebSocket
↓
Server verifies identity
Authorization(授權):
確認「你有沒有權限做這件事情」。
Authentication:
你是不是 Alvin?
Authorization:
Alvin 能不能讀 Conversation C123?
即使 Alvin 已經 Login,也不能讀自己沒有加入的 Private Group。
Messages 在 Network 中傳輸時需要保護。
WSS = WebSocket Secure
WebSocket → WebSocket 通訊
Secure → 安全的
中文可以理解成:
安全的 WebSocket Connection
通常代表:
WebSocket over TLS
TLS = Transport Layer Security
Transport Layer → 傳輸層
Security → 安全
中文:
傳輸層安全協定
TLS 主要協助提供:
Encryption
Integrity
Server Authentication
Transport Layer(傳輸層):
Network Communication 中,負責 Application 之間 End-to-End Data
Transport 的 Layer。
常見 Protocol:
TCP
UDP
今天不需要背完整 OSI Model。
先知道:
Application Data
↓
Network Layers
↓
另一台 Machine
而 TLS 用來保護傳輸中的 Communication。
Chat App 常看到:
E2EE = End-to-End Encryption
End-to-End → 從通訊的一端到另一端
Encryption → 加密
中文:
端到端加密
核心概念:
Message 在 Sender 端加密,只有預期的 Recipient Endpoint 能解密;中間
Server 不應取得可直接閱讀的 Message Plaintext。
Alvin
↓
Encrypt
↓
Ciphertext
↓
Server
↓
Ciphertext
↓
Bob
↓
Decrypt
Plaintext(明文):
尚未被 Encryption 保護、可以直接閱讀的原始內容。
Hello Bob
Ciphertext(密文):
Encryption 後產生、沒有正確 Key 時不應直接可讀的 Data。
Plaintext
↓
Encryption
↓
Ciphertext
主要保護:
Client ↔ Server
之間的 Network Transport。
目標:
Sender
↓
Encrypted
↓
Server
↓
Encrypted
↓
Recipient
Server 不應直接閱讀 Message Content。
因此:
TLS ≠ E2EE
E2EE 還涉及 Key Management、Multi-Device、New Device、Group Membership
等更複雜問題,今天先理解目的即可。
Reliability(可靠性):
即使部分 Components Failure,System 仍能盡可能正確提供服務並恢復。
Connection Server Crash:
Client disconnects
↓
Reconnect
↓
Another Server
↓
Sync missing messages
Failover(故障切換):
原本 Component Failure 時,切換到其他可用 Component。
Server A ❌
↓
Reconnect
↓
Server B ✅
Retry(重試):
Operation 失敗後,再嘗試一次。
但 Retry Message 可能造成 Duplicate,所以要搭配:
Client Message ID
Idempotency
Deduplication
如果 10M Clients 同時斷線,不能不停立即 Reconnect。
Exponential Backoff(指數退避):
每次失敗後逐漸增加 Retry 等待時間。
1 sec
2 sec
4 sec
8 sec
Jitter(隨機抖動 / 隨機延遲):
在 Retry Delay 中加入 Randomness。
Client A → 3.8 sec
Client B → 4.2 sec
Client C → 4.7 sec
避免全部 Clients 同時重連。
Thundering Herd(驚群效應):
大量 Clients / Workers 同時對同一 Resource 發 Request,瞬間造成巨大
Load。
例如:
Chat Server outage
↓
10M clients disconnect
↓
Server recovers
↓
10M clients reconnect together
所以常搭配:
Exponential Backoff
+
Jitter
Observability(可觀測性):
透過 Metrics、Logs、Traces 等 Signals 理解 System 內部發生什麼。
Chat 可以監控:
Active Connections
Connection Success Rate
Reconnect Rate
Messages/sec
Delivery Latency
Failure Rate
Queue Backlog
Database Latency
p95 / p99 Latency
RPS = Requests Per Second
Requests → 請求
Per Second → 每秒
中文:
每秒 Request 數量
但 Chat 不能只看 RPS。
還需要:
Concurrent Connections
Messages/sec
DAU = Daily Active Users
Daily → 每日
Active → 活躍
Users → 使用者
中文:
每日活躍使用者
假設:
50M DAU
40 messages/user/day
每天:
50M × 40
= 2B Messages/day
一天約 100K seconds:
2B / 100K
≈ 20K Messages/sec average
如果 Peak 是 5 倍:
≈ 100K Messages/sec
假設 Peak:
10M Users Online
平均:
1.5 active device connections/user
那麼:
10M × 1.5
= 15M Concurrent Connections
這告訴我們 Connection Layer 必須 Horizontal Scale。
假設:
2B Messages/day
500 Bytes/message
Raw Data:
≈ 1 TB/day
一年:
≈ 365 TB
還沒有算:
Indexes
Replication
Metadata
Attachments
Backups
Metadata(中繼資料 / 描述資料的資料):
不是 Message Content 本身,而是描述 Message 的資訊。
例如:
message_id
sender_id
conversation_id
created_at
sequence_number
status
Attachment(附件):
附加在 Message 裡的 File。
例如:
Image
Video
PDF
Audio
大型 File 通常不直接放進普通 Message Database Row,而可以放進:
Object Storage
Object Storage(物件儲存):
適合保存 Images、Videos、Documents 等大型 Files / Objects 的 Storage
System。
Message Database
→ Metadata + file reference
Object Storage
→ Actual image/video
CDN = Content Delivery Network
Content → 內容
Delivery → 傳遞
Network → 網路
中文:
內容傳遞網路
用途:
把 Content 放到靠近 User 的 Edge,降低 Network Distance 與 Origin
Load。
Chat Images / Videos 可以:
Object Storage
↓
CDN
↓
User
┌──────────────────────┐
│ HTTP APIs │
│ Login / History etc. │
└──────────┬───────────┘
│
↓
Alvin Client API Services
│
│ WSS
↓
Connection Server A
│
↓
Message Service
│
├────────→ Message Storage
│
├────────→ Message Queue
│
↓
Message Router
│
├────────→ Connection Registry
│
↓
Connection Server B
│
│ WSS
↓
Bob Client
If Bob Offline:
Message Service
↓
Message Storage
↓
Notification System
↓
APNs / FCM
↓
Bob Device
Supporting Services:
Presence Service
Synchronization Service
Group / Membership Service
Observability
Alvin 傳:
Hello Bob
可以經過:
1. Client generates client_message_id
2. Send through WebSocket
3. Authenticate connection
4. Validate request
5. Authorize conversation access
6. Deduplicate client_message_id
7. Generate server message_id
8. Assign sequence_number
9. Persist Message
10. ACK Sender
11. Find Bob's connections
12. Route Message
13. Bob receives Message
14. Bob sends Delivery ACK
15. Update DELIVERED
16. Bob reads Message
17. Send Read Receipt
18. Update READ
19. Sync status to Alvin's other devices
Alvin
↓
Message
↓
Persist
↓
Bob has no active connection
↓
Store as undelivered
↓
Notification System
↓
Push Notification
Bob 回來:
Reconnect
↓
Authenticate
↓
Send last received sequence
↓
Server finds missing messages
↓
Sync
Alvin
↓
Connection Server
↓
Message Service
↓
Persist one logical message
↓
Group Membership
↓
Find recipients
↓
Fan-out
↓
Route to online members
↓
Store / Sync for offline members
Large Group 要注意:
Fan-out Cost
Write Amplification
Hot Partition
Queue Backlog
Connection Capacity
Problem:
Chat needs low-latency bidirectional communication
Solution:
Persistent bidirectional connection
Problem:
Bob may be connected to any server
Solution:
Track User / Device → Server mapping
Problem:
Offline users and history require persistence
Solution:
Persist messages
Problem:
Distributed delivery may arrive out of order
Solution:
Per-conversation ordering
Problem:
Sender does not know whether receiver got data
Solution:
Acknowledgement
Problem:
Retry may create duplicate messages
Solution:
Identify same logical message
Problem:
Connection may die silently
Solution:
Periodic liveness signal
Problem:
Network interruption can cause missing messages
Solution:
Reconnect and recover missing data
Problem:
One group message has many recipients
Solution:
Expand one logical message into delivery work
不要只說:
Because WebSocket is real-time.
可以回答:
Chat requires low-latency bidirectional communication. Polling
requires the client to repeatedly ask the server for new messages,
which creates unnecessary requests. WebSocket maintains a persistent
connection so both client and server can send data through the same
connection, making it suitable for real-time message delivery.
1. Persist Message
2. Detect Bob has no active connection
3. Keep Message as undelivered
4. Optionally trigger Push Notification
5. Bob reconnects
6. Client reports last received sequence
7. Server synchronizes missing Messages
8. Update Delivery Status
Client generates client_message_id
↓
Send
↓
Server stores ID
↓
Network failure
↓
Client retries same ID
↓
Server detects duplicate
↓
Return existing result
核心:
Idempotency
+
Deduplication
不要只回答:
Use Timestamp
先問:
Global Ordering?
Per-Conversation Ordering?
Chat 通常更需要:
Per-Conversation Ordering
可以考慮:
conversation_id
+
sequence_number
Timestamp 可以當 Metadata,但不同 Machines 可能有 Clock Skew。
可以結合:
WebSocket Connection
+
Connection Registry
+
Heartbeat
+
Presence Service
但 Presence 不一定瞬間完美準確。
例如:
Bob suddenly loses network
Server 可能等 Heartbeat Timeout 後才知道。
Connection Server A crashes
↓
WebSocket disconnects
↓
Clients detect failure
↓
Exponential Backoff + Jitter
↓
Reconnect to Server B
↓
Update Connection Registry
↓
Sync missing messages
不能假設:
user_id → one connection
而要考慮:
user_id
├── device A
├── device B
└── device C
Message 可能要送給 Recipient 的多個 Active Devices,也要同步到 Sender
自己的其他 Devices。
不要背:
Chat = NoSQL
先分析:
Access Pattern
Data Volume
Write Throughput
Ordering Requirement
Consistency Requirement
Query Pattern
Operational Complexity
例如常見 Query:
Give me latest 50 messages
for conversation C123
before sequence 1000
再根據 Requirement 選擇 Storage。
□ One-to-One Chat
□ Group Chat
□ Conversation
□ Message ID
□ Real-Time Communication
□ Latency
□ HTTP
□ Polling
□ Long Polling
□ WebSocket
□ Persistent Connection
□ Bidirectional Communication
□ Full-Duplex
□ Connection Server
□ Concurrent Connections
□ Horizontal Scaling
□ Connection Mapping
□ Connection Registry
□ Routing
□ Presence
□ Heartbeat
□ Ping / Pong
□ Offline Message
□ Persistent Storage
□ Message History
□ Pagination
□ Cursor
□ Message Ordering
□ Timestamp
□ Clock Skew
□ Sequence Number
□ Per-Conversation Ordering
□ Sending / Sent / Delivered / Read
□ ACK
□ Delivery ACK
□ Read Receipt
□ Client Message ID
□ Idempotency
□ Deduplication
□ Reconnect
□ Synchronization
□ Multi-Device
□ Device ID
□ Fan-out
□ Fan-out on Write
□ Fan-out on Read
□ Write Amplification
□ Partitioning
□ Partition Key
□ Sharding
□ Hot Partition
□ Message Queue
□ APNs
□ FCM
□ Authentication
□ Authorization
□ WSS
□ TLS
□ Transport Layer
□ E2EE
□ Plaintext
□ Ciphertext
□ Reliability
□ Failover
□ Retry
□ Exponential Backoff
□ Jitter
□ Thundering Herd
□ Observability
□ RPS
□ DAU
□ Metadata
□ Attachment
□ Object Storage
□ CDN
ID
= Identifier
= 識別碼
HTTP
= Hypertext Transfer Protocol
= 超文字傳輸協定
ACK
= Acknowledgement
= 確認 / 確認收到
WSS
= WebSocket Secure
= 安全的 WebSocket Connection
TLS
= Transport Layer Security
= 傳輸層安全協定
E2EE
= End-to-End Encryption
= 端到端加密
RPS
= Requests Per Second
= 每秒 Request 數量
DAU
= Daily Active Users
= 每日活躍使用者
APNs
= Apple Push Notification service
= Apple 推播通知服務
FCM
= Firebase Cloud Messaging
= Firebase 雲端訊息服務
CDN
= Content Delivery Network
= 內容傳遞網路
Chat System 看起來只是:
Alvin
↓
Hello
↓
Bob
真正設計時卻需要處理:
Real-Time Communication
WebSocket
Persistent Connections
Connection Routing
Presence
Heartbeat
Offline Messages
Message Storage
Ordering
Sequence Number
ACK
Delivered / Read Receipt
Idempotency
Deduplication
Reconnect
Synchronization
Multi-Device
Group Fan-out
Partitioning
Reliability
Security
Observability
每個 Component 都應該從 Problem 推導:
Polling 太浪費
↓
WebSocket
User 可能連不同 Server
↓
Connection Registry + Routing
User 可能 Offline
↓
Persistent Message Storage
Connection 可能靜默死亡
↓
Heartbeat
Network 可能中斷
↓
Reconnect + Sync
Retry 可能重複
↓
Client Message ID + Idempotency
Messages 可能亂序
↓
Per-Conversation Sequence Number
Group 有很多 Members
↓
Fan-out
Server 可能 Failure
↓
Reconnect + Failover
User 有多台 Devices
↓
Multi-Device Synchronization
核心仍然是:
Requirement
↓
Problem
↓
Bottleneck / Failure
↓
Solution
↓
Trade-off
好的 Chat System,不只是把 Message 從 Alvin 傳給 Bob,而是要在
Network Failure、Millions of Connections、Offline Users、Multiple
Devices、Group Fan-out 與 Out-of-Order Delivery 的情況下,仍然讓 User
感覺訊息快速、可靠,而且順序合理。
Day 23|Design YouTube:Video
Upload、Storage、Transcoding、Streaming 與 CDN 到底怎麼設計?
會從最基礎解釋:
Video File
Upload
Object Storage
Metadata
Codec
Encoding
Decoding
Compression
Bitrate
Resolution
Container Format
Transcoding
Streaming
Buffer
Buffering
Chunk
Segment
Adaptive Bitrate Streaming
CDN
Origin
Edge Server
Cache
Upload Pipeline
Processing Pipeline
Thumbnail
Asynchronous Processing
Message Queue
Replication
Availability
Bandwidth
Egress
遇到縮寫,例如:
CDN
HLS
DASH
VOD
也會先按照:
完整英文
↓
每個字的意思
↓
中文意思
↓
為什麼需要
↓
簡單例子
↓
System Design 用法
再進入 Architecture。