对强一致存储系统的思考

本文对强一致存储系统进行思辨: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 研究讨论群

相关推荐
大模型微调Online5 分钟前
深度复盘:Qwen3-4B-Instruct-2507微调实战——打造“快思考、强执行”的 ReAct IoT Agent
java·后端·struts
Z.风止44 分钟前
Go-learning(1)
开发语言·笔记·后端·golang
光电大美美-见合八方中国芯1 小时前
【SOA仿真6】多层膜仿真计算
后端·restful
小马爱打代码1 小时前
Spring Boot:Sentinel 企业级熔断、降级与限流实战
spring boot·后端·sentinel
野犬寒鸦1 小时前
从零起步学习并发编程 || 第二章:多线程与死锁在项目中的应用示例
java·开发语言·数据库·后端·学习
没有bug.的程序员1 小时前
Spring Cloud Sentinel:熔断降级规则配置与分布式流量防线实战终极指南
java·分布式·后端·spring cloud·sentinel·熔断规则·分布式流量防线
JP-Destiny1 小时前
后端-RabbitMQ
后端·消息队列·rabbitmq·java-rabbitmq
李慕婉学姐1 小时前
【开题答辩过程】以《基于SpringBoot Vue的校园后勤管理系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
vue.js·spring boot·后端
咖啡啡不加糖1 小时前
Arthas 使用指南:Java 应用诊断利器
java·spring boot·后端
努力也学不会java1 小时前
【Spring Cloud】优雅实现远程调用-OpenFeign
java·人工智能·后端·spring·spring cloud