MySQL主从复制是实现数据读写分离、降低主库压力的核心方案,将分析类任务对接到从库,再接入大数据处理引擎,就能在不影响线上业务的前提下完成数据实时分析。这种架构既保证了主库的事务处理能力,又能满足实时分析的业务需求。

MySQL主从复制基础原理
MySQL主从复制的核心流程分为三个步骤:主库将数据的变更记录到二进制日志(binlog)中,从库的I/O线程拉取主库的binlog并写入本地的中继日志(relay log),从库的SQL线程读取中继日志并重放,最终实现从库数据与主库同步。
主从复制的同步模式分为异步复制、半同步复制和全同步复制,实时分析场景通常选择异步复制,避免同步等待影响主库写入性能。如果需要更高的数据一致性,可以调整为半同步复制。
搭建MySQL主从复制环境
主库配置
首先修改主库的配置文件my.cnf,开启binlog并设置唯一server-id:
[mysqld] # 开启二进制日志 log-bin=mysql-bin # 设置server-id,主从库的id不能重复 server-id=1 # 需要同步的数据库,不设置则同步所有库 binlog-do-db=test_db # 忽略同步的数据库 binlog-ignore-db=mysql
重启主库后,创建用于从库同步的账号并授权:
-- 创建同步账号 CREATE USER 'repl_user'@'从库IP' IDENTIFIED BY 'repl_password'; -- 授予复制权限 GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'从库IP'; -- 刷新权限 FLUSH PRIVILEGES; -- 查看主库binlog状态,记录File和Position值 SHOW MASTER STATUS;
从库配置
修改从库的my.cnf配置文件,设置唯一的server-id:
[mysqld] # 设置从库唯一server-id server-id=2 # 开启中继日志 relay-log=relay-bin # 设置只读,避免从库被误写入 read-only=1
重启从库后,配置主库连接信息并启动复制:
-- 配置主库连接信息,替换为实际的主库IP、同步账号、binlog文件和位置 CHANGE MASTER TO MASTER_HOST='主库IP', MASTER_USER='repl_user', MASTER_PASSWORD='repl_password', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154; -- 启动从库复制 START SLAVE; -- 查看从库复制状态,确保Slave_IO_Running和Slave_SQL_Running都是Yes SHOW SLAVE STATUSG
从库接入大数据处理引擎实现实时分析
常见的实时大数据处理引擎有Flink、Spark Streaming等,这里以Flink为例说明从库接入的实现方式。Flink可以通过CDC(变更数据捕获)组件读取MySQL从库的binlog,实时获取增量数据进行分析。
环境准备
首先需要下载Flink对应的MySQL CDC连接器,将jar包放到Flink的lib目录下,然后启动Flink集群。
Flink实时读取从库数据示例
以下是Flink SQL读取MySQL从库binlog并做简单统计的代码示例:
import org.apache.flink.table.api.EnvironmentSettings;
import org.apache.flink.table.api.TableEnvironment;
public class MysqlSlaveCdcDemo {
public static void main(String[] args) {
// 创建Flink表环境,使用流式模式
EnvironmentSettings settings = EnvironmentSettings
.newInstance()
.inStreamingMode()
.build();
TableEnvironment tEnv = TableEnvironment.create(settings);
// 创建MySQL CDC源表,连接从库
String sourceDdl = "CREATE TABLE user_order (n" +
" id INT,n" +
" user_id INT,n" +
" order_amount DECIMAL(10, 2),n" +
" create_time TIMESTAMP(3),n" +
" PRIMARY KEY (id) NOT ENFORCEDn" +
") WITH (n" +
" 'connector' = 'mysql-cdc',n" +
" 'hostname' = '从库IP',n" +
" 'port' = '3306',n" +
" 'username' = '从库只读账号',n" +
" 'password' = '从库只读密码',n" +
" 'database-name' = 'test_db',n" +
" 'table-name' = 'order'n" +
")";
tEnv.executeSql(sourceDdl);
// 创建结果表,这里以控制台输出为例
String sinkDdl = "CREATE TABLE order_stat (n" +
" user_id INT,n" +
" total_amount DECIMAL(10, 2),n" +
" order_count BIGINT,n" +
" PRIMARY KEY (user_id) NOT ENFORCEDn" +
") WITH (n" +
" 'connector' = 'print'n" +
")";
tEnv.executeSql(sinkDdl);
// 执行统计逻辑,按用户统计订单总金额和订单数
String statSql = "INSERT INTO order_statn" +
"SELECT user_id, SUM(order_amount) as total_amount, COUNT(*) as order_countn" +
"FROM user_ordern" +
"GROUP BY user_id";
tEnv.executeSql(statSql);
}
}
注意事项
- 从库需要开启binlog,并且binlog格式设置为ROW,才能保证CDC组件正确解析数据变更。
- 从库账号需要授予SELECT和REPLICATION SLAVE权限,确保可以读取数据和binlog。
- 如果分析任务不需要全量数据,可以在CDC配置中指定过滤条件,减少数据传输量。
- 要监控从库的复制延迟,避免延迟过高导致分析结果时效性不足,延迟过高时可以优化从库硬件配置或者调整同步参数。
- 从库的只读配置要生效,避免分析任务或者误操作修改从库数据,导致主从数据不一致。
常见问题排查
如果从库复制出现异常,首先查看SHOW SLAVE STATUSG的输出,根据Last_Error字段定位问题。常见的错误包括主从server-id重复、同步账号权限不足、binlog文件或位置配置错误等。如果是Flink读取从库数据失败,需要检查CDC连接器的版本是否和Flink版本兼容,从库的网络是否可达,账号密码是否正确。