複製(replication)
如果你把唯一一本相簿放在一個地方,而房子燒了,那些照片就永遠沒了。所以你做副本、存在不同的地方。複製就是把這個點子套用到分散式系統裡的資料與服務上:在不同的機器上保有同一份資料的好幾份副本(replica),這樣即使一台機器失效,其他機器仍握有資訊、系統繼續運作。它是容錯的主要工具——撐過一個節點的失去——而且它也能加速,因為可以讓許多機器同時服務讀取。
麻煩在於:當資料變動時,要讓這些副本保持同步。大致有兩種策略。同步複製是指:一個寫入要等到每一個(或多數)副本都儲存了它,才向使用者確認:副本維持緊密一致,但這個寫入會和最慢的那個副本一樣慢,而且若某些副本連不上、寫入可能卡住。非同步複製是指:寫入只要一個副本拿到就確認,其他副本稍後再更新:寫入很快、也維持可用,但有一小段時間副本之間不一致,而且若主副本在把變更傳出去之前就當掉,那個變更可能遺失。常見的折衷路線,是主備(primary-backup,一個副本領頭、其餘跟隨)相對於法定人數(quorum,一個寫入必須抵達一個多數,就像共識那樣)的方案。
為什麼重要,以及誠實的張力:複製是幾乎每個正經系統撐過硬體失效、並服務全球觀眾的方式。但它直接和 CAP 定理、以及共識相撞。你保有的副本越多、你越是堅持它們要緊密一致,每次更新就要花越多協調(與延遲),而你也越容易受一個「使你無法抵達足夠副本」的分裂所傷。所以複製從來不是免費的安全——它是在「持久度、效能、以及你願意容忍多少暫時的不一致」之間,一個刻意的取捨。
一個訊息服務把每則訊息存在三台機器上。如果其中一台機器的磁碟壞了,這則訊息仍存在於另外兩台上、使用者毫無察覺——這就是透過複製達成的容錯。設計問題在於:「已送出」的勾勾,是在一個副本拿到訊息的瞬間就出現(快、非同步),還是要等三台都確認後才出現(持久、同步)。
保有好幾份副本,好讓系統撐過失效。讓它們保持一致,就是代價所在。
複製買到的是持久度與可用性,而非免費的一致性:同步副本慢但一致,非同步副本快但可能短暫分歧、或遺失一筆最近的寫入。選哪一種是一個明確的決定,而非預設。