如 Day 21 Synchronous Versus Asynchronous Replication 所說過的,把 Follower 的 replica 全設為 synchronous (同步) 是不實際的;倘若將 Follower replica 設為 Asynchronous (非同步),雖然短時間內 Follower 資料可能與 Leader 不一致,但 Follower 最終會 catch up 並保持資料跟 Leader 一致,這個結果稱為 eventual consistency (最終一致性) 。
雖然理論上會 eventual consistency,但當這個 Lag (延遲) 慢慢變大時,這就從理論升級成實在的問題了,接下來會介紹 3 個 Lag 的範例,並看看要如何解這問題。
讀你所寫 (很像在駡人齁 XD);有些系統是在 user 送出後馬上就看到他送出後的內容,例如對一篇文章寫評論,在非同步 Replication 下,若沒做特別處理,user 有可能會看不到自己剛剛寫的評論,如下圖說明:
在這個情況底下,我們需要 read-after-write 一致性 (或稱為 read-your-writes 一致性);那我們如何在 leader-based replication 實做 read-your-writes 呢?
第二個 replication lag 的範例為不規則的讀取,如下圖,user 2345 在第二次讀取時向 Follower 2 讀取資料,但那台 Lag 比較久所以就沒讀取到資料,這種情形挺常發生,例如重新整理網頁,這只會讓 user 對你的系統失去信心。
Monotonic reads 能保證這種情形不會發生,第一個做法舊的資料不做變動,只讀取比較新的資料;第二個做法比較直覺,讓 user 只讀取特定的 replica 資料,不同 user 可透過 user id 或某個方式 hash 後,他就只會讀取某個 replica,但要注意的是當 Follower 掛掉時,要有機制轉移 user 到不同的 replica 上。
第三個 replication lag 的範例也是不規則的讀取,且違法因果關係,想像一下你在聊天室觀察 2 人對話,正常的順序應是這樣:
Mr. Poons:
How far into the futre can you see, Mrs. Cake? (妳能看到多久的未來?)
Mrs. Cake:
About ten seconds usually, Mr. Poons. (大約 10 秒)
然後發生了 Lag,結果你看到的對話變成了:
Mrs. Cake:
About ten seconds usually, Mr. Poons. (大約 10 秒)
Mr. Poons:
How far into the futre can you see, Mrs. Cake? (妳能看到多久的未來?)
這令人困惑的對話發生原因如下圖:
上面這個範例我們就需要另一個保證:consistent prefix reads ,這能保證任何人讀取的順序跟寫入的順序一致,這是在有 partitioned (sharded) 功能的資料庫中會發生的問題,我們在 Day 27 談到 Partition 時在細講吧!
如前面所討論,工程師們能設計這些方法在應用軟體端保證資料的正確性,可能你會想說「啊我用 single-node 且有 transactions 保證的資料庫就好啦」,但系統終究會越來越大,數據更密集,分散式資料是必不可免的,在有 scalable (可擴充性) 性質的系統下,transactions 是昂貴的操作,許多系統會捨棄這個特性,所以只能斷言 eventual consistency 會發生,然後再加上前面提到的方法來保證資料正確。
本書的第 7 章跟第 9 章會再回頭討論 Transactions 的議題,所以可能是明年的鐵人賽會分享囉XD