一、主从复制概述
主从复制(Master-Slave Replication)是数据库高可用性和负载均衡的核心技术。通过将数据从主库复制到从库,实现读写分离,提升系统性能和可靠性。
二、主从复制原理
2.1 MySQL复制架构
MySQL主从复制基于二进制日志(Binary Log)实现:
graph TD
A[主库 Master] --> B[二进制日志 Binary Log]
B --> C[网络传输]
C --> D[从库 Slave]
D --> E[中继日志 Relay Log]
E --> F[SQL线程]
F --> G[从库数据]
A --> A1[写入操作]
A1 --> B
2.2 复制流程
sequenceDiagram
participant Master as 主库
participant Slave as 从库
participant IO as IO线程
participant SQL as SQL线程
Master->>Slave: 发送二进制日志
IO->>Master: 请求日志
Master-->>IO: 返回日志事件
IO->>Slave: 写入中继日志
SQL->>Slave: 读取中继日志
SQL->>Slave: 执行SQL语句
2.3 复制类型
| 复制类型 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 基于语句 | 记录SQL语句 | 日志量小 | 可能不一致 |
| 基于行 | 记录行变更 | 一致性好 | 日志量大 |
| 混合模式 | 自动选择 | 平衡优缺点 | 复杂 |
三、主从复制配置
3.1 主库配置
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
binlog_do_db = mydatabase
expire_logs_days = 7
3.2 从库配置
[mysqld]
server-id = 2
relay_log = /var/log/mysql/relay-bin.log
read_only = 1
3.3 启动复制
-- 主库创建复制用户
CREATE USER 'repl'@'slave_ip' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'slave_ip';
-- 从库配置复制
CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=107;
START SLAVE;
四、读写分离策略
4.1 读写分离架构
graph TD
A[应用程序] --> B{路由层}
B --> C[写入请求]
B --> D[读取请求]
C --> E[主库 Master]
D --> F[从库1 Slave1]
D --> G[从库2 Slave2]
D --> H[从库3 Slave3]
E --> I[复制]
I --> F
I --> G
I --> H
4.2 读写分离实现方式
应用层分离
在应用代码中实现读写分离:
public class DbRouter
{
private readonly DbConnection _master;
private readonly List<DbConnection> _slaves;
public DbConnection GetConnection(bool isWrite)
{
if (isWrite) return _master;
return _slaves[new Random().Next(_slaves.Count)];
}
}
中间件分离
使用数据库中间件实现读写分离:
// MyCat配置示例
<dataNode name="dn1" dataHost="localhost1" database="db1"/>
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1">
<writeHost host="hostM1" url="localhost:3306" user="root" password=""/>
<readHost host="hostS1" url="localhost:3307" user="root" password=""/>
<readHost host="hostS2" url="localhost:3308" user="root" password=""/>
</dataHost>
代理层分离
使用代理层实现读写分离:
# ProxySQL配置
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES
(1, 'master', 3306),
(2, 'slave1', 3306),
(2, 'slave2', 3306);
INSERT INTO mysql_replication_hostgroups (writer_hostgroup, reader_hostgroup) VALUES (1, 2);
五、主从延迟问题
5.1 延迟原因
- 网络延迟:主从之间网络传输耗时
- 从库负载:从库执行速度慢
- 事务大小:大事务导致延迟
- 并行度:单线程复制慢
5.2 延迟监控
-- 查看从库延迟
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master 表示延迟秒数
5.3 延迟解决方案
| 方案 | 原理 | 适用场景 |
|---|---|---|
| 并行复制 | 多线程并行执行 | 高并发写入 |
| 半同步复制 | 等待至少一个从库确认 | 高一致性要求 |
| 延迟容忍读写 | 允许一定延迟 | 非实时查询 |
| 强制读主库 | 关键数据读主库 | 强一致性查询 |
六、高可用性设计
6.1 自动故障转移
使用工具实现自动故障转移:
graph TD
A[主库故障] --> B{监控检测}
B --> C[触发故障转移]
C --> D[选择新主库]
D --> E[提升从库为主库]
E --> F[更新应用配置]
F --> G[恢复服务]
6.2 常用高可用工具
| 工具 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| MHA | 自动故障转移 | 维护复杂 | MySQL |
| Orchestrator | 可视化管理 | 依赖外部存储 | MySQL |
| Patroni | 支持多种数据库 | 配置复杂 | PostgreSQL |
| Keepalived | 简单高效 | 需要虚拟IP | 通用 |
七、主从复制最佳实践
7.1 定期备份
定期备份主库数据,防止数据丢失。
7.2 监控复制状态
实时监控从库复制状态,及时发现问题。
7.3 避免大事务
将大事务拆分为小事务,减少复制延迟。
7.4 从库只读
设置从库为只读模式,防止误写入。
7.5 多从库负载均衡
使用多个从库分担读压力,实现负载均衡。
八、总结
主从复制和读写分离是构建高可用、高性能数据库系统的核心技术。通过合理配置和监控,能够实现系统的水平扩展和故障自动恢复,满足数据密集型应用的需求。