Redis 雙活架構

( 基於CRDTS )

雙活(Active-Active)架構

雙活(Active-Active)架構是一種資料彈性架構,它透過獨立的、分佈在不同地理位置的叢集和節點,在多個資料中心分發資料庫資訊。該架構由多個獨立的處理節點組成,每個節點都能存取共享的複製資料庫,使所有節點都能參與相同應用,並確保本地低延遲,同時各區域可以獨立運作。

雙活架構或雙活地理分散式拓撲(Active-Active Geo-Distributed topology)透過在Redis企業版中實現CRDT(無衝突複製資料類型) 來建立跨多個叢集的全域資料庫,此資料庫稱為無衝突複製資料庫(CRDB)。

CRDB 相較於其他地理分散式解決方案,具備三大核心優勢:

  • 本地低延遲:無論有多少個地理複製區域,或它們之間的距離多遠,CRDB 都能確保讀寫操作的低延遲。
  • 無衝突資料同步:針對Redis 核心的資料類型(包括簡單且複雜類型),實現自動無衝突合併,避免資料不一致問題。
  • 高可用性保障:即使大部分地理複製區域(如5 個區域中有3 個宕機)無法運行,其餘可用區域仍能繼續執行讀寫操作,確保業務連續性。

部署與拓樸結構

CRDB(無衝突複製資料庫)是一個跨多個Redis Enterprise 叢集建立的資料庫,這些叢集通常位於全球不同的資料中心。每個參與集群中的資料庫稱為「CRDB 實例」。只要CRDB 資料集的大小適配CRDB 實例的內存,每個CRDB 實例都可以採用不同的配置——它們可以由不同數量的分片組成,並運行在不同數量或類型的叢集節點上。

此外,一個CRDB 實例可以部署在多可用區(AZ)的叢集配置中,啟用高可用性和資料持久化。而另一個CRDB 執行個體則可能運行在單一可用區的叢集配置中,不啟用高可用性或資料持久化。這些CRDB 執行個體可以在任何雲端環境(包括Google Cloud、Azure 和AWS)中同時運作。這種靈活性有助於優化基礎設施成本,並根據特定業務需求提升資料庫效能。

使用CRDB 的應用程式會連線到本機CRDB 實例的端點。所有CRDB 實例之間採用雙向資料庫複製,並形成網狀拓撲結構,即應用程式對本機實例的所有寫入都會複製到所有其他實例,如下圖所示:

Redis 雙活架構 CRDTs

進階架構

CRDB 架構是基於Redis 命令和資料類型的替代實作(即無衝突複製資料類型,CRDT)。在Redis 企業版中,CRDB 是基於Redis 模組資料類型API 建構的專有Redis 模組

讀取操作由本機CRDB 實例處理。由於CRDT 層採用無共識機制,因此無需進行其他雙活架構常見的「讀取修復」(read repair)。

寫入操作遵循基於操作的CRDT(operation-based CRDT) 原則,分為兩個步驟:

  • 準備階段:使用者請求在本地CRDB 實例上處理,並產生對應的影響資料(effect)
  • 應用階段(Effect step):產生的影響資料會分發到所有CRDB 執行個體(包含本機執行個體)並執行應用程式。

基於操作的CRDT 要求影響資料必須確保精確投遞一次(exactly-once delivery),並維持來源FIFO(先進先出)一致性。 CRDB 主要依賴Redis 複製機制,並針對該機制進行了一些最佳化,以滿足這些一致性要求。

對等複製

CRDB 複製由同步器(syncers) 實現,它們會與遠端主實例(primary)建立連接並請求對等複製(Peer Replication),並為此引入了一種全新的資料庫複製機制。對等複製的工作方式類似於標準Redis 複製:

  • 透過PSYNC 和複製偏移(replication offset) 來恢復中斷的連線。
  • 在必要時,可回退至完整SYNC 進行全量同步。

一旦對等節點建立複製連接,僅由CRDT 模組產生的CRDT 影響資料(CRDT effects) 會被傳播。根據不同的拓撲結構,還可以進行額外的篩選,以僅包含特定更新。在網狀拓撲(mesh topology) 中,對等複製僅傳播本地CRDB 實例產生的影響資料。

此外,CRDB 實例可以向不同的對等實例推送多個複製流,使對等複製機制能夠管理多個不同的複製日誌。

自動GZIP 壓縮與SSL 加密:當偵測到遠端公網IP 時,CRDB 會自動啟用GZIP 壓縮,以最佳化廣域網路(WAN)連線的頻寬利用率。同時,如果在連線建立過程中偵測到SSL 握手,則會自動啟用加密,確保資料傳輸的安全性。

下圖展示了對等複製的運作機制:

高可用性與災難復原

如果一個或多個CRDB實例發生故障,全域CRDB 下的其他實例仍可繼續讀寫,確保業務持續可用,並提供災難復原能力。即使大部分CRDB 實例(例如5 個實例中有3 個宕機)無法執行,剩餘的CRDB 實例仍能正常提供讀寫服務,不受影響。在此類區域性故障的情況下,無法連線到本機CRDB 執行個體的使用者通常會自動被引導至其他資料中心,以存取仍可用的CRDB 執行個體。這確保了即使本機CRDB 實例宕機,套用的讀寫請求仍可正常進行。

