Skip to main content
主从复制、读写分离、分库分表。

主从复制

原理

┌─────────────┐                    ┌─────────────┐
│   Master    │                    │    Slave    │
│  ┌───────┐  │     ① binlog      │  ┌───────┐  │
│  │ binlog│──┼────────────────→──┼──│IO线程 │  │
│  └───────┘  │                    │  └───┬───┘  │
└─────────────┘                    │      ↓      │
                                   │  ┌───────┐  │
                                   │  │relay  │  │
                                   │  │ log   │  │
                                   │  └───┬───┘  │
                                   │      ↓      │
                                   │  ┌───────┐  │
                                   │  │SQL线程│  │
                                   │  └───────┘  │
                                   └─────────────┘
三步流程:
  1. Master 将数据变更写入 binlog
  2. Slave 的 IO 线程读取 Master 的 binlog,写入 relay log
  3. Slave 的 SQL 线程执行 relay log 中的事件

配置步骤

Master 配置
# my.cnf
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW
-- 创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

-- 查看 Master 状态
SHOW MASTER STATUS;
Slave 配置
# my.cnf
[mysqld]
server-id = 2
relay-log = mysql-relay
read_only = 1
-- 配置主从关系
CHANGE MASTER TO
    MASTER_HOST = '192.168.1.100',
    MASTER_USER = 'repl',
    MASTER_PASSWORD = 'password',
    MASTER_LOG_FILE = 'mysql-bin.000001',
    MASTER_LOG_POS = 154;

-- 启动复制
START SLAVE;

-- 查看状态
SHOW SLAVE STATUS\G

复制模式

模式说明特点
异步默认模式,Master 不等 Slave性能好,可能丢数据
半同步至少一个 Slave 确认折中
全同步所有 Slave 确认性能差,不推荐
半同步复制
-- Master 安装插件
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;

-- Slave 安装插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

主从延迟

原因:
  • 从库机器性能差
  • 大事务
  • 从库压力大
解决方案:
  • 提升从库配置
  • 拆分大事务
  • 多个从库分担压力
  • 并行复制
-- 开启并行复制(MySQL 5.7+)
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
SET GLOBAL slave_parallel_workers = 8;

读写分离

原理

                    ┌─────────────┐
                    │   应用程序   │
                    └──────┬──────┘

                    ┌──────┴──────┐
                    │   中间件    │
                    └──────┬──────┘
              ┌────────────┼────────────┐
              ↓            ↓            ↓
        ┌─────────┐  ┌─────────┐  ┌─────────┐
        │ Master  │  │ Slave1  │  │ Slave2  │
        │  (写)   │  │  (读)   │  │  (读)   │
        └─────────┘  └─────────┘  └─────────┘

实现方式

方式说明代表产品
代码层在代码中判断读写动态数据源
中间件独立代理层MyCat, ShardingSphere
驱动层MySQL Connector 层mysql-connector-j

代码实现

// Spring Boot 动态数据源示例
@Configuration
public class DataSourceConfig {
    
    @Bean
    public DataSource dynamicDataSource() {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setDefaultTargetDataSource(masterDataSource());
        
        Map<Object, Object> dataSources = new HashMap<>();
        dataSources.put("master", masterDataSource());
        dataSources.put("slave", slaveDataSource());
        dataSource.setTargetDataSources(dataSources);
        
        return dataSource;
    }
}

// 使用注解切换
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnly {}

@Aspect
@Component
public class DataSourceAspect {
    
    @Before("@annotation(ReadOnly)")
    public void switchToSlave() {
        DynamicDataSourceContextHolder.set("slave");
    }
    
    @After("@annotation(ReadOnly)")
    public void restore() {
        DynamicDataSourceContextHolder.clear();
    }
}

注意事项

问题解决方案
主从延迟强制读主库、缓存
事务问题事务内全部走主库
数据一致性关键查询走主库

分库分表

何时分库分表

指标阈值
单表数据量> 500万 ~ 1000万
单库数据量> 5000万
并发连接数> 单库承受能力

拆分策略

垂直拆分 按业务拆分:
用户库          订单库          商品库
├── user       ├── orders      ├── product
├── user_ext   ├── order_item  ├── category
└── address    └── payment     └── inventory
水平拆分 按规则拆分:
user_0          user_1          user_2
├── id 0-999    ├── id 1000-1999├── id 2000-2999

分片策略

策略说明优缺点
范围分片按 ID 范围简单,热点问题
Hash 分片按 ID 取模均匀,扩容复杂
时间分片按时间适合日志
一致性Hash虚拟节点扩容平滑

ShardingSphere 示例

# application.yml
spring:
  shardingsphere:
    datasource:
      names: ds0, ds1
      ds0:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db0
        username: root
        password: 123456
      ds1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db1
        username: root
        password: 123456
    
    rules:
      sharding:
        tables:
          user:
            actual-data-nodes: ds$->{0..1}.user_$->{0..1}
            database-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: database-inline
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: table-inline
        
        sharding-algorithms:
          database-inline:
            type: INLINE
            props:
              algorithm-expression: ds$->{id % 2}
          table-inline:
            type: INLINE
            props:
              algorithm-expression: user_$->{id % 2}

分库分表问题

问题解决方案
跨库 JOIN避免,或使用中间件
跨库事务分布式事务、最终一致性
全局 ID雪花算法、UUID、号段模式
跨库分页归并排序、二次查询
数据迁移双写、增量同步

全局 ID 方案

方案优点缺点
UUID简单无序,索引效率低
雪花算法趋势递增,高性能时钟回拨问题
号段模式数据库生成依赖数据库
Redis高性能依赖 Redis
雪花算法结构
0 | 0000000000 0000000000 0000000000 0000000000 0 | 00000 | 00000 | 0000000000 00
  |←───────────────── 41位时间戳 ────────────────→|←5位→|←5位→|←──── 12位序列号 ─→|
                                                  机器ID 数据中心

高可用方案

MHA(Master High Availability)

                 ┌─────────────┐
                 │ MHA Manager │
                 └──────┬──────┘
          ┌─────────────┼─────────────┐
          ↓             ↓             ↓
    ┌─────────┐   ┌─────────┐   ┌─────────┐
    │ Master  │   │ Slave1  │   │ Slave2  │
    └─────────┘   └─────────┘   └─────────┘
功能:
  • 自动故障转移
  • 数据补偿(从宕机 Master 拉取 binlog)

MGR(MySQL Group Replication)

MySQL 官方的高可用方案,基于 Paxos 协议。 模式:
  • 单主模式:自动选主
  • 多主模式:任意节点可写

其他方案

方案说明
Keepalived + VIP简单,故障切换慢
OrchestratorGitHub 开源
VitessYouTube 开源,云原生
TiDB分布式 NewSQL