基于NodeJS從零構建線上自動化打包工作流
本文翻譯自國外論壇 medium,原文地址:https://medium.com/@interviewready/data-replication-in-distributed-system-87f7d265ff28
什么是數據復制?
數據復制是指將數據復制到一個或多個數據容器以確??捎眯缘倪^程。復制的數據通常存儲在不同的數據庫實例中,即使一個實例發生故障,我們也可以從其他實例獲取數據。
一種流行數據復制的實現架構是主從架構。
“
推薦博主開源的 H5 商城項目waynboot-mall,這是一套全部開源的微商城項目,包含三個項目:運營后臺、H5 商城前臺和服務端接口。實現了商城所需的首頁展示、商品分類、商品詳情、商品 sku、分詞搜索、購物車、結算下單、支付寶/微信支付、收單評論以及完善的后臺管理等一系列功能。技術上基于最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中間件。分模塊設計、簡潔易維護,歡迎大家點個 star、關注博主。
github 地址:https://github.com/wayn111/waynboot-mall
”
主從架構
為了理解這個架構,我們舉一個例子。
- 我們有四個客戶端,每個客戶端都連接到一個負載均衡器。
- 然后負載均衡器將請求分發到三個應用程序服務器。
- 每臺服務器連接到一個數據庫實例。
你能注意到這里有什么問題嗎?
我們的數據庫存在單點故障。如果它崩潰了,我們的整個系統就會停止工作。
為了避免這種單點故障,我們可以使用另一個數據庫(最好是不同的數據庫實例)來存儲原始數據的副本(一般我們成為從庫)。現在如果原始數據庫(主庫)崩潰,我們可以將請求轉到從庫。
但是我們如何保持從庫與主庫同步呢?這有兩種方法。
同步復制數據
- 在這種方法中,數據同時寫入主庫和從庫
- 數據始終一致。即數據如果寫入主庫,它也會寫入從庫
- 數據庫負載較高
異步復制數據
- 在這種方法中,首先將數據寫入主庫,并定期將更新寫入從庫
- 由于復制以固定間隔進行,因此存在數據丟失和不一致的可能性
- 數據庫負載相對較低
這里我們的一般定義是收到寫請求的主庫數據庫是 master)。從庫被稱為 slaves。
主從架構
如上圖我們的主站也就是 Server2 維護事務日志。他會更新從站中(Server1)的數據,它發送命令,然后從站以相同的順序執行這些命令。
如果服務器向從站發送寫入請求會發生什么?
有兩種方法可以處理這種情況
- 不允許對從站的寫請求,從站無法寫入數據庫,它只能去讀從庫數據。
- 允許從站寫入數據。我們將允許從站寫入數據。然后從站將更改復制到主站。在這種情況下,從站就接替了主站的角色。所以不再是主從架構而是主主架構
主主架構的問題
網絡故障可能會導致主主架構中的數據不一致。
讓我們用一個例子來理解這一點,假設我們有兩個數據庫實例 A 和 B。
- 兩人都是 master。
- 它們之間的路由器出現故障。所以 A 認為 B 離線,B 認為 A 離線。
- 他們有一個數據項 X,其值最初為 100。
現在用戶發送以下請求,
- X 減去 20,該請求被路由到 A,此時 A 中 X 的值為 80。
- X 減去 80,這個請求被路由到 B(因為都是 master,所以寫請求可以路由到任何數據庫)。現在 B 中 X 的值為 20。
由于存在通信故障,A 和 B 無法同步,它們具有不同的數據值,因此不一致。
- 現在,如果用戶發出讀請求,他/她將獲得不同的值,具體取決于他/她將連接到的數據庫。
這個問題被稱為裂腦問題。
解決裂腦問題
解決裂腦問題
我們可以通過添加第三個節點(數據庫實例)來解決裂腦問題。
這里我們假設一個節點崩潰以及其他兩個節點之間的路由器崩潰的可能性極小。
讓我們考慮三個數據庫實例 A、B 和 C。
- 如果 C 崩潰,A 和 B 是主庫并且它們是同步的。所以他們處于一致的狀態。當 C 在線時,他們可以讀取 A 或 B 的內容。
- 如果 A 和 B 之間出現通信故障
- 當 A 收到寫入請求時,它將其狀態傳播到 C。最初狀態為 S0,然后轉移到 Sx。所以現在 A 和 C 都有 Sx。
- 當 B 收到寫入請求時,它將其狀態從 S0 移至 Sy。它嘗試將其狀態傳播到 C,但失敗,因為 B 的先前狀態不等于 C。現在 B 中止寫入請求并將其狀態更新為 Sx?,F在 B 可以接受寫入請求并將更改傳播到 C。
這稱為分布式共識。多個節點就特定值達成一致。在這種情況下,A、B 和 C 在最終狀態上達成一致。
最后
感謝您的閱讀,希望本文能對你理解分布式架構中的數據復制有所幫助。