在極少數情況下,某個CRDB 實例可能會發生資料完全遺失,需要從頭開始進行資料庫複製。這種情況需要特殊處理,因為該CRDB 實例在故障前可能已經向部分對等實例發送了更新,而這些更新的接收情況可能存在差異。由於無法保證所有對等實例最終會達成一致(部分影響資料可能僅由部分實例接收),Redis Enterprise 採用資料對帳機制(Reconciliation Mechanism)來協調所有相關的CRDB 實例。對帳完成後,復原中的執行個體可以從任意可用副本進行全量同步(Full Sync),以完成復原。

一致性模型

在CRDB 部署中,應用了多種一致性特性:

  • 本地CRDB 實例操作:當使用WAIT 指令時,可實現接近強一致性(near strong consistency);否則,操作會歸類為弱一致性(weak consistency)。
  • 全域CRDB 操作:採用強最終一致性(Strong Eventual Consistency, SEC),確保任何兩個CRDB 實例在接收相同(無序)的更新集合後,無需共識協定即可達到相同狀態。與僅提供活性保證(liveness guarantee)的最終一致性系統不同(即更新最終會被觀察到),強最終一致性還額外提供安全性保證(safety guarantee),確保數據狀態穩定可靠。

無衝突解析

CRDB 的衝突解析是基於CRDT(無衝突複製資料型別) 的三大原則:

  • 並發寫入的結果是可預測的,並遵循一套確定性的規則。
  • 應用程式無需額外處理並發寫入,但必須與CRDB 的「方言」(dialect)相容。
  • 資料集最終會收斂到單一、一致的狀態,確保資料一致性。

衝突解析機制

每個CRDB 實例都會獨立維護一個向量時脈(vector clock),用於追蹤每個資料物件或子物件的更新狀態。向量時脈會在本機更新操作發生時更新,或當相同物件的更新操作從其他CRDB 執行個體傳入時更新。

當CRDB 執行個體接收到來自其他執行個體的更新操作(及其向量時脈)時,會執行下列步驟:

第一階段:更新分類

收到的更新操作可能屬於以下三種情況:

  1. 新更新(new update)
  2. 舊更新(old update)

  3. 並發更新(concurrent update)

分類演算法如下:

當實例A 收到實例B 發送的關於物件X 的更新時:

  • 如果x_vc[b] > x_vc[a],則該更新為「新更新」。
  • 如果x_vc[b] < x_vc[a],則該更新為「舊更新」。

  • 如果x_vc[b] ≸ x_vc[a],則該更新為「並發更新」。

其中,x_vc[a]是實例A 維護的物件X 的向量時鐘,x_vc[b]是實例B 維護的物件X 的向量時鐘。

第二階段:本地更新對象

  • 如果更新被分類為“新更新”,則在本機CRDB 實例中更新該物件的值。
  • 如果更新被分類為“舊更新”,則不在本機CRDB 實例中更新物件的值。

  • 如果更新被分類為“並發更新”,則執行衝突解析機制,決定是否以及如何更新該物件的值。

CRDB 的衝突解析演算法主要基於兩個處理流程:

流程1:無衝突資料類型/操作的解析

在許多並發更新場景下,某些資料類型的固有特性可確保更新完全無衝突(conflict-free),例如:

  • 計數器(Counter):當資料類型為計數器(對應到CRDT 的Counter)時,所有操作都是可交換的(commutative),因此不會發生衝突。
    範例:用於追蹤文章熱度、分享次數或不同地區的轉發數量。
  • 集合(Set):當資料類型為集合(對應到CRDT 的Add-Wins Observed-Removed Set),且並發更新均為ADD 運算時,所有運算都是結合性(associative)或冪等的(idempotent),因此不會發生衝突。
    範例:在詐欺偵測中,應用程式追蹤與特定ID 或信用卡相關的可疑事件。如果關聯的Redis Set 基數達到某個閾值,則觸發警報。

  • 哈希表(Hash):當資料類型為雜湊表(映射到CRDT 的map),並發更新發生在不同的Hash 欄位上時,所有操作都是無衝突的,相當於這些欄位分別作用於不同的物件。
    範例:企業共享帳戶,多個使用者在不同地點或以不同費率使用相同帳戶。每個帳戶的HASH 物件包含多個字段,每個字段對應不同使用者的使用情況,即使並發更新,也不會發生衝突。

在這些場景下,物件值的更新會依照資料類型的策略執行,確保資料的一致性。

流程2:使用「最後寫入優先(LWW)」 機制解析衝突

對於非無衝突的資料類型(如Redis 字串(String),映射到CRDT 的register),需要應用衝突解析演算法。在這種情況下,CRDB 採用最後寫入優先(LWW, Last Write Wins) 機制,透過操作時間戳記(timestamp)作為仲裁標準來解析衝突。

即使不同地區的時間戳記有偏差(timestamp skew),LWW 仍可確保最終達到強最終一致性(Strong Eventual Consistency)。例如:

  • 假設實例A 的時間戳記總是比其他實例的時間戳靠前(即在發生衝突時,實例A 總是獲勝),最終仍能確保一致性。
    範例:當一個使用者帳戶的密碼被修改時,多個分佈在不同地區的使用者可能會受到影響。在這種情況下,其他用戶將被強制登出,這可能是許可證管理等場景下的正確行為。

Resources

Technical Articles

Honghong will provide you with any support you need!

Our professional Honghong team will be the first to respond and provide you with the best service to solve all your problems.