分布式数据复制技术
分布式數據復制技術
- 前言
- 什么是數據復制技術?
- 數據復制技術原理及應用
- 同步復制技術原理及應用
- 異步復制技術原理及應用
- 半同步復制技術原理及應用
- 三種數據復制技術對比
- 知識擴展:在半同步復制技術中,對于未回復數據更新結果的節點,如何解決數據不一致或沖突呢?
- 總結
前言
數據分布(也稱數據分片)技術,主要用于構建數據索引, 是實現“導購”功能的關鍵技術。數據分布的本質是,將原數據集劃分為多個數據子集,以存儲到不同的地方,在一定程度上體現了數據的可用性和可靠性(一個存儲節點故障,只影響該存儲節點的數據)。
數據分片和數據復制技術均是實現“導購”的關鍵技術:
- 數據分片是確定數據位置;
- 數據復制是實現數據可靠性的關鍵方法。
在實際情況下,僅考慮數據分片,其實是無法真正應用到生產環境的。因為,故障導致數據丟失和不可用是很常見的情況。因此,在進行分布式數據存儲設計時,通常會考慮對數據進行備份,以提高數據的可用性和可靠性,而實現數據備份的關鍵技術就是“數據復制技 術”。
什么是數據復制技術?
數據復制是一種實現數據備份的技術。比如,現在有節點 1 和節點 2,節點 1 上存儲了 10M 用戶數據,數據復制技術就是將節點 1 上的這 10M 數據拷貝到節點 2 上,以使得節點 1 和節點 2 上存儲了相同的數據,也就是節點 2 對節點 1 的數據進行了備份。當節點 1 出現故障后,可以通過獲取節點 2 上的數據,實現分布式存儲系統的自動容錯。
數據復制技術可以保證存儲在不同節點上的同一份數據是一致的。當一個節點故障后,可以從其他存儲該數據的節點獲取數據,避免數據丟失,進而提高了系統的可靠性。
在分布式數據庫系統中,通常會設置主備數據庫,當主數據庫出現故障時,備數據庫可以替代主數據庫進行后續的工作,從而保證業務的正常運行。備數據庫繼續提供服務就是提高了分布式存儲系統的可用性及可靠性。
在這個過程中,實現備數據庫替代主數據庫,就涉及到數據一致性的問題了,只有主備數據庫中的數據保持一致時,才可實現主備的替換。在這個例子中,數據復制技術實際就是指,如何讓主備數據庫保持數據一致的技術。
數據復制技術原理及應用
CAP 理論的 C、A 和 P 三個特性,在分布式存儲系統中,分區容錯性是肯定要滿足的,為此需要在一致性和可用性之間做出權衡。所以,對于數據的一致性,通常是指不同節點上數據要保持一致。要實現不同節點上的數據 一致,數據復制技術必不可少。對于分布式存儲系統中的數據復制技術來講,也需要在一致性和可用性之間做出一些權衡。這就導致出現了多種數據復制技術方法,大體上有三類:
同步復制技術原理及應用
同步復制技術:指當用戶請求更新數據時,主數據庫必須要同步到備數據庫之后才可給用戶返回,即如果主數據庫沒有同步到備數據庫,用戶的更新操作會一直阻塞。這種方式保證了數據的強一致性,但犧牲了系統的可用性。
在一個分布式數據庫系統中,有兩個節點,分別作為主節點和備節點。通常情況下,兩個節點均可接收用戶讀請求,然后將本節點的數據及時返回給用戶,讀請求響應比較快。而如果用戶發送的是寫請求,寫操作必須由主節點進行,即使用戶將寫請求發送到備節點,備節點也會將該請求轉發給主節點,因此寫請求通常比讀請求響應慢。MySQL 集群的讀寫分離就是一個典型實例。
如此設計的原因是,讀請求不需要改變數據,只需要在更改數據時保證數據一致,就可以隨時讀;而寫請求,因為要修改數據,如果每個節點均修改同一數據,則可能導致數據不一致。因此只有主節點可以進行寫操作,但又要保證主節點和備節點的數據一致,這就是數據復制技術要發揮的作用了。
對于上述場景,如果采用同步復制技術的話,對于寫請求,主數據庫會執行寫操作,并將數據同步到所有備數據庫之后才可以響應用戶。如圖所示,客戶端向主數據庫發起更新操作 V,將 X 設置為 2,主數據庫會將寫請求同步到備數據庫,備數據庫操作完后會通知主數據庫同步成功,然后主數據庫才會告訴客戶端更新操作成功。MySQL 集群支持的全復制模式就采用了同步復制技術。
在同步復制技術中,主數據庫需要等待所有備數據庫均操作成功才可以響應用戶,會影響用戶體驗,同步復制技術經常用于分布式數據庫主備場景(對于一主多備場景,由于多個備節點均要更新成功后,主節點才響應用于,所需時延比較長)或對數據一致性有嚴格要求的場合,比如金融、交易之類的場景。
異步復制技術原理及應用
異步復制技術:指當用戶請求更新數據時,主數據庫處理完請求后可直接給用戶響應,不必等待備數據庫完成同步,即備數據庫會異步進行數據的同步,用戶的更新操作不會因為備數據庫未完成數據同步而導致阻塞。這種方式保證了系統的可用性,但犧牲了數據的一致性。
如圖所示,客戶端 1 向主數據庫發起更新操作 V,主數據庫執行該操作,將 X=1 修改為 X=2,執行后直接返回給客戶端 1 更新操作成功,而未將數據同步到備數據庫。當客戶端 2 請求主數據庫的數據 X 時,可以得到 X=2,但客戶端 3 請求備數據庫中的數據 X 時,卻只能得到 X=1,從而導致請求結果不一致。
分布式數據庫主備模式場景下,若對數據一致性要求不高,可以采用異步復制方法。MySQL 集群默認的數據復制模式采用的是異步復制技術,以 MySQL 集群默認的復制模式為例,展示主備數據庫同步的流程:
異步復制技術大多應用在對用戶請求響應時延要求很高的場景,比如很多網站或 App 等需要面向實際用戶,這時后臺的數據庫或緩存如果采用同步復制技術,可能會流失用戶,因此這種場景采用異步復制技術就比較合適。
在緩存數據庫 Redis 集群中,采用的也是異步復制技術,因此性能較高。但在 Redis 中還會有其他機制來保證數據的一致性。
半同步復制技術原理及應用
同步復制技術會滿足數據的強一致性,但會犧牲一定的可用性;異步復制技術會滿足高可用,但一定程度上犧牲了數據的一致性。介于兩者中間的是,半同步復制技術。
半同步復制技術:用戶發出寫請求后,主數據庫會執行寫操作,并給備數據庫發送同步請求,但主數據庫不用等待所有備數據庫回復數據同步成功便可響應用戶,主數據庫可以等待一部分備數據庫同步完成后響應用戶寫操作執行成功。
半同步復制技術通常有兩種方式:
第二種半同步復制方案要求的一致性比第一種要高一些,但相對可用性會低一些。
MySQL 集群在一主多備場景下,也支持半同步復制模式,一般采用的是第一種半同步復制技術,這種技術既不會影響過多的性能,還可以更好地實現對數據的保護。
具有 CP 特性的 ZooKeeper 集群采用的數據復制技術就是第二種半同步復制方案。在 ZooKeeper 集群中,寫請求必須由 Leader 節點進 行處理,每次寫請求 Leader 會征求其他 Follower 的同意,只有當多數節點同意后寫操作才可成功,因此保證了較高的一致性。
還有很多系統采用了第二種半同步復制方案,比如微軟云關系型數據庫 Microsoft SQL Azure 的后端存儲系統 Cloud SQL Server、Kubenetes 中保存集群所有網絡配置和對象狀態信息的 Etcd 組件(該組件采用的是 Raft 一致性協議)等。
多數的分布式存儲系統可以通過配置來選擇不同的數據復制技術。比如 MySQL 數據庫集群,就支持全同步復制、異步復制和半同步復制三種模式,再比如 Oracle 數據庫,也提供了三種模式:
- 最大保護模式,對于寫請求,要求主數據庫必須完成至少一個備數據庫的數據同步才可成功返回給客戶端,采用的是半同步復制技術中的第一種方式。
- 最大性能模式,對于寫請求,只要主數據庫執行成功即可返回給客戶端,采用的是異步復制技術。這種方式極大地提高了系統的可用性,但一致性難以保證。
- 最大可用性模式,介于最大保護模式和最大性能模式兩者之間。系統在通常情況下采用最大保護模式,但當主備之間出現網絡故障時,切換為最大性能模式, 等到網絡恢復后,備數據庫再進行數據同步。這種方式在系統的一致性和可用性之間做了一個權衡。
三種數據復制技術對比
知識擴展:在半同步復制技術中,對于未回復數據更新結果的節點,如何解決數據不一致或沖突呢?
對于半同步復制技術,因為只有部分備節點更新數據后,主節點即可返回響應用戶。對于未回復數據更新結果的節點,可能存在的數據不一致或沖突。
不同的場景有不同的處理方式,需要根據用戶的需求進行選擇,比如以最新數據為準、以最大數據為準等,沒有統一的評判規則,和用戶的需求緊密相關。
在分布式系統中,很多系統采用了 Raft 算法。Raft 算法采用的是第二種半同步復制技術,主數據庫等超過一半節點 (包括主數據庫)回復數據更新成功后,再給用戶響應寫操作成功。當有 Follower 節點的數據與 Leader 節點數據不一致時,采用強制復制策略來解決不一致情況。
由于所有的數據更新操作最先在 Leader 節點執行,因此當產生沖突時,以 Leader 節點為準。Leader 節點上會對比與自己數據不一致的 Follower 節點所存儲的信息,找到兩者最后達成一致的地方,然后強制將這個地方之后的數據復制到該 Follower 節點上。
具體方法:Leader 節點將每一次數據操作看作一條記錄,并對這條記錄標記一個 index,用于索引。Leader 節點會為每個 Follower 節點維護一個記錄狀態變量 nextIndex,即下一個記錄的索引位置(nextIndex 的值為 Leader 節點當前存儲數據記錄的下一個 Index 值)。Leader 節點會將 nextIndex 發送給 Follower 節點,若 Follower 節點發現與本節點的 nextIndex 不一致,則告知 Leader 節點不一致,Leader 節點將 nextIndex 減 1,重復上述過程,直到與 Follower 節點的 nextIndex 相等位置,即找到了兩者最后達成一致的地方。
比如,對于變量 X,Leader 節點記錄的操作是{(Index 1, X = 1, Version:0), (Index 2, X=2, Version:1), (Index3 , X=3, Version:2)},其中,Follower 節點 2 記錄的操作為 {(Index 2, X=1, Version:0), (Index 6, X=4, Version:2)}。Leader 節點發現兩者最后一致的狀態是 {(Index 1, X=1, Version:0)},為此將后續的 {(Index 2, X=2, Version:1), (Index 3, X=3, Version:2)}復制到節點 2 上,則節點 2 更新為 (Index 1, X = 1, Version: 0), (Index 2, X=2, Version:1), (Index3 , X=3, Version:2)}。節點 2 與 Leader 節點的數據保持一致。
總結
總結
- 上一篇: 《跟着王老师学Excel VBA》的笔记
- 下一篇: 安装RocketChat报错:npm W