Jw
首页
技术
英语
首页
技术
英语
  • MySQL

    • MySQL 基础
    • 环境变量配置(PATH)
    • SQL 语法与分类
    • MySQL 数据类型
    • SQL - DDL 数据定义语言
    • SQL - DML 数据操作语言
    • SQL - DQL 数据查询语言
    • SQL - DCL 数据控制语言
    • MySQL 函数
    • SQL 约束
    • SQL 外键约束
    • 多表关系
    • 多表查询(连接查询)
    • 隐式内连接 vs 显式内连接
    • 子查询
    • 多表查询案例
    • 事务
    • 并发事务问题与隔离级别
    • MySQL 体系结构与存储引擎
    • 索引概述
    • 索引结构
    • 索引分类
    • 索引语法
    • SQL 性能分析
    • 索引使用
    • 索引设计原则
    • SQL 优化 - 插入数据与主键优化
    • SQL 优化 - order by 与 group by
    • SQL 优化 - limit / count / update
    • 视图
    • 存储过程
    • 存储过程 - 变量
    • 存储过程 - 流程控制、游标与条件处理
    • 存储函数
    • 触发器
    • 锁概述与全局锁
    • 表级锁
    • 行级锁
    • InnoDB 逻辑存储结构
    • InnoDB 架构
    • 事务原理(redo / undo log)
    • MVCC
    • MySQL 系统数据库
    • MySQL 常用工具
    • 数据备份与导入导出
    • 错误日志与二进制日志
    • 查询日志与慢查询日志
    • 主从复制 - 概述与原理
    • 主从复制 - 搭建
    • Mycat 配置
    • Mycat 垂直拆分与水平拆分
    • Mycat 分片规则
    • Mycat 管理与监控
    • Mycat 读写分离 - 一主一从
    • Mycat 读写分离 - 双主双从

Mycat 读写分离 - 双主双从

双主双从:Master1 写、Master2 备,两台主库互为主备;S1、S2 与备用的 M2 一起分担读请求。主库宕机后由另一台主库接管写,靠 switchType 自动切换。

一、架构介绍

一个主机 Master1 用于处理所有写请求,它的从机 Slave1 和另一台主机 Master2 还有它的从机 Slave2 负责所有读请求。当 Master1 主机宕机后,Master2 主机负责写请求,Master1、Master2 互为主备。

                 ┌── M1 ──复制──▶ S1   (主)
应用程序 ─▶ MyCat ┤      ↕ 复制(互为主备)
                 └── M2 ──复制──▶ S2   (备)
特点说明
写平时只有 Master1 承担写
读S1、S2,以及备用的 M2 都可参与
故障Master1 挂掉后,Master2 接管写

二、准备工作

需要准备 5 台服务器:

编号地址(示例)预装软件角色
11.2.3.4MyCat、MySQLMyCat 中间件服务器
21.2.3.5MySQLM1
31.2.3.6MySQLS1
41.2.3.7MySQLM2
51.2.3.8MySQLS2

关闭以上所有服务器的防火墙:

systemctl stop firewalld
systemctl disable firewalld

三、搭建

3.1 主库配置

Master1(1.2.3.5) 修改 /etc/my.cnf:

# mysql 服务 ID,保证整个集群环境中唯一,取值范围 1 ~ 2^32-1,默认为 1
server-id=1

# 指定同步的数据库
binlog-do-db=db01
binlog-do-db=db02
binlog-do-db=db03

# 在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates

Master2(1.2.3.7) 修改 /etc/my.cnf:

# 服务 ID 与 Master1 不同
server-id=3

binlog-do-db=db01
binlog-do-db=db02
binlog-do-db=db03

# 作为从库时,写入也要更新二进制日志
log-slave-updates

两台主库都要重启:

systemctl restart mysqld

log-slave-updates 是双主互备的关键:M2 从 M1 复制来的写操作,还要再写进自己的 binlog,才能继续传给 S2(以及反向复制)。

3.2 从库配置

Slave1(1.2.3.6):

server-id=2

Slave2(1.2.3.8):

server-id=4

重启 MySQL:

systemctl restart mysqld

四台机器的 server-id 必须互不相同。

3.3 两台主库创建账户并授权

在两台主库上分别执行:

-- 创建 itcast 用户,可在任意主机连接
CREATE USER 'itcast'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';

-- 分配主从复制权限
GRANT REPLICATION SLAVE ON *.* TO 'itcast'@'%';

查看两台主库的二进制日志坐标:

SHOW MASTER STATUS;

记下各自的 File 与 Position,下一步配置从库时要用到。

3.4 两台从库配置关联的主库

CHANGE MASTER TO
    MASTER_HOST='主库地址',
    MASTER_USER='itcast',
    MASTER_PASSWORD='你的密码',
    MASTER_LOG_FILE='binlog.000002',
    MASTER_LOG_POS=1383;
从库对应主库
Slave1Master1
Slave2Master2

注意 slave1 对应的是 master1,slave2 对应的是 master2,不要配反。

启动主从复制并查看状态:

START SLAVE;
SHOW SLAVE STATUS\G

3.5 两台主库相互复制

Master2 复制 Master1,Master1 复制 Master2:在两台主库上分别执行 CHANGE MASTER TO,指向对方。

CHANGE MASTER TO
    MASTER_HOST='对方主库地址',
    MASTER_USER='itcast',
    MASTER_PASSWORD='你的密码',
    MASTER_LOG_FILE='binlog.000002',
    MASTER_LOG_POS=1383;

START SLAVE;
SHOW SLAVE STATUS\G

MySQL 8.0.23+ 可使用 CHANGE REPLICATION SOURCE TO / START REPLICA,参数名对应 SOURCE_*,见 主从复制 - 搭建。

