Mycat 高可用数据库架构搭建及读写分离,主从切换测试案例

本文详细介绍了Mycat数据库中间件的功能和使用方法,包括分库分表、读写分离、主从切换等高级特性,以及如何安装、配置和管理Mycat,适用于系统开发中对数据库性能优化的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mycat 简介

系统开发中,数据库是非常重要的一个点。除了程序的本身的优化,如:SQL 语句优化、代
码优化,数据库的处理本身优化也是非常重要的。主从、热备、分表分库等都是系统发展迟
早会遇到的技术问题问题。Mycat 是一个广受好评的数据库中间件,已经在很多产品上进行
使用了。希望通过这篇文章的介绍,能学会 Mycat 的使用。

什么是 Mycat

• 一个彻底开源的,面向企业应用开发的大数据库集群
• 支持事务、ACID、可以替代 MySQL 的加强版数据库
• 一个可以视为 MySQL 集群的企业级数据库,用来替代昂贵的 Oracle 集群
• 一个融合内存缓存技术、NoSQL 技术、HDFS 大数据的新型 SQL Server
• 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
• 一个新颖的数据库中间件产品

常用功能

分库分表

一个系统的多张数据表,存储到多个数据库实例中;

对于一张多行(记录)多列(字段)的二维数据表,又分两种情形:

垂直分表: 竖向切分,不同分表存储不同的字段,可以把不常用或者大容量、或者不同
业务的字段拆分出去;

水平分表(最复杂): 横向切分,按照特定分片算法,不同分表存储不同的记录。

读写分离

不同的数据库,同步相同的数据,分别只负责数据的读和写;

主从切换

数据库宕机后自动切换到备机

安装

Mycat 官网下载地址:http://www.mycat.io/

根据不同的系统选择不同的版本。包括 linux、windows、mac,作者考虑还是非常周全的,当
然,也有源码版的。(ps:源码版的下载后,只要配置正确,就可以正常运行调试,这个赞一
下。)
在这里插入图片描述
Mycat 的安装其实只要解压下载的目录就可以了,非常简单。
安装完成后,目录如下:

在这里插入图片描述

配置文件

Mycat 的配置文件都在 conf 目录里面,这里介绍几个常用的文件:
在这里插入图片描述
Mycat 的架构其实很好理解,Mycat 是代理,Mycat 后面就是物理数据库。和 Web 服务器的
Nginx 类似。对于使用者来说,访问的都是 Mycat,不会接触到后端的数据库。

指令

Mycat 的启动也很简单,启动命令在 Bin 目录:

启动

mycat start

停止

mycat stop

重启

mycat restart

如果在启动时发现异常,在 logs 目录中查看日志。

wrapper.log 为程序启动的日志,启动时的问题看这个

mycat.log 为脚本执行时的日志,SQL 脚本执行报错后的具体错误内容,查看这个文件。

mycat.log 是最新的错误日志,历史日志会根据时间生成目录保存。

mycat 启动后,执行命令不成功,可能实际上配置有错误,导致后面的命令没有很好的执行。

Mycat 带来的最大好处就是使用是完全不用修改原有代码的,在 mycat 通过命令启动后,你
只需要将数据库连接切换到 Mycat 的地址就可以了。
如下面就可以进行连接了:

mysql -h192.168.0.1 -P8806 -uroot -p123456

连接成功后可以执行 sql 脚本了。

Mycat 还有一个管理的连接,端口号是 9906.

mysql -h192.168.0.1 -P9906 -uroot -p123456

连接后可以根据管理命令查看 Mycat 的运行情况,当然,喜欢 UI 管理方式的人,可以安装
一个 Mycat-Web 来进行管理,有兴趣自行搜索。

简而言之,开发中使用 Mycat 和直接使用 Mysql 机会没有差别。

使用场景

以某个系统为例,有 6 台 mysql 物理库集群,划分了 4 个逻辑库,分别是订单库,商品库,
用户库和系统库,数据量较大的订单库和商品库下分别挂两个物理库 order1 和 order2,
goods1 和 goods2,用户库和系统库分别下挂一个物理库 user1 和 sys1
order1 和 order2 做读写分离,读操作发往 order1,写操作发往 order2;
order1 和 order2 做主从复制,主从切换,实时同步两边数据,宕机后切换备机,恢复后切
换回主机
goods1 和 goods2 做读写分离,读操作发往 goods1,写操作发往 goods2
goods1 和 goods2 做主从复制,主从切换,实时同步两边数据,宕机后切换备机,恢复后切
换回主机

高可用架构

在这里插入图片描述

分库结构

在这里插入图片描述

配置

server.xml

配置 mycat 的登陆用户名,密码和操作的数据库

<user name="root">
	<property name="password">123456</property>
	<property name="schemas">xxx</property>
	<property name="readOnly">false</property>

schema.xml

配置分库分表信息,逻辑库节点
物理库名

<schema name="xxx" checkSQLschema="false" sqlMaxLimit="100">

物理表,逻辑节点

