對強一致存儲系統的思考

對強一致存儲系統的思考

本文對強一致存儲系統進行思辨: Paxos/Raft 帶來了什麼?又失去了什麼?我們真的需要強一致性存儲系統嗎?我們業務對一致性要求沒到強一致的地步,真的需要 Paxos/Raft 驅動設計存儲系統嗎?

我想用 PolarDB-X 話題討論|分佈式數據庫,掛掉兩臺機器會發生什麼 這篇引出本文。在阿里 PolarDB 公衆號中,作者羅列了主備架構的各種痛點,得出了一些結論:

我首先嚐試 “反駁” 作者過於絕對的結論,並進一步思考,**我們業務對一致性要求沒到強一致的地步,真的需要 Paxos/Raft 驅動設計存儲系統嗎?**甚至拋出一個面試問題:當存儲系統使用了 Raft/Paxos 協議,是否意味着該系統就是強一致系統?

我先給出一個結論:系統使用了 Paxos 或者 Raft,並不意味着該系統就是強一致性系統,也不意味着客戶端 "免費" 地獲得了強一致性。Paxos 或者 Raft 只是副本間的複製協議,它規約了一種 (獲得一致性) 遊戲規則幫助架構師理清思路,解決可能會遇到的容災、腦裂、數據丟失等問題,而不是僅爲系統提供了強一致性保證(事實上要獲得強一致,開發者需要付出更多的努力呢)。

集羣典型架構

單主模型:

用戶讀寫 master,一般在控制面有 Router 對 Master/Slave 進行選舉,當 Router 發現 Master 有問題 (可能是網絡、進程 core、宕機) 即進行切換,並更新路由信息。

單主模型最大的問題是丟失更新,在 Master 寫入數據後,返回給客戶端後,Slave 切換後仍可能丟失更新。現象爲:寫入的數據永遠丟失了。單主模型切換爲了儘量保證一致性,切換前各種探測,通常在 3~5s 不可用。

進一步可能的選項是:寫時同步複製,即同時等 slave 寫完後再返回客戶端,衍生的問題是,slave 宕機時帶來的可用性問題。再進一步的優化是?我冒出一個想法: 模仿 neondb@Architecture decisions in Neon[1],將 WAL 分離到獨立集羣,必要時,補齊備機 wal,無忌切換宕機。有意思的是,應該如何確保 wal 集羣的可用性?

多主模型

多主模型好處顯而易見,沒有單主模型帶來的切換不可用時間。例如字節 Abase2 主要通過多主技術實現系統高可用目標。在多主模式下,分片的任一副本都可以接受和處理讀寫請求,以確保分片只要有任一副本存活,即可對外提供服務。

多主的問題是需要衆多技術和補丁,2008 年 Dynamo 論文 [2] 展示了極致高可用的系統是如何用衆多補丁設計架構。例如 Abase2 使用 NWR 模型實現可調一致性,使用 Anti-Entropy 檢測對比分片差異,注意這是每個副本在內存緩存 replicaLog 向量 [seqno1,seqno2...seqnoN],併發向其他副本拉齊缺失的日誌,以逐步推進 seqno 前進。這裏缺失 log 的原因是 NWR 模型中 N<W,即部分副本寫入成果就算成功(所以需要補數據) 導致。與 DynamoDB、Cassandra 等通過掃描引擎層構建 merkle tree 來完成一致性檢測相比,Abase2 似乎只關注寫入時 wal 的一致性。儘管做到了這些,Abase2 還是會產生非冪等操作衝突的問題(why?),進而需要引入基於 HLC 的操作的 CRDTs 技術解決衝突。

多主系統架構是複雜的,Dynamo 系統運維如此複雜已被 Amazon 拋棄。不知字節 Abase2 還好嗎。

Raft base 系統

網絡上關於 Raft 協議的討論真的多如牛毛,我也不打算在此討論 Raft 協議細節,而是想要回答:選擇了 Raft 協議,並不是立即擁有了強一致性系統。從未有人討論過如何將 Raft 降級一致性 (從而獲得更好的可用性):