3.6 测试主从同步

分别在两台主库 Master1、Master2 上执行 DDL、DML 语句,查看涉及到的数据库服务器的数据同步情况:

CREATE DATABASE db01;
USE db01;

CREATE TABLE tb_user(
    id   INT(11) NOT NULL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    sex  VARCHAR(1)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO tb_user(id, name, sex) VALUES (1, 'Tom', '1');
INSERT INTO tb_user(id, name, sex) VALUES (2, 'Trigger', '0');
INSERT INTO tb_user(id, name, sex) VALUES (3, 'Dawn', '1');
INSERT INTO tb_user(id, name, sex) VALUES (4, 'Jack Ma', '1');
INSERT INTO tb_user(id, name, sex) VALUES (5, 'Coco', '0');
INSERT INTO tb_user(id, name, sex) VALUES (6, 'Jerry', '1');

在 M1 写入后,S1、M2、S2 都应能查到;在 M2 写入后,S2、M1、S1 也应同步。

四、双主双从读写分离配置

Mycat 控制后台数据库的读写分离和负载均衡由 schema.xml 文件 dataHost 标签的 balance 属性控制,通过 writeType 及 switchType 来完成失败自动切换。

<schema name="ITCAST_RW2" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn7">
    <!-- <table name="tb_user" dataNode="dn7" primaryKey="id" /> -->
</schema>

<dataNode name="dn7" dataHost="dhost7" database="db01" />

<dataHost name="dhost7" maxCon="1000" minCon="10" balance="1"
          writeType="0" switchType="1" dbType="mysql" dbDriver="jdbc">
    <heartbeat>select user()</heartbeat>

    <writeHost host="master1" url="jdbc:mysql://1.2.3.5:3306?useSSL=false"
               user="root" password="你的密码">
        <readHost host="slave1" url="jdbc:mysql://1.2.3.6:3306?useSSL=false"
                  user="root" password="你的密码" />
    </writeHost>

    <writeHost host="master2" url="jdbc:mysql://1.2.3.7:3306?useSSL=false"
               user="root" password="你的密码">
        <readHost host="slave2" url="jdbc:mysql://1.2.3.8:3306?useSSL=false"
                  user="root" password="你的密码" />
    </writeHost>
</dataHost>

server.xml 中加上逻辑库:

<user name="root" defaultAccount="true">
    <property name="password">你的密码</property>
    <property name="schemas">SHOPPING,ITCAST,ITCAST_RW2</property>
</user>

4.1 balance

balance="1":代表全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡。

简单说,当双主双从模式(M1 → S1,M2 → S2,并且 M1 与 M2 互为主备),正常情况下,M2、S1、S2 都参与 select 语句的负载均衡。

4.2 writeType

取值含义
0写操作都转发到第 1 台 writeHost,writeHost1 挂了,会切换到 writeHost2 上
1所有的写操作都随机地发送到配置的 writeHost 上

4.3 switchType

取值含义
-1不自动切换
1自动切换

五、测试

登录 MyCat,测试查询及更新操作,判定是否能够进行读写分离,以及读写分离的策略是否正确:

-- 写:默认走 master1;master1 挂掉后应切到 master2
INSERT INTO tb_user(id, name, sex) VALUES (7, 'Alice', '0');

-- 读:参与负载均衡的是 M2、S1、S2
SELECT * FROM tb_user WHERE id = 7;

再验证当主库挂掉一个之后,是否能够自动切换。

速查

<!-- schema.xml:双主双从 -->
<dataNode name="dn7" dataHost="dhost7" database="db01" />

<dataHost name="dhost7" maxCon="1000" minCon="10" balance="1"
          writeType="0" switchType="1" dbType="mysql" dbDriver="jdbc">
    <heartbeat>select user()</heartbeat>
    <writeHost host="master1" url="jdbc:mysql://1.2.3.5:3306"
               user="root" password="你的密码">
        <readHost host="slave1" url="jdbc:mysql://1.2.3.6:3306"
                  user="root" password="你的密码" />
    </writeHost>
    <writeHost host="master2" url="jdbc:mysql://1.2.3.7:3306"
               user="root" password="你的密码">
        <readHost host="slave2" url="jdbc:mysql://1.2.3.8:3306"
                  user="root" password="你的密码" />
    </writeHost>
</dataHost>
# M1 /etc/my.cnf
server-id=1
binlog-do-db=db01
log-slave-updates

# S1
server-id=2

# M2
server-id=3
binlog-do-db=db01
log-slave-updates

# S2
server-id=4
-- 两台主库建复制账号
CREATE USER 'itcast'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';
GRANT REPLICATION SLAVE ON *.* TO 'itcast'@'%';

-- 从库指向各自主库;两台主库再相互指向对方
CHANGE MASTER TO
    MASTER_HOST='主库地址',
    MASTER_USER='itcast',
    MASTER_PASSWORD='你的密码',
    MASTER_LOG_FILE='binlog.000002',
    MASTER_LOG_POS=1383;

START SLAVE;
SHOW SLAVE STATUS\G
参数作用
balance="1"所有 readHost + 备用 writeHost 参与读负载均衡
writeType="0"写第 1 台,挂了切第 2 台
switchType="1"主库故障自动切换
log-slave-updates从库写入也记 binlog,双主互备必需

相关

  • Mycat 读写分离 - 一主一从:writeHost / readHost 基础配置
  • 主从复制 - 搭建:CHANGE REPLICATION SOURCE 与状态检查
  • Mycat 配置:dataHost 属性全表
  • Mycat 管理与监控:查看数据源与集群状态
最近更新: 2026/10/25 23:58
Contributors: liujw
Prev
Mycat 读写分离 - 一主一从