MySQL主从复制与读写分离实战指南

深入理解MySQL主从复制原理、配置步骤以及读写分离的实现方案,附完整配置示例

一、背景

在面对高并发读写场景时,单一数据库实例往往成为系统瓶颈。主从复制 + 读写分离是解决这一问题的经典方案,也是后端开发者进阶必须掌握的核心技能。

二、主从复制原理

2.1 核心概念

MySQL主从复制基于binlog日志实现,主要包含三个线程:

线程 作用 所在节点
Binlog Dump 读取binlog并发送给从库 主库
IO Thread 接收主库发送的binlog 从库
SQL Thread 重放relay log中的SQL 从库

2.2 复制流程

复制代码
主库: INSERT → binlog → Binlog Dump →──────→ IO Thread → relay log → SQL Thread → 从库
  1. 主库执行SQL,生成binlog
  2. Binlog Dump线程读取binlog,发送给从库
  3. 从库IO线程接收,写入relay log
  4. 从库SQL线程重放relay log中的SQL

2.3 复制模式

模式 特点 异步/同步
异步复制 主库不等待从库确认 异步
半同步复制 主库等待至少一个从库确认 半同步
全同步复制 主库等待所有从库确认 同步

三、实战配置

3.1 环境说明

复制代码
192.168.1.10  - 主库 (Master)
192.168.1.20  - 从库 (Slave)

3.2 主库配置

bash 复制代码
# /etc/mysql/my.cnf
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
sync_binlog = 1

3.3 创建复制账号

sql 复制代码
-- 主库执行
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

3.4 从库配置

bash 复制代码
# /etc/mysql/my.cnf
[mysqld]
server-id = 2
relay_log = /var/log/mysql/mysql-relay-bin
read_only = 1

3.5 启动复制

sql 复制代码
-- 从库执行
CHANGE MASTER TO
    MASTER_HOST='192.168.1.10',
    MASTER_USER='repl',
    MASTER_PASSWORD='repl_password',
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=154;

START SLAVE;
SHOW SLAVE STATUS\G;

关键检查点:

  • Slave_IO_Running: Yes
  • Slave_SQL_Running: Yes
  • Seconds_Behind_Master: 0

四、读写分离实现

4.1 方案对比

方案 优点 缺点 适用场景
应用层代理 无单点、性能好 需要修改代码 中大型项目
中间件代理 透明接入 有性能损耗 快速接入
数据库中间件 支持分库分表 配置复杂 超大规模

4.2 Spring Boot实现

java 复制代码
@Configuration
public class DataSourceConfig {
    
    @Autowired
    private DataSourceProperties properties;
    
    @Bean
    public DataSource dataSource() {
        AbstractRoutingDataSource routingDataSource = 
            new AbstractRoutingDataSource() {
                @Override
                protected Object determineCurrentLookupKey() {
                    return RoutingContext.isWrite() ? "master" : "slave";
                }
            };
        
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", createDataSource(properties.getMaster()));
        targetDataSources.put("slave", createDataSource(properties.getSlave()));
        
        routingDataSource.setTargetDataSources(targetDataSources);
        return routingDataSource;
    }
}

4.3 路由切粒

java 复制代码
public class RoutingContext {
    private static final ThreadLocal<Boolean> isWrite = new ThreadLocal<>();
    
    public static void setWrite(boolean write) {
        isWrite.set(write);
    }
    
    public static boolean isWrite() {
        return Boolean.TRUE.equals(isWrite.get());
    }
    
    public static void clear() {
        isWrite.remove();
    }
}

Service层使用:

java 复制代码
@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Transactional
    public void saveUser(User user) {
        RoutingContext.setWrite(true);
        userMapper.insert(user);
    }
    
    public User getUserById(Long id) {
        RoutingContext.setWrite(false);
        return userMapper.selectById(id);
    }
}

五、常见问题与解决方案

5.1 主从延迟

症状: 从库延迟超过100ms

排查:

sql 复制代码
SHOW SLAVE STATUS\G;
-- 查看 Seconds_Behind_Master

解决方案:

  • 开启并行复制:slave_parallel_workers > 0
  • 优化主库大事务:分批提交
  • 确认网络延迟

5.2 数据不一致

原因:

  • 主从切换未同步
  • 复制中断未处理
  • 双写导致

修复方案:

bash 复制代码
# 重新同步
mysqldump --master-data=2 -h master -u root -p > backup.sql
mysql -h slave -u root -p < backup.sql

5.3 relay log损坏

恢复步骤:

sql 复制代码
STOP SLAVE;
RESET SLAVE;
CHANGE MASTER TO ...;
START SLAVE;

六、总结

核心要点:

  1. 主从复制基于binlog实现,有异步、半同步、同步三种模式
  2. 配置时注意server-id唯一,row格式binlog更安全
  3. 读写分离通过数据源路由实现,需处理事务边界
  4. 监控主从延迟,设置告警阈值

进阶方向:

  • MGR(MySQL Group Replication)
  • Binlog Server架构
  • 分库分表中间件(ShardingSphere、MyCAT)
相关推荐
神仙别闹3 小时前
基于Java+MySQL实现(GUI)医院管理系统
java·mysql·oracle
土星碎冰机3 小时前
ai自学笔记(3.安卓篇,制作app
android·笔记·ai
随遇丿而安4 小时前
专题:Glide / Coil / Fresco,不是三种写法,而是三套图片加载思路
android
TO_WebNow5 小时前
MySQL 索引的相关知识
数据库·mysql
只可远观5 小时前
Android 自动埋点(页面打开 / 关闭 + 点击事件)完整方案
android·kotlin
还是鼠鼠5 小时前
AI掘金头条新闻系统 (Toutiao News)-获取新闻分类
后端·python·mysql·fastapi·web
无小道6 小时前
Mysql——操作篇
mysql·操作··
私人珍藏库6 小时前
【Android】小小最新AI--千变万化扮演任何角色--沉浸式互动
android·app·工具·软件·多功能
zh_xuan6 小时前
Android MVI架构
android·mvi
测试开发-学习笔记7 小时前
Airtest+Poco快速上手
android·其他