MySQL学习笔记10:MySQL高级特性深度学习(下)———主从复制、读写分离与生产实战
📅 学习日期:2025年10月10日
⏰ 学习时长:1.5小时
🎯 学习方式:苏格拉底式深度思考
📝 博客性质:真实学习过程记录(含思考+疑问+纠正)
📖 前言
这是MySQL高级特性学习的下篇,接续上篇的count函数、数据类型选择和分库分表基础。
本篇重点:
- 分库分表进阶(一致性Hash深度理解)
- 主从复制原理与实战
- 读写分离架构设计
- 生产环境容错方案
继续记录真实的学习过程,包括我的疑问、错误理解和最终的顿悟。

📑 目录
📊 第一部分:分库分表进阶 - 扩容难题
场景回顾
在上篇中,我学习了按user_id取模的分片方案:
4台服务器:
user_id % 4 = 0 → 服务器1
user_id % 4 = 1 → 服务器2
user_id % 4 = 2 → 服务器3
user_id % 4 = 3 → 服务器4
但业务继续增长,需要扩容到8台!
我遇到的扩容难题
需要改成:user_id % 8
我立即意识到问题:
user_id = 5:
原来:5 % 4 = 1 → 服务器2
现在:5 % 8 = 5 → 服务器6 ❌
需要迁移!
数据迁移量计算
我手动计算了16个用户(user_id 0-15)的迁移情况:
user_id 原位置(% 4) 新位置(% 8) 是否迁移
0 0 0 ✅ 不迁移
1 1 1 ✅ 不迁移
2 2 2 ✅ 不迁移
3 3 3 ✅ 不迁移
4 0 4 ❌ 迁移
5 1 5 ❌ 迁移
6 2 6 ❌ 迁移
7 3 7 ❌ 迁移
8 0 0 ✅ 不迁移
...
我的发现:16个用户中,8个需要迁移 = 50%!
50%迁移的影响
假设我的系统有:
- 3亿订单数据
- 每条订单1KB
- 总数据量:300GB
扩容需要迁移:150GB!
我的思考:
“迁移150GB数据,假设100MB/s的速度,需要25分钟。这25分钟内,服务还能正常运行吗?如果有新数据写入,写到哪里?”
这就引出了一致性Hash!
🔄 第二部分:一致性Hash深度理解
我的初步理解(有误)
最开始我以为和普通Hash表一样:“Hash一个key对应值,查找O(1)”
后来我意识到:一致性Hash和普通Hash表是完全不同的概念!
Hash环的概念
我的疑问: “什么是’环’?为什么会成环?”
Hash值范围:0 到 2^32-1(约43亿),首尾相连形成环。
关键理解: 环不是真实的物理环,是逻辑概念!就像钟表的12点就是0点。
服务器和数据映射
服务器Hash值(简化0-100):
服务器1 → hash("server1") % 100 = 25
服务器2 → hash("server2") % 100 = 50
服务器3 → hash("server3") % 100 = 75
服务器4 → hash("server4") % 100 = 0
查找规则:从数据Hash值顺时针找第一个服务器
示例:user_id=123
hash(123) % 100 = 30
从30顺时针找:30 → 50 → 找到服务器2
扩容只影响一部分数据
新增服务器5(hash=35)后:
环变成:0(服务器4) → 25(服务器1) → 35(服务器5) → 50(服务器2) → 75(服务器3)
数据分布变化:
0-24: 存在服务器4 ✅ 不变
25-34: 原在服务器1,现在还在服务器1 ✅ 不变
35-49: 原在服务器1,现在在服务器5 ❌ 需要迁移!
50-74: 存在服务器2 ✅ 不变
75-99: 存在服务器3 ✅ 不变
我的顿悟: 只有35-49这部分数据需要迁移!约25%!
Hash环容量问题
我的困惑: “2^32约43亿,但有100亿数据,存得下吗?”
理解纠正: Hash环不是存储空间!是路由规则!多条数据映射到相同Hash值 → 存储到同一服务器。
🔄 第三部分:主从复制核心原理
场景:单机压力
cpp-chat项目:QPS 15000(80%读、20%写),单机CPU 90%,快撑不住了。
我的想法: “80%读操作,能不能用多台服务器分担?但数据怎么一致?”
分库分表 vs 主从复制(重要区别)
我最初混淆了!
分库分表: 数据分散(user_id=1在库1,user_id=5在库2),应用层路由
主从复制: 数据完全相同(所有库都有所有数据),数据库层自动同步
redo log vs binlog(我理解错了!)
我的第一反应: “主从复制用redo log吧”
这是错的!应该是binlog!
| 日志类型 | 所属层次 | 作用 | 格式 |
|---|---|---|---|
| redo log | InnoDB引擎层 | 崩溃恢复 | 物理日志 |
| binlog | MySQL Server层 | 主从复制、归档 | 逻辑日志 |
崩溃恢复用redo log,主从复制用binlog!
主从复制完整流程
主库:
1. 执行SQL
2. 写入表
3. 写入redo log(保证持久性)
4. 记录binlog(给主从复制用)← 注意顺序!
5. 提交事务
为什么先写表后写binlog? 避免主库没数据但从库有数据的不一致!
从库两个线程:
IO线程: 连接主库 → 读binlog → 写relay log(中继日志)
SQL线程: 读relay log → 重放SQL → 更新表
为什么需要relay log? 解耦IO和SQL执行,安全、性能、可靠!
三种复制模式
我的推测: “主库写完,一个从库写完再返回”
实际:默认是异步复制!
1. 异步复制(默认): 主库写入 → 立即返回 → 后台同步(性能高但可能不一致)
2. 半同步复制: 主库写入 → 等1个从库确认 → 返回(相对安全)
3. 全同步复制: 等所有从库确认(性能差,很少用)
从库读写问题
我的疑问: “从库能写吗?”
两种"写":
- SQL线程重放(必须允许)✅
- 应用直接写(必须禁止)❌
生产配置:
read-only = 1
super-read-only = 1
复制线程不受影响 ✅
🎯 第四部分:读写分离实战设计
主从延迟问题
场景: 用户发消息 → 主库写入 → 立即查询从库 → 查不到!
原因: 从库压力大(既处理查询又同步数据)、大事务、网络延迟
cpp-chat完整方案
数据分类:
- 刚发消息:Redis(TTL 5分钟)
- 最近100条:Redis(TTL 1分钟,LRU)
- 历史消息:从库(不缓存)
写入流程(双写):
1. 写主库(持久化)
2. 同时写Redis(快速读取)
3. Redis失败不影响主流程
读取流程(三层降级):
第1层:Redis缓存
↓ 未命中
第2层:从库集群
↓ 失败
第3层:主库(最后保障)
🛡️ 第五部分:生产环境容错方案
三层防护
- Redis缓存:90%+命中率
- 从库集群:负载均衡
- 主库降级:承担少量降级流量
监控告警
- 从库同步延迟 > 5秒
- Slave_SQL_Running: No(紧急)
- 降级主库请求 > 10%
- Redis命中率 < 80%
性能提升
单机:QPS 15000,CPU 90%,响应50ms
优化后:CPU主库60%从库30%,响应5ms(Redis)/15ms(从库)
提升:10倍+
📚 总结与反思
核心知识点
- 一致性Hash:扩容只迁移25%数据
- binlog vs redo log:Server层vs引擎层,复制vs恢复
- 主从复制:binlog→IO线程→relay log→SQL线程
- 读写分离:三层防护(Redis+从库+主库)
我的成长
- 理清概念(分库分表vs主从复制)
- 系统设计思维(层层防护)
- 错误价值(binlog理解纠正)
面试准备
- 一致性Hash原理和优势
- binlog和redo log区别
- 主从复制流程
- 主从延迟解决方案
- read-only后还能同步吗
📊 Mermaid流程图
主从复制流程
读写分离架构
三层降级
📝 学习笔记 - 2025年10月10日
苏格拉底式深度思考 | MySQL高级特性 | 面试+实战准备
记录真实学习过程:疑问→思考→纠正→顿悟
✨ 晚上实战:搭建1主2从环境!
更多推荐


所有评论(0)