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

技術文章

宏虹將提供您所需的任何支援!

專業的宏虹團隊會第一時間回應,為您提供最佳的服務,解決您的一切問題