📅 学习日期:2025年10月10日
学习时长:1.5小时
🎯 学习方式:苏格拉底式深度思考
📝 博客性质:真实学习过程记录(含思考+疑问+纠正)


📖 前言

这是MySQL高级特性学习的下篇,接续上篇的count函数、数据类型选择和分库分表基础。

本篇重点:

  • 分库分表进阶(一致性Hash深度理解)
  • 主从复制原理与实战
  • 读写分离架构设计
  • 生产环境容错方案

继续记录真实的学习过程,包括我的疑问、错误理解和最终的顿悟。

在这里插入图片描述

📑 目录

  1. 分库分表进阶:扩容难题
  2. 一致性Hash深度理解
  3. 主从复制核心原理
  4. 读写分离实战设计
  5. 生产环境容错方案
  6. 总结与反思

📊 第一部分:分库分表进阶 - 扩容难题

场景回顾

在上篇中,我学习了按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 logInnoDB引擎层崩溃恢复物理日志
binlogMySQL 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%+命中率
  • 从库集群:负载均衡
  • 主库降级:承担少量降级流量

监控告警

  1. 从库同步延迟 > 5秒
  2. Slave_SQL_Running: No(紧急)
  3. 降级主库请求 > 10%
  4. Redis命中率 < 80%

性能提升

单机:QPS 15000,CPU 90%,响应50ms
优化后:CPU主库60%从库30%,响应5ms(Redis)/15ms(从库)
提升:10倍+

📚 总结与反思

核心知识点

  1. 一致性Hash:扩容只迁移25%数据
  2. binlog vs redo log:Server层vs引擎层,复制vs恢复
  3. 主从复制:binlog→IO线程→relay log→SQL线程
  4. 读写分离:三层防护(Redis+从库+主库)

我的成长

  • 理清概念(分库分表vs主从复制)
  • 系统设计思维(层层防护)
  • 错误价值(binlog理解纠正)

面试准备

  1. 一致性Hash原理和优势
  2. binlog和redo log区别
  3. 主从复制流程
  4. 主从延迟解决方案
  5. read-only后还能同步吗

📊 Mermaid流程图

主从复制流程

应用 主库 Binlog 从库IO线程 Relay Log 从库SQL线程 从库表 INSERT数据 写表+写redo log 记录binlog 返回成功 读binlog 写relay log 读relay log 重放SQL 应用 主库 Binlog 从库IO线程 Relay Log 从库SQL线程 从库表

读写分离架构

同步
同步
命中
未命中
应用
路由层
主库
从库1
从库2
Redis
返回

三层降级

命中
未命中
成功
失败
成功
失败
查询
Redis
返回
从库
返回
主库
返回
异常

📝 学习笔记 - 2025年10月10日
苏格拉底式深度思考 | MySQL高级特性 | 面试+实战准备
记录真实学习过程:疑问→思考→纠正→顿悟

✨ 晚上实战:搭建1主2从环境!

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