RT ,最近在看 Paxos 、Raft 等共识算法,Paxos 没怎么看明白,Raft 看了整个流程,相较于 Paxos 好理解许多;有些疑问想要请教下 V 友们:我了解过 mysql 的副本同步机制,mysql 通过 binlog 来完成副本同步,为了保证 redolog 和 binlog 不发生一致性问题,还专门做了两段式提交:阶段一:主库写 redolog 但不提交;阶段二:主库写 binlog ,然后标记相关 redolog 为提交状态当且仅当 binlog 写成功时,redolog 里相关改动才算提交,这样可以保证多副本最终一定会按照 binlog 可靠的达成共识(一致?)在这个过程中,mysql 既没有实现 Paxos ,也没有依赖 Raft ,最终还是达成了多副本的共识(一致?),那为什么还专门提出来 Paxos 这类复杂的共识算法来完成多副本一致性呢?PS:在此期间还看到有人纠正:共识和一致不是一回事;但我理解共识算法的目的也是为了多副本就一份数据达成一致吧?所以一致性还是最终的目的,总之我被绕晕了😭

我只看过 raft ,mysql 不太了解。我觉得可能比较关键的点是,提供了什么样的一致性。比如 raft 提供了线性一致性保证( linearizability ),mysql 是否提供了相同的一致性,或是说只是提供了一个很模糊的最终一致性( eventual consistency )?另外提一点,这里的一致性指多个 replica 之间读写的一些保证,与事务( ACID )里的一致性是不同的概念

共识和一致确实不是同一回事。lz 可以看看 design data intensive application 这本书,里面有专门的章节介绍一致性( consistency )和共识( consensus ) dataintensive.net/

binlog 达成不了强一致性

  1. Paxos 和 Raft 不是唯二的共识算法2. Paxos 性能太低了,一般只用来管理 group membership, 然后根据 group membership 退化到主从复制来处理数据。zookeeper 就是这样做的。3. MySQL 能保证一致性的是 group replication, 它的 group membership 确实依赖共识算法来管理: dev.mysql.com/blog-archive/the-king-is-dead-long-live-the-king-our-homegrown-paxos-based-consensus/

我个人不太喜欢 binlog 同步,任何对数据库的小变动,都往这文件里写。我们服务器是老式硬盘,一直高强度写,有很大损耗的。任何方法都有一定局限性,写个同步算法,也可以有 3 ~ 4 种完全不同的思路。

mysql 没法选主啊 , 主就是固定的

paxos 和 raft 算法可以实现强一致性,容易理解就是复制状态机,所有的节点有相同的输入和输入顺序,只要大多数节点存活就能正常工作(更严谨是说法要满足共识算法的大多数节点以及大多数节点的状态),最原始的 paxos 算法里任何节点都可以提交 log ,但是这样效率太低,后来的共识算法都改为只有一个节点提交 log ,这个节点是可以通过算法选举出来的。binlog 是预先配置好的主+多个备,一旦主故障后,备是不能写入的,否则会导致数据和主不一致。

双向复制的时候,怎么保证 binlog 的一致?应该听谁的?

binlog 那是依赖一个主多个从, 当你集群有多个主和多个从节点, 要想达到一致性就不能靠这个了。mysql 集群 如果要允许多个主多个从 可以写入并达到一致性,就要依赖 paxos ,raft 。不同的公司都有一些实现,比如 facebook 的论文中就有通过 raft 来做一致性

engineering.fb.com/2023/05/16/data-infrastructure/mysql-raft-meta/可以看看这篇文章

你想想,主库挂了会怎样

存在 Leader 选举,才会用 Raft Paxos 这些东西。比如一开始有三个内容一样的副本(其中一个为 Leader ),修改内容的时候去 Leader 修改,然后同步到其他副本,如果 Leader 挂了,Raft 这时候就可以重新选举了,说白了他就是选举话事人的。MySQL 通过二阶段提交保证 binlog 和 redolog 的一致性,我觉得单靠这个也不能保证,比如阶段二中 binlog 刷盘之后,标记 redolog 提交状态之前挂了,这个时候 binlog 事务是提交的,redolog 中事务状态是未提交的,这个时候需要 mysql 启动的时候进行崩溃恢复,可以通过 binlog 判断出事务已经提交了,然后把 redolog 的事务标记为提交,这样就保证一致了。所以我觉得他们都属于共识算法,binlog 和 redlog 通过崩溃恢复达成了某个事务是否提交的共识,这个实现我觉得没有 Raft 这种更具有通用性,他只负责当前多副本只有一个老大,其他全部老老实实同步数据就行。

保证了主库 binlog 和 redo 一致不代表可以保证集群的状态一致性,同步 binlog 最多只能保证最终一致性,强一致性需要分布式事务去支持。

binlog 能用的前提是 MySQL 一直在跑,master 能一直活着负责做决定,其他节点只管跟随这不叫“分布式共识”

如果向 master 内写了 x=1, 写成功之后 master 挂了(其它节点, 拿不到最新的 binlog). 这时候从其它节点读 x, 能读到 1 还是之前的值 ?raft 能提供这种线性一致性的保证

可是共识算法中不也是 leader 负责做决定,Follower 跟随吗?唯一的区别是 leader 身份可切换

共识算法是为了可用性, 服务器节点存在三个角色 :leader 、follower 、candidate主从模式中是只有主节点可以写入的。

