对强一致存储系统的思考

本文对强一致存储系统进行思辨:Paxos/Raft带来了什么?又失去了什么?我们真的需要强一致性存储系统吗?我们业务对一致性要求没到强一致的地步,真的需要Paxos/Raft驱动设计存储系统吗?

我想用PolarDB-X 话题讨论|分布式数据库,挂掉两台机器会发生什么这篇引出本文。在阿里PolarDB公众号中,作者罗列了主备架构的各种痛点,得出了一些结论:

  • 所谓一致性和可用性"兼顾"的主备方案,实际上是"兼不顾"。现代分布式数据库,解决了传统数据库主备结构的容灾问题。
  • 选择Paxos/Raft协议,每份数据会存在三个副本,并且能够保证在一个副本挂掉的情况下,不影响可用性,并且不会出现任何一致性问题(脑裂、丢数据、丢更新等)。在这个时代,但凡数据有一定的重要性,都不应该选择主备架构的产品。
  • 最后(其实这才是作者重点)通过概率算出随意分布的三副本挂两台丢数据的风险,引出CopySet算法。

我首先尝试"反驳"作者过于绝对的结论,并进一步思考,我们业务对一致性要求没到强一致的地步,真的需要Paxos/Raft驱动设计存储系统吗? 甚至抛出一个面试问题:当存储系统使用了Raft/Paxos协议,是否意味着该系统就是强一致系统?如果是,无脑使用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,将WAL分离到独立集群,必要时,补齐备机wal,无忌切换宕机。有意思的是,应该如何确保wal集群的可用性?

多主模型

多主模型好处显而易见,没有单主模型带来的切换不可用时间。例如字节Abase2 主要通过多主技术实现系统高可用目标。在多主模式下,分片的任一副本都可以接受和处理读写请求,以确保分片只要有任一副本存活,即可对外提供服务。

多主的问题是需要众多技术和补丁,2008年Dynamo论文展示了极致高可用的系统是如何用众多补丁设计架构。例如Abase2使用NWR模型实现可调一致性,使用Anti-Entropy检测对比分片差异,注意这是每个副本在内存缓存replicaLog向量[seqno1,seqno2...seqnoN],并发向其他副本拉齐缺失的日志,以逐步推进seqno前进。注意这里缺失的原因是NWR模型中N<W,即部分副本写入成果就算成功(所以需要补数据)。与 DynamoDB、Cassandra 等通过扫描引擎层构建 merkle tree 来完成一致性检测相比,Abase2似乎只关注写入时wal的一致性。尽管做到了这些,Abase2还是会产生非幂等操作冲突的问题,进而需要引入基于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)。

回到刚开始的问题,使用Raft驱动设计存储,是否我们就(免费)得到了强一致的读系统?答案是否定的, 我们在Raft读数据是,通常会选择经济的leader lease模型,下图中,若系统发生了网络分区,leader无法继续续租,则认为可能发生了脑裂,此时我们有两个选择,立即返回失败(因为无法保证线性一致性)或者直接返回数据(可能发生数据回绕)。

double logging?

double logging?使用raft base系统时,是否会导致既写raft wal,又写了一份存储引擎wal,额外增加了开销?别开玩笑了,将两个日志合并,关闭后者是基操了。

总结

raft/paxos复制协议只是帮助完成了副本间数据的同步,复制协议规约了一种游戏规则,让开发者方便获得一致性,在基于Raft log index,可以简化做很多扩容。而主备系统也不是无可救药的毒药,加上各种补丁,可能有不错的收益。下文看到,越来越多公司在用上了raft+rocksdb架构,填补内存型redis成本高昂与性能均衡间的空隙。

看遍各大互联网公司KV存储

字节

abase2:多主系统,多租户,系统是挺复杂,各种补丁,底层是rocksdb/terarkdb/等磁盘存储。

ByteKV:Raft base系统,感觉比较优雅,支持SQL,底层是rocksdb磁盘存储。

美团

Squirrel:内存型Redis,优化了各种扩缩容技术,跨地域容灾,大改RDB持久化逻辑。

Cellar: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实验室,进rocksdb 研究讨论群

相关推荐
喵了个Code4 分钟前
Spring Boot 3 + Spring Security + OAuth2 + Gateway企业级认证授权平台实现
后端
开心猴爷9 分钟前
除了 Perfdog,如何在 Windows 环境中完成 iOS App 的性能测试工作
后端
桦说编程1 小时前
简单方法实现子任务耗时统计
java·后端·监控
盖世英雄酱581361 小时前
物品超领取损失1万事故复盘(一)
java·后端
凌览1 小时前
别再死磕 Nginx!http-proxy-middleware 低配置起飞
前端·后端
拾玖不会code1 小时前
简单分表场景下的业务发散思考:分表如何保证丝滑?
后端
CryptoRzz1 小时前
印度尼西亚(IDX)股票数据对接开发
java·后端·websocket·web3·区块链
咕白m6252 小时前
通过 C# 快速生成二维码 (QR code)
后端·.net
踏浪无痕2 小时前
架构师如何学习 AI:三个月掌握核心能力的务实路径
人工智能·后端·程序员
小毅&Nora2 小时前
【后端】【SpringBoot】① 源码解析:从启动到优雅关闭
spring boot·后端·优雅关闭