文章目錄
數據複製
目的
- 高可用。容忍單個副本故障、網絡分區。
- 可擴展。多副本提高讀吞吐量。
- 低延時。距用戶較近,交互更快。
主從複製
- 寫:主節點。讀:從節點。
- 到主節點網絡問題影響所有寫入。
複製形式
- 同步複製。從節點確認寫入後返回。
- 從節點數據最新版本,可瞬間故障切換。
- 異步複製。從節點無需確認。
- 從節點不會影響主節點吞吐量。
- 半同步複製。一個從節點同步,其餘異步。
複製日誌
- 基於語句。INSERT等。
- 非確定性語句,now等執行結果不同。
- 依賴現有數據的操作,如UPDATE,需要保證副本按照相同順序執行。
- 基於物理日誌WAL,如redo。
- 和存儲引擎耦合,偏底層。如果存儲格式不前後兼容,無法滾動升級。
- 基於邏輯日誌,如binlog。
- 複製和存儲邏輯解耦。向後兼容,方便異構數據。
- 包含行前後值。記錄因果關係,處理併發。
- 基於觸發器。
- 靈活但是增加數據庫壓力。
運維變更
- 新增從節點。
- 一致性快照 -> 複製日誌追趕變更。
- 從節點失效。根據複製日誌追趕式恢復。
- 主節點失效。節點切換。
- 確認主節點失效。如心跳超時。
- 選新的主節點。選舉->共識算法推送,節點和主節點差異小優先。
- 新主節點生效。寫請求轉發,原主節點恢復後降級成從節點。
- 節點切換風險。
- 腦裂。老主節點上線未失效,寫衝突。
- 數據丟失。異步複製從節點落後,如果外部依賴這部分數據,危險。
- 使用自增主鍵,外部映射到該主鍵關係錯誤。
- 頻繁切換。超時時間選取,可使用手工切換。
副本一致性
- 讀寫一致。從節點讀到自己主節點寫的數據。
- 從主節點讀取用戶可能修改的數據。
- 讀取時帶時間戳(版本號或時鐘),副本需要覆蓋寫入的時間戳,否則重選副本。
- 單調讀一致。讀到新版本後不再讀到舊版本。
- 根據用戶id路由指定副本。
- 因果一致。先發生先讀。
- 有因果關係的寫入從一個副本讀。
- happens-before追蹤因果。
多主複製
適用場景
- 多數據中心。
- 性能。就近寫,不用跨廣域網。
- 容錯。切換數據中心。
- 數據中心失效。
- 到數據中心的網絡失效。
- 離線客戶端。等價於單節點數據中心+極不可靠的網絡。
- 協作編輯。
處理寫衝突
異步檢查:主節點各自寫入的優勢。
同步檢查:簡單。
- 避免衝突。用戶路由到單節點寫,但漫遊或網絡故障可能重新路由產生衝突。
- 收斂於一致。
- 最後寫入者獲勝(LWW)。
- 保留寫入版本號最大記錄。
- 保留節點版本號最大記錄。
- 合併併發寫入,依賴應用層(自動)、用戶(手動)解決衝突。
- 版本號標記操作的因果關係。
- 最後寫入者獲勝(LWW)。
無主複製
- 用戶寫入多個節點並從多個節點讀取。
- 通過數據版本號確認最新的有效值。
quorum一致
- 讀寫quorum。n個節點,w個寫入確認,r個讀取,w+r>n保證讀寫節點有重合,可以讀到最新值。
- 讀修復。讀取到舊版本回寫新版本。
- 反熵。後臺進程check更新數據版本。
quorum一致侷限
部分成功、複製滯後導致。
- 讀寫併發。寫操作部分完成,讀取不確定。
- 部分寫失效。寫操作成功數<w,操作失敗但是能讀取新值。
- 寬鬆quorum條件無法保證讀寫節點有重合。
- 網絡分區導致可達節點<w個,臨時節點暫存數據,保證總共寫入w個,網絡問題解決後數據回傳。
數據分區
- 目的:提高擴展性,大數據集分散在多個節點上,分擔查詢負載。
- partition同義詞。
- shard:ES,MongoDB
- region:Hbase
- tablet:Bigtable
- vnode:Cassandra
分區方式
- 基於關鍵字分區。
- 區間查詢特性良好。每個分區可以關鍵字順序查找。
- 基於關鍵字hash分區。
- 數據均勻分佈。特定模式會數據傾斜,造成熱點。
- 折中。如Cassandra。
- 複合主鍵第一列可hash分區,其他列用作SSTable的排序。
- 第一列分佈均勻,其他列支持區間查找。
二級索引
- 基於文檔。利於寫,ES、Cassandra。
- 本地索引。每個分區獨立,維護自己的二級索引。
- 並行查詢,讀延遲放大。
- 基於詞條。利於讀。
- 分區的全局索引。
- 單個文檔更新,如果涉及多個不同分區的二級索引,寫放大顯著,通常異步。
分區再平衡
- 原因:
- 查詢壓力增加,需要更多CPU。
- 數據規模增加,需要更多硬盤。
- 節點故障,需要其他節點接管。
- 目標:
- 負載、存儲在集羣中分佈均勻。
- 平衡過程中正常提供讀寫服務。
- 避免不必要的遷移,加快過程減少網絡磁盤I/O影響。
- 觸發方式:
- 自動。節點負載過重可能被認爲失效,再平衡會加重負載,可能雪崩。
- 手動。
取模
mysql分庫分表
- 遷移過程中數據在節點間複製,需要雙寫或者複製停寫,讀寫受影響。
- 再平衡成本高。
- 節點N發生變化,每個節點都有數據遷移。
- 節點N發生多次變化,同一條數據多次遷移。
固定數量分區
ES
- 初始創建遠超節點數的分區,節點->分區一對多。
- 新增節點時只需要調整分區、節點映射關係。
- 不影響節點的讀寫。
- 成本低。
動態分區
Hbase
- 初始預分區,或者集中在一個分區,節點->分區一對多。
- 分區數據量大於閾值則分裂,小於閾值則合併。
按節點比例分區
Cassandra
- 初始時每個節點具有固定數量的分區。Cassandra默認1節點->256個分區。
- 新增節點加入時,隨機選擇現有分區分裂拿走一半數據。
請求路由
- 客戶端連接任意節點,節點轉發到目標節點。
- gossip協議同步集羣狀態,如Cassandra。
- 客戶端連接路由層,路由層轉發到目標節點。
- zk同步集羣狀態,如hbase、codis。
- 客戶端感知分區節點,直連目標節點。
- 樣例:redis的三種集羣方案
事務
- ACID
- 事務隔離級別
- 重試中止事務的問題:
- 超時認爲已成功的事務未成功,重試需要保證冪等。
- 系統負載導致錯誤,重試更糟,需要重試上限、指數回退。
- 永久系統故障導致,重試無意義。
- 重試有除DB外的操作,如短信,需要分佈式事務。
- 重試失敗,需要補償。
分佈式系統問題
- 故障->部分失效。
不可靠網絡
- client->network->server->network->client,都有可能出問題。
- 超時是檢測故障唯一可行的方法。
- 網絡採用分組傳輸,動態分區。是可變性和可靠性的權衡。
- 優點是可以用較高的資源利用率應對突發流量。
- 缺點是數據可能包擁堵排隊,造成延遲的波動,這種異步網絡的延遲是沒有上界的。
不可靠時鐘
分類
- 牆上時鐘。絕對時鐘,可以和NTP同步。
- 如
System.currentTimeMillis()
從1970.1.1開始的毫秒,不含閏秒。 - 同步時如果本地時鐘遠快於NTP服務器,會直接回撥本地時鐘。
- 如
- 單調時鐘。相對時鐘,可以測量時間間隔(超時),NTP不同步。
- 如
System.nanoTime
。
- 如
依賴時鐘的風險
- 依賴絕對時間戳,時間不同步,可能產生因果倒序。優先考慮基於遞增計數器、時鐘置信區間。
- LWW前因覆蓋後果。
- LWW前因覆蓋後果。
- 依賴相對時間戳,進程暫停,產生衝突。
- 根據時間校驗租約->暫停->處理。可能暫停完租約過期,和其他節點處理衝突。
- 可以暫停前通知其他節點、大對象不回收定期重啓等應對進程暫停問題。
- 根據時間校驗租約->暫停->處理。可能暫停完租約過期,和其他節點處理衝突。
不可靠信息
真相由多數節點決定,節點不能根據自己的信息判斷自身狀態。//TODO zk故障全公司服務重啓
- 無意誤操作。如進程暫停,進程誤以爲自己還是Master。
- 應對:Fencing令牌,拒絕舊令牌的操作。
- 應對:Fencing令牌,拒絕舊令牌的操作。
- 拜占庭故障。如軟件bug、惡意攻擊。
- 應對:鑑權、加密等。
抽象模型
- 計時模型。網絡是否有上界延遲。
- 同步模型。
- 部分同步模型。
- 異步模型。
- 節點失效模型。
- 崩潰終止
- 崩潰恢復。
- 拜占庭失效。
普遍情況:部分同步+崩潰恢復。
一致性與共識
- 事務隔離:處理事務併發時的各種臨界條件。
- 分佈式一致性:針對延遲、故障等協調副本狀態。
可線性化
- 最強一致性模型。
- 基本思想:一個系統看起來只有一個副本,所有操作都是原子的。
- 使用場景:
- 加鎖和主節點選舉。
- 唯一性約束。主鍵、用戶名等。
- 跨通道的時間依賴。消息消費在圖片存儲完成之後。
- 實現方式。考慮容錯必須多冗餘,涉及複製,只有共識算法可靠。
- 共識算法。VSR,Paxos,Raft,Zab
- 主從複製。從唯一節點讀取。
- 使用快照隔離、腦裂則非線性化。
- 多主複製。非線性化。
- 無主複製。dynamo風格。
- 如果網絡延遲,在寫確認之前讀取,仍然非線性化。
- 如果網絡延遲,在寫確認之前讀取,仍然非線性化。
順序保證
- 因果一致性弱於可線性化。偏序關係。
- 因果關係可以被排序(happens-before)
- 併發關係無法被排序
- Lamport時間戳。
- 唯一:計數器-存儲節點ID的鍵值對
- 因果一致:節點追蹤並維護接觸的最大計數器,請求中帶上該計數器。
事務與共識
- 共識的等價問題:
- 線性化的CAS寄存器
- 原子事務提交
- 全序廣播
- 鎖與租約
- 成員協調
- 唯一性約束
- 解決方式
- 單個主節點。
- 主節點失效:等待恢復、認爲介入、共識算法選新主節點。
- 共識算法的要求:
- 安全性:
- 協商一致性。所有節點接收相同的決議。
- 誠實性。所有節點只能做一次決定。
- 合法性。結論一定是某個節點提出的。
- 活性:
- 可終止性。少於一半節點崩潰可達成結論。
- 安全性:
//TODO zk設計