Mycat 读写分离 - 一主一从
读写分离把写交给主库、读交给从库,Mycat 用
dataHost下的writeHost/readHost实现:写走writeHost,读走readHost。
一、介绍
读写分离,简单地说就是把数据库的读和写操作分开,以对应不同的数据库服务器:
- 主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。
- 通过 MyCat 即可轻易实现上述功能,不仅可以支持 MySQL,也可以支持 Oracle 和 SQL Server。
应用程序 ──▶ MyCat ──writeHost──▶ mysql(m):insert / update / delete
│
└──readHost───▶ mysql(s):select
mysql(m) ──主从复制(binlog)──▶ mysql(s)
读写分离的前提是主从复制已经搭好,否则从库读不到主库的新数据。
二、一主一从原理
MySQL 的主从复制是**基于二进制日志(binlog)**实现的:
master:insert / update / delete → data change → binlog
│ read
▼
slave: IOthread ──write──▶ Relay log ──read──▶ SQLthread ──replay──▶ 从库数据
| 线程 | 职责 |
|---|---|
| IOthread | 读取主库 binlog,写入从库 relay log |
| SQLthread | 读取 relay log 并在从库重放 |
主从复制本身的搭建步骤见 主从复制 - 搭建,本节只做 Mycat 侧的读写分离配置。
三、环境准备
| 主机(示例) | 角色 | 用户名 | 密码 |
|---|---|---|---|
1.2.3.5 | master | root | 你的密码 |
1.2.3.6 | slave | root | 你的密码 |
主从复制按前面课程的步骤搭好后,再配置 Mycat。
四、Mycat 配置
Mycat 控制后台数据库的读写分离和负载均衡由 schema.xml 文件 dataHost 标签的 balance 属性控制。
<schema name="ITCAST_RW" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn7">
<!-- <table name="sku" dataNode="dn7" primaryKey="id" /> -->
</schema>
<dataNode name="dn7" dataHost="dhost7" database="itcast" />
<dataHost name="dhost7" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="jdbc">
<heartbeat>select user()</heartbeat>
<writeHost host="master" url="jdbc:mysql://1.2.3.5:3306?useSSL=false"
user="root" password="你的密码">
<readHost host="slave" url="jdbc:mysql://1.2.3.6: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_RW</property>
</user>
balance 的 4 种取值
| 参数值 | 含义 |
|---|---|
0 | 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上 |
1 | 全部的 readHost 与备用的 writeHost 都参与 select 语句的负载均衡(主要针对双主双从模式) |
2 | 所有的读写操作都随机在 writeHost、readHost 上分发 |
3 | 所有的读请求随机分发到 writeHost 对应的 readHost 上执行,writeHost 不负担读压力 |
一主一从常用
balance="1"或balance="3";balance="0"等于没开读写分离。
五、测试与局限
连接 Mycat,在其中执行 DML、DQL,查看是否能够进行读写分离:
-- 写:应落到 master
INSERT INTO tb_user(id, name, sex) VALUES (7, 'Alice', '0');
-- 读:应落到 slave
SELECT * FROM tb_user WHERE id = 7;
可以通过在主库 / 从库分别查询、对比数据或查看连接情况来判断读写是否分离。
问题:主节点 Master 宕机之后,业务系统就只能读,而不能写入数据了。因为只有一个
writeHost,没有可切换的写节点——这就引出了双主双从。
速查
<!-- 一主一从:写走 writeHost,读走 readHost -->
<dataHost name="dhost7" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="jdbc">
<heartbeat>select user()</heartbeat>
<writeHost host="master" url="jdbc:mysql://1.2.3.5:3306"
user="root" password="你的密码">
<readHost host="slave" url="jdbc:mysql://1.2.3.6:3306"
user="root" password="你的密码" />
</writeHost>
</dataHost>
-- 测试读写分离
INSERT INTO tb_user(id, name, sex) VALUES (7, 'Alice', '0'); -- 写 → master
SELECT * FROM tb_user WHERE id = 7; -- 读 → slave
| 要做什么 | 配置 |
|---|---|
| 开启读写分离 | balance="1"(或 3) |
| 写节点 | writeHost |
| 读节点 | writeHost 内嵌 readHost |
| 主库挂了仍要能写 | 单 writeHost 做不到,需双主双从 |
相关
- Mycat 读写分离 - 双主双从:双写节点与自动切换
- 主从复制 - 搭建:binlog 主从复制的完整步骤
- Mycat 配置:
schema.xml/server.xml全量说明 - Mycat 垂直拆分与水平拆分:分片与读写分离可以叠加使用