復制和事件一致性
復制和事件一致性
1)為什麼要有意識的
當系統分布在區域/區域中時,同步記錄會給網絡故障帶來高潛伏性和低可用性。Eventual consistency(EC)允許出於以下原因暫時對副本進行同步:- 低記錄延遲(本地接收),
- 在網絡分割時提供更好的可用性,
- 水平縮放。
關鍵問題是可控的非嚴格一致性:用戶看到「足夠新鮮」的數據,域不變性得以保留,沖突被檢測並可以預測地解決。
2)一致性模型-我們向客戶承諾什麼
Strong: reading立即看到最後一個條目。
Bounded stale/read-not-older-than (RNOT):讀取不會老化標記(LSN/版本/時間)。
Causal:保留了「因果關系」(A到B)。
閱讀你的寫作:客戶看到他們最近的錄音。
Monotonic Reads:以下每個讀數不是「回滾」。
會議:一屆會議的一套保障措施。
Eventual:如果沒有新條目,所有副本都會收斂。
實踐:結合關鍵路徑上的Session+RNOT和店面/緩存上的Eventual。
3)復制: 力學與抗創作
同步(法定人數/RAFT):記錄在N節點確認後被認為是成功的;最低RPO,高於p99。
異步: 領導者向本地推銷,稍後分發日誌;低潛伏期,RPO> 0.
物理(WAL/binlog):快速,均質。
邏輯/CDC:字符串/事件級別的更改流,靈活的路由,過濾器。
反灌木叢:周期性鉆孔和修剪(Merkle樹,哈希比較,背景重新同步)。
4)版本標識符和因果關系
單調版本:increment/LSN/epoch;簡單但不編碼並發。
Lamport timestamp:按邏輯時鐘的部分順序。
Vector clock:捕獲平行分支並允許檢測沖突升級(concurrent)。
Hybrid/TrueTime/Clock-SI:全球秩序的邏輯「不早於T」。
建議:對於CRDT/沖突升級-矢量時鐘;對於「不老化」-LSN/GTID。
5)沖突: 檢測和解決
類型情況:從兩個區域寫入同一對象。
策略:1.最後的寫作-勝利(LWW)在時鐘/邏輯模具上-很簡單,但可能「丟失」升級。
2.域邏輯中的Merge函數:- 計數字段折疊(G-Conter/PN-Conter),
- 集合為「add-wins/remove-wins」,
- 金額/余額-僅通過事務日誌而不是通過簡單的LWW。
- 3.CRDT(融合類型):G-Counter,OR-Set,LWW-Register,RGA用於列表。
- 4.操作轉換(DB很少,編輯更常見)。
- 5.手動解決:「inbox」中的沖突,用戶選擇正確的版本。
規則:域不變量決定策略。對於金錢/余額-避免LWW;使用具有補償的交易/事件。
6)記錄保證和偶數
命令上的等效密鑰(payment、withdraw、create) →重播是安全的。
通過偶數鍵/序列號在「輸入」(inbox)和「輸出」(outbox)上進行重復數據消除。
沒有強大的先決條件,就無法實現僅Exactly。練習-least-once+等效性。
Outbox/Inbox模式:在DB中寫入並發布atomarna事件(本地事務),收件人通過idempotency-key處理。
7)閱讀「不老化X」(RNOT)
技術人員:- LSN/GTID門:客戶端傳輸最小版本(來自記錄響應),路由器/代理路由到趕上LSN ≥ X的副本,否則發送到領導者。
- Time-bound:「不要老化2秒」是沒有版本的簡單SLA。
- Session pinning:錄制N秒後,我們只閱讀領導者(Read-Your-Writes)。
8)更改流和緩存匹配
CDC →事件總線(Kafka/Pulsar)→消費者(緩存,索引,店面)。
緩存殘疾:拓撲「invalidate:{ns}:{id}」;idempotent處理。
Rebuild/Backfill:在同步時,從事件日誌中重新設置投影。
9)傳奇與補償(服務間交易)
在EC世界中,長壽操作分為具有補償作用的步驟:- 編排:協調員調用步驟及其補償。
- 編舞:步驟響應事件並自行發布以下內容。
不變量(示例):「平衡≥ 0」-在步長邊界上檢查+拒絕時的補償。
10)多區域與網絡分離
本地write, async-replicate:寫入本地區域+交付給其他(EC)。
Geo-fencing:數據被粘貼到區域(潛伏率低,沖突更少)。
CP數據的法定數據庫(Raft);緩存/店面-AP/EC。
Split-brain計劃:當通信丟失時,區域將繼續在域限制(寫入設置,配額)內運行,然後是重新連接。
11)可觀察性和SLO
度量標準:- Replica lag: 時間/LSN距離/疏遠(p50/p95/p99)。
- Staleness:超過閾值的響應比例(例如>2s或LSN
- 沖突率:沖突頻率和成功交易。
- Convergence time:復制副本在峰值之後的收斂時間。
- Reconcile backlog:滯後部分的數量/時間。
- RPO/RTO按數據類別(CP/AP)。
- Lag>目標,沖突增加,「長」不相容窗口。
12)在EC下設計數據電路
每個條目中的顯式版本/向量(「version」,「vc」列)。
用於臨界不變量(平衡,權重)的僅附錄日誌。
事件標識符(snowflake/ULID)用於順序和重復數據消除。
具有可交換性質(計數器,集合)的字段→ CRDT的候選字段。
API設計:帶有if-match/etag的PUT,帶有precondition的PATCH。
13)存儲和閱讀模式
閱讀模型/CQRS:寫入「源」,從投影讀取(可能滯後→顯示「更新」……)。
Stale-OK路線(目錄/磁帶)vs Strict(錢包/限制)。
查詢中的sticky/Bounded樣式標誌(標題「x-read-consistency」)。
14)實施清單(0-45天)
0-10天
分類數據:CP關鍵(金錢,訂單)vs EU/stale-OK(目錄,搜索索引)。
定義SLO steil(例如「不老化2s」),目標瀉藥。
在API中啟用對象轉換和idempotency-keys。
11-25天
引入CDC和outbox/inbox、緩存故障路由。
在記錄關鍵路徑上添加RNOT (LSN門)和session pinning。
實施最少一個merge策略(LWW/CRDT/域)和沖突日誌。
26-45天
自動化anti-entropy(支架/支架)和steel報告。
玩遊戲日:網絡分離,沖突激增,恢復。
在dashbords上可視化:lag, staleness, conflict rate, convergence。
15)反模式
關鍵不變量的盲人LWW(金錢/分數損失)。
缺少idempotency →後退手術。
「強大」模型→ p99尾巴過多,故障時易碎。
沒有RNOT/會話保證 → UX「閃爍」,用戶「看不到」他們的更改。
緩存和源的隱藏同步化(沒有CDC/殘疾)。
缺少reconcile/anti-entropy工具-「幾個世紀」的數據存在分歧。
16)成熟度量
Replica lag p95 ≤目標(例如,該地區內≤ 500 ms,≤ 2 s跨區域)。
Staleness SLO ≥ 99%的「嚴格」路線請求執行。
Conflict resolution success ≥ 99.9%,平均分辨率時間≤ 1分鐘。
高峰後的會議時間是幾分鐘,不是時鐘。
100%的「現金」交易由idempotency密鑰和outbox/inbox覆蓋。
17)食譜(snippets)
If-Match/ETag (HTTP)
PUT /profile/42
If-Match: "v17"
Body: { "email": "new@example.com" }
如果版本更改為「412 Precondition Failed」 →客戶端將解決沖突。
請求「不老化LSN」(偽)
x-min-lsn: 16/B373F8D8
路由器選擇帶有「replay_lsn ≥ x-min-lsn」的副本,否則為領導者。
CRDT G-Counter(想法)
每個地區都有自己的櫃臺;結果-所有組成部分的總和;復制-操作是可交換的。
18)結論
Eventual consistency不是質量權衡,而是有意識的合同:在某些地方,我們為速度和可用性支付新鮮度,但通過域策略和工具保護關鍵不變性。輸入版本、idempotency、RNOT/Session保修、CDC和防漏洞,測量lag/staleness/conflicts-您的分布式系統即使在故障和峰值負載下也能快速、穩定且可預測地收斂。