前面我們學過 Database Replication:
┌→ Replica #1
Primary Database├→ Replica #2
└→ Replica #3
它可以分散 Read Traffic,但也帶來一個重要問題:
如果 Primary 已更新,但 Replica 還沒更新,User
會看到新資料還是舊資料?
例如 User 把名字:
Alvin → Wei-Hong
Primary 已經是 Wei-Hong,但 Replica 暫時還是 Alvin。User 更新後立即
Refresh,如果 Read 被送到 Replica,就可能再次看到 Alvin。
今天要學的核心就是:
Consistency
State 可以理解成:
System 在某一個時間點,目前記住的資料。
例如:
name = "Alvin"
就是一個 State。
修改成:
name = "Wei-Hong"
State 就改變了。
Shopping Cart:
Cart:
- iPhone x 1
- AirPods x 1
也是 State。
所以 State 不需要想得很抽象,它就是:
System 現在保存的資料長什麼樣子。
Write 是改變資料:
Create
Update
Delete
例如:
UPDATE users
SET name = 'Wei-Hong'
WHERE id = 123;
Read 是取得資料:
SELECT name
FROM users
WHERE id = 123;
今天很多 Consistency 問題都可以簡化成:
Write 發生
↓
下一次 Read
↓
到底看到什麼?
Consistency 中文是「一致性」。
在 Distributed System 裡,可以先用這個問題理解:
資料被更新後,不同 Server / Database Copy
看到的資料,什麼時候會一致?
例如:
Primary → Wei-Hong
Replica 1 → Wei-Hong
Replica 2 → Alvin
這時不同 Copy 的 State 不完全相同。
我們就需要問:
這種不同可以存在多久?
User 可以看到舊資料嗎?
哪些操作一定要看到最新資料?
Distributed System:
一個 System 的工作由多台 Computer / Server 一起完成。
例如:
Backend #1
Backend #2
Redis
Primary DB
Replica #1
Replica #2
Message Queue
這些 Component 可能在不同 Machine,甚至不同 Data Center。
資料必須透過 Network 傳送,所以:
更新很難永遠在所有 Machine 上完全同一瞬間完成。
這就是 Consistency 變重要的原因。
Replica 是原本資料的一份 Copy。
Replication 是把資料的變化從一個 Database 複製到另一個 Database:
Write
↓
Primary
↓
Copy Change
↓
Replica
Replication 可以幫助 Read Scaling、Availability、Failover,但也會產生
Replication Lag。
Lag 就是「落後」。
Replication Lag = Replica 的資料更新進度落後 Primary 一段時間。
例如:
10:00:00.000
Primary: Alvin → Wei-Hong
10:00:00.100
Replica: Alvin
10:00:00.300
Replica: Wei-Hong
在中間那段時間:
Primary ≠ Replica
因為資料需要經過:
Primary processes Write
↓
Change travels through Network
↓
Replica receives Change
↓
Replica applies Change
Network Busy、Replica Busy、大量 Writes 等都可能讓 Lag 增加。
Stale 原本有「不新鮮、過期」的意思。
所以:
Stale Data = 已經不是最新版本的資料。
例如最新資料:
Wei-Hong
但某個 Replica 還是:
Alvin
那 Alvin 就是 Stale Data。
Stale Read:
Read 到已經不是最新版本的資料。
Write:
Alvin → Wei-Hong
Primary:
Wei-Hong
Replica:
Alvin
GET /profile
↓
Replica
↓
Alvin
這就是 Stale Read。
所以:
Replication
↓
Replication Lag
↓
Stale Data
↓
Possible Stale Read
Strong Consistency 可以先理解成:
Write 成功後,後續 Read 應該看到最新資料。
例如:
Alvin
↓ Update
Wei-Hong
↓ Success
Read #1 → Wei-Hong
Read #2 → Wei-Hong
User 的直覺就是:
「既然 System 告訴我修改成功,我下一次讀取就應該看到修改後的資料。」
Bank Balance:
Balance = $1,000
轉出:
$500
成功後:
Balance = $500
你通常不希望下一次看到:
$1,000
再過一下才變 $500。
Financial Operation 通常需要更嚴格地思考 Consistency。
有。
為了確保資料符合較強的 Consistency Requirement,多台 Server
之間可能需要更多:
Coordination
Coordination 可以理解成:
多個 Server 互相確認、配合,才能決定下一步。
像:
Server A: 更新好了嗎?
Server B: 好了。
Server C: 我也好了。
Server A: 那可以繼續。
更多 Coordination 通常代表更多 Network Communication,也可能增加
Latency。
Latency 就是:
一個操作從開始到得到結果,需要等待多久。
所以 Stronger Consistency 並不是免費的。
Eventual 就是「最終會」。
所以 Eventual Consistency:
資料不保證每一瞬間都完全一致,但如果沒有新的
Update,經過一段時間後,各個 Copy 最終會一致。
例如:
Time 1:
Primary → Wei-Hong
Replica 1 → Alvin
Replica 2 → Alvin
過一下:
Time 2:
Primary → Wei-Hong
Replica 1 → Wei-Hong
Replica 2 → Alvin
最後:
Time 3:
Primary → Wei-Hong
Replica 1 → Wei-Hong
Replica 2 → Wei-Hong
Social Media Like Count:
1,000 Likes
你按 Like:
1,001
另一個地方的 User 短時間可能還看到:
1,000
幾秒後才變:
1,001
通常 Business Impact 不大,所以這種資料可能可以接受 Eventual
Consistency。
注意:
Eventual Consistency 不代表資料永遠錯。
它是短時間可以不同,但最後會 Converge。
Converge 中文可以理解成「收斂」。
原本不同的 State,最後慢慢變成相同。
例如:
A = 10
B = 8
C = 7
同步後:
A = 10
B = 10
C = 10
這就是 States Converge。
Strong Consistency Eventual Consistency
Write 後 Read 希望看到最新資料 短時間可能看到舊資料
Stale Read 盡量避免 可能發生
Coordination 通常較多 通常可以較少
Latency 可能較高 可能較低
常見考量 Critical Data 可接受短暫延遲的 Data
不要死背「Bank = Strong、Social Media = Eventual」。
真正應該問:
這個 Feature 對資料新鮮度的 Requirement 是什麼?
Data Freshness:
資料有多新、離最新 State 有多近。
例如 Stock Price 如果顯示 10 分鐘前的價格,可能太舊。
但 YouTube View Count 晚兩秒更新,可能可以接受。
所以不同 Data 有不同 Freshness Requirement。
Consistency Requirement 就是在問:
這份資料需要多快一致?可以接受看到多舊的資料?
例如:
Bank Balance
→ Requirement 比較嚴格
Like Count
→ 可能可以接受幾秒 Delay
System Design 不應該先選 Strong 或 Eventual,而應該先問 Business
能接受什麼。
拆開:
Write
↓
After
↓
Read
Read-After-Write Consistency:
User 自己剛 Write 成功的資料,接下來自己 Read 時應該可以看到。
例如:
Alvin → Wei-Hong
↓
Update Success
↓
Refresh
↓
Wei-Hong
而不是又看到 Alvin。
這對 User Experience 很重要。
一個簡單概念:
Write → Primary
Write 後,這個 User 短時間的 Read:
Read → Primary
而不是 Replica。
因為 Primary 已經有最新資料。
等 Replica Catch Up 後,再讓 Read 回到 Replica。
Catch Up 就是「追上」。
例如:
Primary Version = 105
Replica Version = 100
後來:
Replica Version = 105
就代表 Replica 已經追上。
Session 可以先理解成:
System 用來記住某個 User 在一段使用期間中的相關狀態。
例如 Login 後:
User ID = 123
Logged In = true
System 可能知道 User 123 剛完成 Write。
Session-based Routing:
根據 User Session 狀態,決定 Request 要去哪個 Server / Database。
例如:
User 123 recently wrote data
→ Read from Primary
Other users
→ Read from Replica
這樣不需要讓所有 Read 永遠都打 Primary。
Monotonic Read 這個名字很難,但概念很簡單:
User 已經看到比較新的資料後,之後不應該又退回看到更舊的資料。
例如:
Read #1 → Version 10
Read #2 → Version 8 ❌
比較合理:
Read #1 → Version 10
Read #2 → Version 10
或 Version 11
一句話:
不要往回看。
Version 可以理解成資料更新到第幾個版本。
Version 1 → Alvin
Version 2 → Wei-Hong
Version 3 → Wei-Hong Lin
如果 User 已看到 Version 3,下一次卻看到 Version 1,就像資料倒退。
假設:
Replica #1 → Version 10
Replica #2 → Version 8
第一次:
User → Replica #1 → Version 10
第二次:
User → Replica #2 → Version 8
User 就看到更舊的資料。
Read-After-Write、Monotonic Read 都可以叫:
Consistency Guarantee
Guarantee 就是「保證」。
System 承諾至少做到某件事:
Read-After-Write
→ 你自己剛寫的資料,自己接下來看得到
Monotonic Read
→ 看過新資料後,不會又退回更舊版本
所以 Consistency 不一定只有 Strong vs Eventual 兩個極端。
Consistency Model:
System 定義 Read 和 Write 之間應遵守哪些規則。
例如:
Write 完後 Read 必須看到最新?
允許短時間 Stale Read?
至少保證 User 看得到自己的 Write?
這些規則描述了 System 的 Consistency Model。
今天不用背所有 Model。
重點是:
Consistency 可以有不同強度的 Guarantee。
Social Media Like Count:
1000 vs 1001
短時間不同,通常 Business Impact 有限,可能接受 Eventual Consistency。
User Profile:
其他 User 晚幾秒看到新名字
→ 可能可以接受
修改者自己 Refresh 還看到舊名字
→ User Experience 很差
所以可以考慮:
Others → Eventual acceptable
Writer → Read-After-Write
Shopping Cart:
Add iPhone
↓
Refresh
↓
Cart Empty
會讓 User 很困惑,因此 User 自己的 Cart View 通常需要更一致。
Bank Balance 涉及扣款、轉帳等 Operation 時,通常需要更嚴格的 Transaction
/ Concurrency / Consistency Control。
Inventory 也類似。
假設只剩:
1 iPhone
兩個 User 同時看到:
stock = 1
兩邊都成功買到:
Sold = 2
Stock = 1
這叫 Overselling:
賣出去的數量超過實際可用庫存。
因此 Checkout 最終扣庫存不能隨便依賴可能 Stale 的 Cache /
Replica,可能需要 Primary、Atomic Update、Transaction、Locking
等更嚴格機制。
Source of Truth:
當不同地方的資料不一樣時,哪一份才是正式、可信任的資料。
例如:
Redis Cache → stock = 2
Primary DB → stock = 1
如果 Primary DB 是 Source of Truth:
stock = 1
才是正式判斷依據。
Cache 只是暫時 Copy。
假設 Primary 和 Replica 之間 Network 出問題。
Replica 不確定自己是不是最新。
System 可以:
A. 繼續從 Replica 回應
→ Availability 較高
→ 但可能 Stale Read
或者:
B. 暫時拒絕某些 Read
→ 避免不確定的舊資料
→ 但 User 可能拿不到 Response
Availability:
System 在 User 需要時,能不能正常提供 Service / Response。
這就開始碰到 Consistency vs Availability 的 Trade-off。
這裡的 Network Partition 不是 Day 9 的 Database Partitioning。
它指:
Distributed System 中,一部分 Server 暫時無法和另一部分 Server
正常通訊。
Server A ✅
|
X Network Problem
|
Server B ✅
A 還活著,B 也活著,但彼此不能正常溝通。
Replica 這時不知道 Primary 最近有沒有新
Write,所以自己的資料可能最新,也可能已經舊。
System 就必須決定:
繼續提供 Response?
還是暫停部分操作?
你可能看過:
CAP Theorem
它和 Consistency、Availability、Network Partition 有關。
今天先不要直接死背 C、A、P。
先建立這條思路:
資料可能不同步
↓
Network 也可能失敗
↓
System 必須做 Trade-off
下一篇再正式拆 CAP Theorem。
Day 5 的 ACID 也有:
C = Consistency
但它和今天的 Consistency 不是完全相同的概念。
ACID Consistency 比較關心:
Transaction 前後,Database 是否維持定義好的 Rules / Constraints。
今天的 Distributed System Consistency 比較關心:
多個 Copy / Node 在 Read 和 Write
時看到的資料是否符合我們定義的規則。
所以看到 Consistency,一定要看 Context。
Node:
Distributed System 裡參與工作的其中一台 Machine / Server /
Instance。
例如:
Database Node #1
Database Node #2
Database Node #3
每一台都可以叫 Node。
Consistency 不等於資料本身一定正確。
例如:
Primary → age = 500
Replica 1 → age = 500
Replica 2 → age = 500
三份資料完全一致,但 age = 500 可能本身就是錯的。
所以:
Consistency
→ 不同地方的 State 是否符合 Consistency Rule
Accuracy
→ 資料本身是否正確
可能原因:
Write
↓
Primary
↓
Replication Lag
↓
Read from Replica
↓
Stale Read
Requirement:
User 自己剛更新的資料
最好立刻可以看到
所以可以考慮:
Read-After-Write Consistency
例如 Recent Writer 暫時 Read Primary,Replica Catch Up 後再 Read
Replica。
不要只回答:
Use Eventual Consistency.
先分析:
1000 vs 1001
短時間不同的 Business Impact 通常有限。
所以可以接受短暫 Stale Data,考慮 Eventual Consistency,以降低
Coordination,並改善 Scalability / Latency。
但仍然要根據 Requirement 決定。
不要只背:
Bank → Strong
要先問是哪一種 Operation。
顯示某些非關鍵 Summary,和真正決定 Transfer 能不能成功,Requirement
不同。
涉及:
扣款
轉帳
防止重複消費
時,需要更嚴格的 Transaction、Concurrency 與 Consistency Control。
Product Page 顯示:
「大約還有庫存」
和 Checkout 真正扣庫存是不同 Operation。
可以:
Product Page
→ Cache / Replica may be acceptable
Checkout
→ Reliable Source of Truth
→ Atomic Update / Transaction / Locking
所以:
同一份 Data,在不同 Operation 裡可能有不同 Consistency
Requirement。
不要直接回答 Strong 或 Eventual。
先問:
1. 這是什麼 Data?
2. 這是哪一個 Operation?
3. User 可以接受 Stale Data 嗎?
4. 可以接受多久?
5. 看到舊資料的 Business Impact 是什麼?
6. 需要 Read-After-Write 嗎?
7. 是否涉及 Money / Inventory / Security?
8. Stronger Consistency 的 Latency / Availability Cost 可以接受嗎?
最後才決定適合的 Consistency Guarantee。
Replication
↓
Multiple Copies
↓
Copies update at different times
↓
Replication Lag
↓
Stale Data
↓
Possible Stale Read
↓
Need Consistency Requirement
接著:
Strong Consistency
→ 更強調看到最新 State
Eventual Consistency
→ 短時間允許不同
→ 最終 Converge
還可以有:
Read-After-Write
Monotonic Read
這些更具體的 Guarantee。
1. State 是什麼?
2. Read vs Write?
3. Consistency 是什麼?
4. Distributed System 是什麼?
5. Replica / Replication 是什麼?
6. Replication Lag 是什麼?
7. Stale Data / Stale Read 是什麼?
8. Strong Consistency 是什麼?
9. Strong Consistency 有什麼 Cost?
10. Coordination / Latency 是什麼?
11. Eventual Consistency 是什麼?
12. Converge 是什麼?
13. Strong vs Eventual Consistency?
14. Data Freshness 是什麼?
15. Consistency Requirement 是什麼?
16. Read-After-Write 是什麼?
17. Catch Up 是什麼?
18. Session / Session-based Routing 是什麼?
19. Monotonic Read 是什麼?
20. Version 是什麼?
21. Consistency Guarantee / Model 是什麼?
22. Like Count 適合怎麼思考?
23. Shopping Cart 呢?
24. Bank Balance 呢?
25. Inventory 呢?
26. Overselling 是什麼?
27. Source of Truth 是什麼?
28. Consistency vs Availability?
29. Network Partition 是什麼?
30. CAP Theorem 和今天有什麼關係?
31. ACID Consistency vs Distributed Consistency?
32. Node 是什麼?
33. Consistency vs Accuracy?
34. Profile 更新後看到舊資料怎麼分析?
35. 為什麼不同 Operation 可能需要不同 Consistency Requirement?
Consistency 最核心的問題:
當同一份 Data 存在多個 Copy 時,Write 發生之後,各個 Read
應該在什麼時候看到新的 State?
重要名詞:
State
Read
Write
Replication
Replication Lag
Stale Data
Stale Read
Strong Consistency
Eventual Consistency
Read-After-Write
Monotonic Read
Network Partition
Source of Truth
最重要的觀念:
Strong Consistency 不是永遠最好;Eventual Consistency 也不是代表
System 很差。
真正要問:
如果 User 看到舊資料,會發生什麼?
例如:
Like Count
→ 可以接受短暫不同
Profile Update
→ Writer 自己最好立即看到
Inventory Checkout
→ 不能隨便依賴 Stale Data
Money Transfer
→ 需要非常謹慎處理
如果:
Server A ✅
Network ❌
Server B ✅
兩台 Server 都活著,但彼此無法正常溝通。
這就是 Network Partition。
這時 System 會面臨經典問題:
我要繼續提供 Service?
還是
我要拒絕部分 Request,
避免回傳可能不一致的 Data?
下一篇:
Day 14|CAP Theorem:Consistency、Availability、Partition
到底為什麼不能全部都要?
會先從零解釋:
CAP 的 C 是什麼?
CAP 的 A 是什麼?
CAP 的 P 是什麼?
Partition 到底代表什麼?
再進入:
CP
AP
CA
並特別說明一個常見誤解:
CAP Theorem 並不是叫你平常隨便從 C、A、P 三個選兩個。