1. 程式人生 > 實用技巧 >《設計資料密集型應用》- Designing Data-Intensive Application - 第5章 複製 讀書筆記

《設計資料密集型應用》- Designing Data-Intensive Application - 第5章 複製 讀書筆記

在這裡插入圖片描述

複製

領導者與追隨者

單領導者

同步複製與非同步複製

  • 同步
  • 非同步
  • 半同步:一個副節點同步,其餘副節點非同步

設定新從庫

  • 全量鏡象+增量

處理節點宕機

  • 從節點

    • 追趕恢復
  • 主節點

    • 流程

      • 由剩餘從節點或控制節點進行選主流程
      • 通常選舉有最新副本的從節點做為主節點
      • 舊主節點上線後作為從節點
    • 存在問題

      • 新主庫缺失舊主庫部分寫入,如果其收到衝突的寫入(如主鍵衝突),常見方法是丟掉舊主庫未同步的寫入,但影響了寫入的永續性
      • 如果丟掉的寫入與其他資料庫相關聯,則有可能會出現資料不一致的問題
      • 腦裂
      • 主庫判定失效超時時間設定困難,太短,容易受網路抖動延遲誤操作;太長,選主延遲加大,丟失的資料也可能越多

複製日誌的實現

  • 基於語句的複製

    • 問題

      • 非確定語句執行會出現主從不一致的問題,如NOW(),RAND()
      • 如果使用了自增列或依賴於庫中現有的資料,則從節佔的執行順序必須嚴格按主節點的執行順序
      • 現MYSQL會將含有不確定的語句轉換為基於行的複製
  • 基於WAL,PostgreSQL與Oracle使用該類複製

    • 問題:日誌記錄過於底層,記錄了磁碟塊上哪些位元組有了更改,對主從所採用的儲存引擎、資料庫版本的一致性要求高
  • 基於邏輯日誌(基於行)

    • 記錄與儲存引擎相分離,因此主從可採用不同的儲存格式,資料庫也可不同
  • 基於觸發器

    • 由於事務需要等觸發器完成其操作才能提交,所以事務處理延遲會增加。

複製延遲問題

解決方法

  • 讀己之寫

    • 從業務程式碼上入手

      • 對於和自身相關的資訊,都從主庫讀取,其它使用者的從從庫讀取

      • 跟蹤上次更新時間,如果小於一定時間(如一分鐘),則從主庫讀

      • 客戶端儲存最近一次寫入的時間戳,所讀的從庫確保最新的資料時間大於等於該時間(訪問需要系統額外判斷從庫資料的時間資訊)

        • 如果同一使用者在不同終端同時登入並做了寫入操作,此時不同客戶端所儲存的時間戳不一致,也會出現所看到的資料不一致問題,在多資料中心的情況下情況更復雜
  • 單調讀

    • 為防止兩次讀取從庫可能出現的時間倒流情況(第一次讀較新的庫,第二次讀了較舊的庫),可使使用者只在一個從庫上讀,確保資料單調一致性。(如根據使用者ID進行HASH)
  • 一致字首讀

    • 為防止具有先後因果的資料所寫入不同分割槽,而“因”資料的讀入延遲大於“果”的讀入延遲,在客戶端側看來會出現因果倒置於的現象,需要將具有前後因果的資料寫入同一分割槽解決

多主複製

優勢

  • 效能:寫操作可以在本地資料中心進行處理,寫網路延遲可能更低

  • 可用性

    • 容忍單個數據中心停機

    • 資料中心間採用非同步複製,因此中心間的網路通訊故障不會導致寫入失敗

      • 需要考慮的問題:寫衝突
  • 其它適用的場景

    • 協同編輯

      • 如石墨文件
    • 離線場景

      • 考慮手機,膝上型電腦和其他裝置上的日曆應用。無論裝置目前是否有網際網路連線,你需要能隨時檢視你的會議(發出讀取請求),輸入新的會議(發出寫入請求)。如果在離線狀態下進行任何更改,則裝置下次上線時,需要與伺服器和其他裝置同步
    • 專為多主設計的資料庫CouchDB

      • CouchDB支援雙向資料複製,衝突檢查。其適用於文中的離線操作場景主要是受益於CouchDB的支援MVCC(多版本併發控制)特性,詳見第7章。

寫衝突

  • 如果採用同步衝突檢測,即等待所有主節點寫完畢告訴使用者寫成功,會失去各主節點可以獨立寫的優點

  • 避免衝突

    • 如同一使用者所接入的寫資料中心只能是同一個,如果允許同一使用者的寫請求同時接入多個數據中心,則需要在業務層面處理衝突
  • 衝突合併

    • 給每個寫入分配一個ID(如時間戳),具有最新的ID勝出,丟棄其它寫請求。

      • 易造成資料丟失
    • 給每個副本分配一個副本ID,具有最高ID的優先順序高

      • 易造成資料丟失
    • 增加業務處理衝突程式碼

      • 寫時執行

        • 檢測到寫衝突就呼叫使用者自定義的處理程式碼。如Bucardo可編寫Perl程式碼解決衝突
      • 讀時執行

        • 寫入時,所有衝突均會記錄,待使用者讀時,返回多版本給應用,用應用決定處理
  • 複製拓撲

    • 環形

    • 星形

    • 互聯(All to All)

      • 問題:如果出現了因果資料寫入,則可能會出現類似於分片時延不同而導致的資料亂序問題

        • 解決方法:使用“版本向量”技術控制

無主複製

定義:由客戶端同時向多個副本寫入資料,由客戶端決定寫入是否成功,讀取時根據各副本的版本號投票決定讀取的結果

故障時寫入資料庫

  • 例子:假設3副本的環境,有一個副本不可用,2個副本可以正常寫入

  • 讀修復和反熵

    • 讀修復:在客戶端讀取時向老版本的副本庫中寫入新的資料
    • 反熵:資料庫後臺檢測舊版本,並對其資料進行修復
  • 讀寫的法定人數

檢測併發寫入

  • 單副本:使用基於版本號的樂觀鎖進行寫入
  • 多副本:基於版本向量