<table name="tb_order" dataNode="order"/>
<table name="tb_order_2" dataNode="order"/>
<table name="tb_order_3" dataNode="order"/>
<table name="tb_item" dataNode="goods"/>
<table name="tb_item_2" dataNode="goods"/>
<table name="tb_item_3" dataNode="goods"/>
<table name="tb_item_4" dataNode="goods"/>
<table name="tb_item_5" dataNode="goods"/>
<table name="tb_item_6" dataNode="goods"/>
<table name="tb_item_7" dataNode="goods"/>
<table name="tb_item_8" dataNode="goods"/>
<table name="tb_item_9" dataNode="goods"/>
<table name="tb_item_10" dataNode="goods"/>
<table name="tb_item_11" dataNode="goods"/>
<table name="tb_item_12" dataNode="goods"/>
<table name="tb_user" dataNode="user"/>
<table name="tb_user_2" dataNode="user"/>
<table name="tb_user_3" dataNode="user"/>
<table name="tb_user_4" dataNode="user"/>
<table name="tb_sys" dataNode="sys"/>
<table name="tb_sys_2" dataNode="sys"/>
<table name="tb_sys_3" dataNode="sys"/>
<table name= tb_sys_4" dataNode="sys"/>
 <table name="tb_sys_5" dataNode="sys"/>
<table name="tb_sys_6" dataNode="sys"/>
<table name="tb_sys_7" dataNode="sys"/>
<table name="tb_sys_8" dataNode="sys"/>
<table name="tb_sys_9" dataNode="sys"/>
<table name="tb_sys_10" dataNode="sys"/>
<table name="tb_sys_11" dataNode="sys"/>
<table name="tb_sys_12" dataNode="sys"/>
…
<!-- balance 为 3 表示读写分离,所有读操作都发到 readhost,switchtype 为 2 表示主库
宕机后根据主从同步状态决定是否切换从库-->
<dataHost name="host_order" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native"
switchType="2" slaveThreshold="100">
心跳
<heartbeat>show slave status</heartbeat>
写库信息
<writeHost host="order_m" url="172.16.23.126:3301" user="root"
password="111111">
读库信息
<readHost host="order_r" url="172.16.23.126:3302" user=""
root" password=" 111111" />
同时读库也是写库的备份库
<writeHost host="order_s" url="172.16.23.126:3302" user="root"
password="111111">
</writeHost>
写库信息
<writeHost host="goods_m" url="172.16.23.126:3303" user="root"
password="111111">
读库信息
<readHost host="goods_r" url="172.16.23.126:3304" user=""
root" password="111111" />
</writeHost>
同时读库也是写库的备份库
<writeHost host="goods_s" url="172.16.23.126:3304" user="root"
password="111111">
</writeHost>
写库信息
<writeHost host="user_m" url="172.16.23.126:3305" user="root"
password="111111">
 </writeHost>
</dataHost>
<dataHost name="host_sys" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchTT
ype="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
写库信息
<writeHost host="sys_m" url="172.16.23.126:3306" user="root"
password="111111">
</writeHost>

log4j2.xml

日志配置

<asyncRoot level="debug" includeLocation="true">

测试用例

分库

登陆 mycat
从任意一台 mysql 主机访问

mysql -h172.16.23.126 -P8066 -uroot -p123456

查询表分片:

mysql> use xxx;
mysql> explain select * from tb_order;
±----------±---------------------------------+
| DATA_NODE | SQL |
±----------±---------------------------------+
| order | SELECT * FROM tb_order LIMIT 100 |
±----------±---------------------------------+
1 row in set (0.00 sec)
mysql> explain select * from tb_item;
±----------±--------------------------------+
| DATA_NODE | SQL |
±----------±--------------------------------+
| goods | SELECT * FROM tb_item LIMIT 100 |
±----------±--------------------------------+
1 row in set (0.03 sec)
mysql> explain select * from tb_member;
±----------±----------------------------------+
| DATA_NODE | SQL |
±----------±----------------------------------+
| user | SELECT * FROM tb_member LIMIT 100 |
±----------±----------------------------------+
1 row in set (0.00 sec)
mysql> explain select * from tb_express;
±----------±-----------------------------------+
| DATA_NODE | SQL |
±----------±-----------------------------------+
| sys | SELECT * FROM tb_express LIMIT 100 |
±----------±-----------------------------------+
1 row in set (0.08 sec)

读写分离

监控日志
/root/mycat/logs/mycat.log

指令:

SELECT * FROM tb_order;

Orderhost 读操作走的是 3302 库

**2019-04-01 10:01:49.271 DEBUG [$_NIOREACTOR-1-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=41, lastTime=1554112909262, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=true, threadId=30,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{SELECT *
FROM tb_order
LIMIT 100}, respHandler=SingleNodeHandler [node=order{SELECT *
FROM tb_order
LIMIT 100}, packetId=20], host=172.16.22.119, port=3302, statusSync=null, writeQueue=0,
modifiedSQLExecuted=false]

指令:

insert into tb_order(order_id,payment) values (1,200) ;

Orderhost 写操作走的是 3301 库