可是 raft 也保证不了完全的强一致吧?比如:leader 写了一个数据,此时同步到 Follower ,「多半」 Follower 响应 leader 后 leader 将此信息传给客户端,告知客户端已经写成功,但如果此时客户端读这个数据的时候正好读到了还未将此数据标记为 commited 状态的那个 Follower 节点(「多半」意味着总会有落后的 Follower ),这不就造成读写不一致了吗?我看过 Quorum 规则,说客户端每次可以读半数以上的节点,以确保至少有一个节点可以读到最新的值,但这对于一个客户端来说操作似乎又太重了(一次请求那么多个节点显然不合适),就很晕😓

raft 协议只解决共识,不解决一致。而你的这个问题是一致问题,而不是共识问题。

#18 据我了解,在 Raft 协议中,client 的读写都是发生在 leader 的,不像 ZooKeeper 。MIT 6.824 课程有讲。

想强一致就 follower 转发 leader ,想一定程度牺牲一致性来换取性能和可用性就 follower read ,总是有取舍的。

你搞错了,Raft 读数据走 leader 即提供全局 linearizable read ,怎么可能不解决 data consistency ?只是想要线性一致性读必须走 leader ,这对于分布式系统的服务可用性和性能是个头疼的问题,所以即便是采用了 Raft 作为 data replication 共识算法的分布式数据系统一样要提供 follower read 提供给用户,典型如 CRDB 和 yugabyteDB

MySQL 的这种做法不就是典型的 2PC ? 2PC 的缺陷不想在这里赘述了,几个知名的分布式数据系统( Spanner ,CRDB ,yugaByteDB )都采用了 paxos 或者 multi paxos 的方式来尽量解决 2PC 的缺陷,比如改进后的 2PC 不需要全局共识了而只需要 quorum 共识,以及 coordinator 可以根据 paxos 算法自动 failover ,这都是很大的改进了。

但是 raft 读数据也可以不走 leader 不是么

C A P 你是一点都不看啊

Raft source paper 可没让走 follower ,论文里就是让走 leader 可提供线性一致性读,后续的各类系统实现的时候走 follower 显然是为了性能的妥协,不能怪到 Raft 算法本身上去

现在存算分离的数据库方案成熟了么,感觉可以直接规避掉这一大堆麻烦事情

我理解 CAP 指的是在实现分布式一致性遇到网络分区( P )时的取舍方案( C or A ),而 Raft 协议是一种保证多副本共识而最终达到多副本强一致的策略,它们都是单独的理论,但在做工程实现时需要一起考虑:比如我有一个分布式系统通过 Raft 实现节点间的强一致,正常情况下,它确实是强一致的,而且运行的很好,但当发生网络分区时我需要结合 CAP 理论在可用性和一致性之间作取舍,如果要舍弃可用性,那就分区期间为了保证一致性让整个系统不可用(具体表现为客户端无法读或写),如果要舍弃强一致性,那就在分区期间也允许读写操作,但后果就是多节点间因为分区导致多 leader 写或单 leader 写的内容无法同步到没有 leader 的分区节点,导致各分区间的数据不一致。额。。只是个人理解,不知道对不对,CAP 和 Raft 都是我最近在研究的东西,感觉都很抽象😭

成熟。但是分离以后存储也得是分布式的吧?分布式存储一样需要解决一致性的问题。没有规避掉这些麻烦事情,只是这些麻烦的事情交给了更底层去做。

Mysql 依赖于单个主库来处理所有写操作,如果主库宕机,切换到从库作为新的主库,这个过程中可能会面临短暂的服务不可用,或者数据延迟问题。而 Paxos 和 Raft 就提供了对分布式而言更通用、更强大的算法,能够帮助设计和实现高可用、高一致性的分布式系统。

2PC 几个回复写得有点问题, mysql 实现 2pc 不是 binlog 和 relog 达成共识,而是 XA 事务。XA 事务在很多数据库中是有实现。

raft 算法演示,非常清晰了 code.bqrdh.com/alg/raft/

6.824 pdos.csail.mit.edu/6.824/schedule.html

谢谢提醒,我理解确实有点问题,把 XA 和崩溃恢复混在一起理解了。

CAP 理论不用太纠结现在很多人批斗这篇论文,因为说的太绝对了。况且分布式的东西你能舍弃 A 吗,共识算法算是保证了部分 A 半数可用,在这种情况下保证一致性。而你一开始提到 Mysql 同步机制,这哪里算是一致性,你这不就是勉强搞了个复制算法吗,同步、半同步、全同步这些东西(个人感觉共识协议是半同步的进化版本)。只能算是做了共识算法的一部分

存算分离和共识完全是不同维度上的事

  1. mysql 副本同步机制,也就是复制机制。2. 比如有 1 主 3 从( A ,B ,C ,D ),如果 mysql 挂了切主,谁当主谁当从,都要达成共识,这是共识算法。3. 最后 A ,B ,C ,D 数据是不是相同,延迟多少,一致成什么效果,才叫一致性。

不要编造名词,或者虚构理论。“既然 mysql 可以靠 binlog 达成多副本共识”,这是谁告诉你的呢。。。

这倒是没错,不过现在的实现倒是都提供了非 leader 读。反正也没人按照原始论文来实现算法,都是改了又改的。