从 Raft 到 MySQL:我是怎么推导出半同步复制原理的

起因

熟悉我的朋友都知道,我从去年 9 月开始就对分布式系统比较沉迷,被那些协议的设计思想深深吸引。

最近偶然看到一个知识盲区:MySQL 主从复制。看到三种复制方式:同步复制、异步复制、半同步复制。

看到异步复制的时候,我脑子里立刻蹦出来:这不就是 Redis 默认的复制方式吗?快,但是可能丢数据。

看到同步复制的时候,我又想到了 Redis------Redis 也有同步复制,同样会慢,等所有从库都写完才返回,谁受得了。

(这里我脑子里其实还闪过另一个念头:Redis 的同步复制会数据不一致。但我没深究 MySQL 会不会也一样,因为我对半同步更感兴趣,直接打住了。后来才发现,MySQL 的同步复制其实演进过------早期版本是先提交事务再等待确认,确实也会不一致;到了 5.x 版本才调整顺序,变成先等待从库确认再提交事务,这才是真正的同步。)

然后看到半同步复制------介于两者之间的方案。我一看描述:

执行完事务后,不立刻返回,也不等所有从库完成,而是等至少一个从库确认收到事件后,再返回给客户端。

到这里,我的分布式系统DNA动了。

我的思考过程

第一步:主从的目的是什么?

主从架构存在的意义,说白了就是:主挂了,从能上位。

如果没有这个前提,搞主从干嘛?读写分离而已的话,异步复制就够了。

所以主从的核心价值 = 高可用 = 主挂了能切换。

第二步:主挂了怎么切换?

既然要从库上位,那多个从库选谁?

这个问题我虽然忘了具体是 Raft 还是 Paxos 还是哪个协议讲的,但有一个原则我记得很清楚:

选数据最新的那个当主。

为什么?因为数据最新的节点,丢失的事务最少,新主和旧主之间的数据差距最小。

第三步:那半同步复制在干嘛?

半同步复制要求至少一个从库确认收到事件,主库才返回成功。

这不就是在保证:任何时候,至少有一个从库的数据是接近主库的吗?

这样的话,主挂了的时候,至少有一个从库的数据是最新的(或者接近最新),选它当新主,数据丢失最少。

第四步:串起来

所以我的推导链路是这样的:

复制代码
主从的目的 → 主挂了从能上位
      ↓
多个从库选谁?→ 选数据最新的
      ↓
怎么保证有从库数据是最新的?→ 半同步复制
      ↓
至少一个从库确认收到 → 随时可以选它当新主

我当时就觉得,MySQL 肯定也是这个思路。

验证:我的推测对不对?

去确认了一下,结果如下:

对的部分

  • 故障转移时,确实会选择数据最新的从库当新主
  • 半同步复制确实是为了减少主库宕机时的数据丢失
  • "选最新的"这个原则,不管在 Raft、Paxos 还是 MySQL 里,都是通用的

需要修正的部分

半同步复制本身不负责选主

它只负责一件事:保证数据至少存在于两个地方(主库 + 至少一个从库)。

选主这件事,是额外的故障转移组件来做的,比如:

  • MHA(Master High Availability)
  • Orchestrator
  • MySQL Group Replication(MGR)

所以准确地说:

机制 职责
半同步复制 数据保护,防丢数据
故障转移组件 检测主库故障,选最新的从库当新主

两者是配合关系,不是同一个东西。

总结:迁移学习是真的有用

说实话,Raft 的具体细节我早就忘了,选举流程、日志复制、心跳机制......大部分都记不清了。

但有一个东西留下来了:选主要选数据最新的

这个原则变成了我的思维工具,看到 MySQL 半同步复制的时候,自动就调用了出来。

所以我觉得,学一个东西最好的检验方式,不是看你能背多少,而是看它能不能帮你理解另一个东西

相关推荐
环流_1 小时前
redis中list应用场景
数据库·redis·list
东风破1371 小时前
DM8达梦分布式计算数据库集群DPC安装部署学习记录
数据库·学习
難釋懷1 小时前
Redis网络模型-基于epoll的服务器端流程
网络·数据库·redis
这个DBA有点耶1 小时前
MySQL深分页优化:从LIMIT 1000000,10到毫秒级响应的三种写法
数据库·程序人生·mysql·性能优化·学习方法·dba·改行学it
凯瑟琳.奥古斯特2 小时前
页面置换算法详解与对比
开发语言·分布式·职场和发展
通往曙光的路上2 小时前
mysql3
数据库
阿坤带你走近大数据2 小时前
什么是 REDO LOG,它在 Oracle 数据库中的作用是什么?
数据库·oracle
东风破1372 小时前
DM8搭建同构(dm-dm)及异构数据库(dm-oracle,dm-mysql)的dblink
数据库·mysql·oracle
凭X而动2 小时前
postgresql18.1部署
数据库·postgresql