Raft Leader+Learner:

如下圖,當我們使用一個 Raft Leader 再配合 Learner 節點 (不投票節點) 時,立即具備了與主備模式相同寫代價的架構,我稱之爲 What ever,don’t give a xxx 模型。數據愛丟就丟無所謂。同理上層需要做一個 learner 切換升成 Raft leader(有損)的控制面邏輯。

Raft witness

使用 witness 節點 (只投票不計算不存儲),可以讓 Raft base 系統成本降低到與主備模型相同 (almost)。

witness 讓多副本成本降低

回到剛開始的問題,使用 Raft 驅動設計存儲,是否我們就 (免費) 得到了強一致的系統?答案是否定的, 我們在 Raft 讀數據時,通常會選擇經濟的 leader lease 防止腦裂,下圖中,若系統發生了網絡分區,leader 無法繼續續租,則認爲可能發生了腦裂,此時我們有兩個選擇,立即返回失敗 (因爲無法保證線性一致性) 或者直接返回數據(可能發生數據迴繞)。後者提升了可用性,並退化到主備模型相同的一致性。

強一致讀模型與 what ever 模型腦裂

double logging?

raft base 系統是否會導致既寫 raft wal,又寫了一份存儲引擎 wal,額外增加了開銷?別開玩笑了,將兩個日誌合併,關閉後者是基操了。

總結

raft/paxos 複製協議只是幫助完成了副本間數據的同步,複製協議規約了一種可能獲得強一致性的遊戲規則。基於 Raft log index,可以簡化系統擴展設計。而主備系統也不是無可救藥的毒藥,加上各種補丁,可能有不錯的收益。下文看到,越來越多公司用上了 raft+rocksdb 架構,填補內存型 redis 成本高昂與性能 / 成本均衡間的空隙。

看遍各大互聯網公司 KV 存儲

字節

abase2[3]: 多主系統,多租戶,系統是挺複雜,各種補丁,底層是 rocksdb/terarkdb / 等磁盤存儲。

ByteKV[4]:Raft base 系統,感覺比較優雅,支持 SQL,底層是 rocksdb 磁盤存儲。

美團

Squirrel[5]: 內存型 Redis,優化了各種擴縮容技術,跨地域容災,大改 RDB 持久化邏輯。

Cellar[6]:Raft base 系統,底層是 rocksdb 磁盤存儲。

TIKV c++ 版: 據說是 tikv 的 C++ 重寫版。Raft base 系統,底層是 rocksdb 磁盤存儲。

阿里:

Tair: 應該是類似 Rocksdb 的 LSM 存儲。

騰訊:

Tendis: gossip 版 redis 集羣實現,底層是 rocksdb,已開源。

.....(還有非常多...)

小紅書

RedKV2: 改進版 gossip 版 redis 集羣實現,底層是 rocksdb。

B 站

Raft base 系統,底層是 rocksdb 磁盤存儲。

其他開源系統:

pika、kvrocks: 底層是 rocksdb 磁盤存儲。有看到兩位中國磁盤型 redis 做的最好開源系統在計劃做 Raft base 改造。希望未來 NOSQL-CN 會在 AxeDB 上實現出一套內存型 / 混合型 Raft base Redis。

引用鏈接

[1] Architecture decisions in Neon: https://neon.tech/blog/architecture-decisions-in-neon
[2] 論文: https://www.cnblogs.com/foxmailed/archive/2012/01/11/2318650.html
[3] abase2: https://www.51cto.com/article/709845.html
[4] ByteKV: https://zhuanlan.zhihu.com/p/145645524
[5] Squirrel: https://tech.meituan.com/2020/07/01/kv-squirrel-cellar.html
[6] Cellar: https://tech.meituan.com/2020/07/01/kv-squirrel-cellar.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/JMIxa9MExcGWCIlfJELN0A