《設計資料密集型應用》- Designing Data-Intensive Application - 第5章 複製 讀書筆記
阿新 • • 發佈:2020-10-23
複製
領導者與追隨者
單領導者
同步複製與非同步複製
- 同步
- 非同步
- 半同步:一個副節點同步,其餘副節點非同步
設定新從庫
- 全量鏡象+增量
處理節點宕機
-
從節點
- 追趕恢復
-
主節點
-
流程
- 由剩餘從節點或控制節點進行選主流程
- 通常選舉有最新副本的從節點做為主節點
- 舊主節點上線後作為從節點
-
存在問題
- 新主庫缺失舊主庫部分寫入,如果其收到衝突的寫入(如主鍵衝突),常見方法是丟掉舊主庫未同步的寫入,但影響了寫入的永續性
- 如果丟掉的寫入與其他資料庫相關聯,則有可能會出現資料不一致的問題
- 腦裂
- 主庫判定失效超時時間設定困難,太短,容易受網路抖動延遲誤操作;太長,選主延遲加大,丟失的資料也可能越多
-
複製日誌的實現
-
基於語句的複製
-
問題
- 非確定語句執行會出現主從不一致的問題,如NOW(),RAND()
- 如果使用了自增列或依賴於庫中現有的資料,則從節佔的執行順序必須嚴格按主節點的執行順序
- 現MYSQL會將含有不確定的語句轉換為基於行的複製
-
-
基於WAL,PostgreSQL與Oracle使用該類複製
- 問題:日誌記錄過於底層,記錄了磁碟塊上哪些位元組有了更改,對主從所採用的儲存引擎、資料庫版本的一致性要求高
-
基於邏輯日誌(基於行)
- 記錄與儲存引擎相分離,因此主從可採用不同的儲存格式,資料庫也可不同
-
基於觸發器
- 由於事務需要等觸發器完成其操作才能提交,所以事務處理延遲會增加。
複製延遲問題
解決方法
-
讀己之寫
-
從業務程式碼上入手
-
對於和自身相關的資訊,都從主庫讀取,其它使用者的從從庫讀取
-
跟蹤上次更新時間,如果小於一定時間(如一分鐘),則從主庫讀
-
客戶端儲存最近一次寫入的時間戳,所讀的從庫確保最新的資料時間大於等於該時間(訪問需要系統額外判斷從庫資料的時間資訊)
- 如果同一使用者在不同終端同時登入並做了寫入操作,此時不同客戶端所儲存的時間戳不一致,也會出現所看到的資料不一致問題,在多資料中心的情況下情況更復雜
-
-
-
單調讀
- 為防止兩次讀取從庫可能出現的時間倒流情況(第一次讀較新的庫,第二次讀了較舊的庫),可使使用者只在一個從庫上讀,確保資料單調一致性。(如根據使用者ID進行HASH)
-
一致字首讀
- 為防止具有先後因果的資料所寫入不同分割槽,而“因”資料的讀入延遲大於“果”的讀入延遲,在客戶端側看來會出現因果倒置於的現象,需要將具有前後因果的資料寫入同一分割槽解決
多主複製
優勢
-
效能:寫操作可以在本地資料中心進行處理,寫網路延遲可能更低
-
可用性
-
容忍單個數據中心停機
-
資料中心間採用非同步複製,因此中心間的網路通訊故障不會導致寫入失敗
- 需要考慮的問題:寫衝突
-
-
其它適用的場景
-
協同編輯
- 如石墨文件
-
離線場景
- 考慮手機,膝上型電腦和其他裝置上的日曆應用。無論裝置目前是否有網際網路連線,你需要能隨時檢視你的會議(發出讀取請求),輸入新的會議(發出寫入請求)。如果在離線狀態下進行任何更改,則裝置下次上線時,需要與伺服器和其他裝置同步
-
專為多主設計的資料庫CouchDB
- CouchDB支援雙向資料複製,衝突檢查。其適用於文中的離線操作場景主要是受益於CouchDB的支援MVCC(多版本併發控制)特性,詳見第7章。
-
寫衝突
-
如果採用同步衝突檢測,即等待所有主節點寫完畢告訴使用者寫成功,會失去各主節點可以獨立寫的優點
-
避免衝突
- 如同一使用者所接入的寫資料中心只能是同一個,如果允許同一使用者的寫請求同時接入多個數據中心,則需要在業務層面處理衝突
-
衝突合併
-
給每個寫入分配一個ID(如時間戳),具有最新的ID勝出,丟棄其它寫請求。
- 易造成資料丟失
-
給每個副本分配一個副本ID,具有最高ID的優先順序高
- 易造成資料丟失
-
增加業務處理衝突程式碼
-
寫時執行
- 檢測到寫衝突就呼叫使用者自定義的處理程式碼。如Bucardo可編寫Perl程式碼解決衝突
-
讀時執行
- 寫入時,所有衝突均會記錄,待使用者讀時,返回多版本給應用,用應用決定處理
-
-
-
複製拓撲
-
環形
-
星形
-
互聯(All to All)
-
問題:如果出現了因果資料寫入,則可能會出現類似於分片時延不同而導致的資料亂序問題
- 解決方法:使用“版本向量”技術控制
-
-
無主複製
定義:由客戶端同時向多個副本寫入資料,由客戶端決定寫入是否成功,讀取時根據各副本的版本號投票決定讀取的結果
故障時寫入資料庫
-
例子:假設3副本的環境,有一個副本不可用,2個副本可以正常寫入
-
讀修復和反熵
- 讀修復:在客戶端讀取時向老版本的副本庫中寫入新的資料
- 反熵:資料庫後臺檢測舊版本,並對其資料進行修復
-
讀寫的法定人數
檢測併發寫入
- 單副本:使用基於版本號的樂觀鎖進行寫入
- 多副本:基於版本向量