2019-04-01 10:04:21.311 DEBUG [$_NIOREACTOR-1-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=15, lastTime=1554113061162, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=38,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{insert into
tb_order(order_id,payment) values (1,200)}, respHandler=SingleNodeHandler
[node=order{insert into tb_order(order_id,payment) values (1,200)}, packetId=1],
host=172.16.22.119, port=3301, statusSync=null, writeQueue=0,
modifiedSQLExecuted=true]

主从复制

前提互备的两台 mysql 需要配置主从复制功能,

在 3302 上查询 mysql 的 order 表,发现也有这条数据,复制成功

主从切换

关闭主库

Orderhost 读操作走的是 3302 库

2019-04-01 10:08:43.845 DEBUG [$_NIOREACTOR-0-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=48, lastTime=1554113323822, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=33,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{SELECT *
FROM tb_order
LIMIT 100}, respHandler=SingleNodeHandler [node=order{SELECT *
FROM tb_order
LIMIT 100}, packetId=21], host=172.16.22.119, port=3302, statusSync=null, writeQueue=0,
modifiedSQLExecuted=false]

Orderhost 写操作走的是 3302 库

2019-04-01 10:10:09.876 DEBUG [$_NIOREACTOR-0-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=48, lastTime=1554113409862, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=33,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{insert into
tb_order(order_id,payment) values (6,800)}, respHandler=SingleNodeHandler
[node=order{insert into tb_order(order_id,payment) values (2,300)}, packetId=1],
host=172.16.22.119, port=3302, statusSync=null, writeQueue=0,
modifiedSQLExecuted=true]

查询 3302 order 表中存在这条记录
在这里插入图片描述
恢复主库

检查主库,数据和从库保持一致
在这里插入图片描述
登陆 mycat 管理端口 index 切换回原来的主库

mysql -h172.16.23.126 -P9066 -uroot -p123456

switch @@datasource host_order:0;
switch @@datasource host_goods:0;

Orderhost 读操作走的是 3302 库

69326688, user=root, schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=true,
threadId=63, charset=latin1, txIsolation=3, autocommit=true, attachment=order{SELECT *
FROM tb_order
LIMIT 100}, respHandler=SingleNodeHandler [node=order{SELECT *
FROM tb_order
LIMIT 100}, packetId=24], host=172.16.22.119, port=3302, statusSync=null, writeQueue=0,
modifiedSQLExecuted=false]

Orderhost 写操作走的是 3301 库

2019-04-02 01:40:06.835 DEBUG [$_NIOREACTOR-0-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=69, lastTime=1554169206828, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=6,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{insert into
tb_order(order_id,payment) values (4,800)}, respHandler=SingleNodeHandler
[node=order{insert into tb_order(order_id,payment) values (4,800)}, packetId=1],
host=172.16.22.119, port=3301, statusSync=null, writeQueue=0,
modifiedSQLExecuted=true]

主从库都存在该条数据:
在这里插入图片描述
关闭从库

2019-04-02 01:43:58.001 DEBUG [$_NIOREACTOR-0-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=69, lastTime=1554169437988, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=6,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{SELECT *
FROM tb_order
LIMIT 100}, respHandler=SingleNodeHandler [node=order{SELECT *
FROM tb_order
LIMIT 100}, packetId=24], host=172.16.22.119, port=3301, statusSync=null, writeQueue=0,
modifiedSQLExecuted=false]

2019-04-02 01:44:53.628 DEBUG [$_NIOREACTOR-0-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=73, lastTime=1554169493608, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=9,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{insert into
tb_order(order_id,payment) values (5,800)}, respHandler=SingleNodeHandler
[node=order{insert into tb_order(order_id,payment) values (5,800)}, packetId=1],
host=172.16.22.119, port=3301, statusSync=null, writeQueue=0,
modifiedSQLExecuted=true]

查看 3301 库的 order 表:
在这里插入图片描述
恢复从库

检查从库,和主库保持一致:
在这里插入图片描述

2019-04-02 01:48:16.833 DEBUG [$_NIOREACTOR-1-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=76, lastTime=1554169696828, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=true, threadId=5,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{SELECT *
FROM tb_order
LIMIT 100}, respHandler=SingleNodeHandler [node=order{SELECT *
FROM tb_order
LIMIT 100}, packetId=25], host=172.16.22.119, port=3302, statusSync=null, writeQueue=0,
modifiedSQLExecuted=false]

2019-04-02 01:48:56.714 DEBUG [$_NIOREACTOR-1-RW]
(io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:341)) -
release connection MySQLConnection [id=74, lastTime=1554169736708, user=root,
schema=zmall, old shema=zmall, borrowed=true, fromSlaveDB=false, threadId=8,
charset=latin1, txIsolation=3, autocommit=true, attachment=order{insert into
tb_order(order_id,payment) values (7,800)}, respHandler=SingleNodeHandler
[node=order{insert into tb_order(order_id,payment) values (7,800)}, packetId=1],
host=172.16.22.119, port=3301, statusSync=null, writeQueue=0,
modifiedSQLExecuted=true]

主从库数据一致:
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值