在深入一致性模型之前,先釐清為什麼要複製資料,並聚焦在「複製作為可擴展性技術」這個角度,說明為什麼認真思考一致性如此重要。
複製的兩大理由#
複製資料有兩個主要原因:可靠性(reliability)與效能(performance)。
- 可靠性:
- 檔案系統若有複製,即使一個副本當機,只要切換到其他副本就能繼續工作。
- 維持多份拷貝也能防範資料毀損。例如一個檔案有三份拷貝,每次讀寫都在三份上進行,只要把「至少兩份拷貝回傳的相同值」當作正確值,就能容忍單一次失敗的寫入。
- 效能:當系統需要在數量與地理範圍兩個維度上擴展時,複製就變得重要。
- 數量擴展:越來越多行程需要存取由單一伺服器管理的資料時,可以複製伺服器並分攤工作量。
- 地理擴展:把資料拷貝放在使用它的行程附近,可縮短存取時間,提升該行程感受到的效能。
複製對效能的好處未必容易評估:客戶端行程也許感覺變快了,但維持所有副本最新可能耗掉更多網路頻寬。
複製的代價:一致性問題#
複製既能提升可靠性又能改善效能,代價是什麼?問題在於:擁有多份拷貝會導致一致性問題。任何一份拷貝被修改後,就與其他拷貝不同了;為了維持一致,修改必須施加到所有拷貝上——何時以及如何進行這些修改,決定了複製的代價。
以改善 Web 網頁存取時間為例:
- 若不採取任何措施,從遠端 Web 伺服器抓取一個頁面可能要花上數秒。瀏覽器因此常把抓過的頁面存在本地(快取),下次直接回傳本地拷貝,使用者感受到的存取時間極佳。
- 但若使用者總是想要最新版本,就可能倒楣:頁面在此期間被修改的話,修改並不會傳播到快取拷貝,快取就過期(out-of-date)了。
延伸討論:兩種解法及其缺點
- 禁止瀏覽器保留本地拷貝,讓伺服器完全掌控複製——但若沒有副本放在使用者附近,存取時間仍然很差。
- 由 Web 伺服器主動作廢(invalidate)或更新每一份快取拷貝——但這要求伺服器追蹤所有快取並發送訊息,反而可能拖垮伺服器整體效能。
複製作為可擴展性技術#
複製與快取是被廣泛採用的擴展技術:可擴展性問題通常以效能問題的形式浮現,把資料拷貝放在使用者附近可以縮短存取時間、化解效能瓶頸。但有兩層代價要權衡。
代價一:更新流量可能白費#
保持拷貝最新需要更多網路頻寬。考慮行程 P 每秒存取本地副本 N 次,而副本本身每秒被更新 M 次,且假設每次更新都完全刷新舊版本:
- 若 N « M(存取更新比極低),許多更新後的版本根本沒被 P 讀過就又被覆蓋,這些版本的網路傳輸完全是浪費。
- 這種情況下,也許不該在 P 附近放本地副本,或應改用其他更新策略。
代價二:維持一致本身不可擴展#
更嚴重的問題是:讓多份拷貝保持一致這件事本身,就可能有嚴重的可擴展性問題。
直觀上,一組拷貝一致,是指它們永遠相同:在任何拷貝上讀都回傳相同結果。因此在某份拷貝上執行更新後,必須先把更新傳播到所有拷貝,之後才允許下一個操作——不論那個操作發起或執行於哪份拷貝。這種一致性有時被(不精確地)稱為緊密一致性(tight consistency),由所謂**同步複製(synchronous replication)**提供,關鍵想法是更新以單一不可分割操作(atomic operation)或交易(transaction)的形式施加到所有拷貝。
問題在於:當副本數量龐大且分散在大範圍網路上,又要求操作快速完成時,實作原子性本質上就很困難:
- 所有副本必須先同步、對「更新何時在本地執行」達成共識,例如用 Lamport 時間戳決定操作的全域排序,或由協調者(coordinator)指派順序。
- 全域同步耗費大量通訊時間,副本散布於廣域網路時尤甚。
這是一個兩難:複製與快取能改善效能、緩解可擴展性問題;但維持所有拷貝一致通常需要全域同步,而全域同步本身在效能上代價高昂——解藥可能比疾病更糟。
許多情況下,唯一的真正解法是放鬆一致性限制:若能免除「更新必須是原子操作」的要求,就能避開(即時的)全域同步而換得效能。代價是各處的拷貝不一定永遠相同。至於一致性能放鬆到什麼程度,高度取決於被複製資料的存取與更新模式,以及資料的用途。
後續章節將先精確定義各種一致性模型,再討論以散布協定(distribution protocol)與一致性協定實作這些模型的方式。關於一致性與複製的其他分類方式,可參考 Gray 等人(1996)與 Wiesmann 等人(2000)的文獻。