Mycat 下载地址:https://github.com/MyCATApache/Mycat-download
MySQL 离线rpm安装包:https://download.csdn.net/download/weixin_29115985/12288220
数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。对于MySQL来说,标准的读写分离是主从模式,一个写节点Master后面跟着多个读节点,读节点的数量取决于系统的压力,通常是1-3个读节点的配置。
如图所示,writeHost表示主节点,readHost表示从节点,Mycat内部定期对一个dataHost里所有的writeHost与readHost节点发起心跳检测(writeHost与readHost都可以配置多个,至于数据同步的问题则需要我们从mysql层面实现了,Mycat并不提供数据同步的支持,本文只讲mysql一主一从),正常情况下,Mycat会将第一个writeHost作为写节点,所有的DML SQL会发送给此节点,若Mycat开启了读写分离,则Select SQL会根据读写分离策略发往readHost(+writeHost)执行。当一个dataHost里面配置了多个writeHost时,如果第一个writeHost宕机,则Mycat会在默认的3次心跳检查失败后,自动切换到下一个可用的writeHost,以此类推。
这存在一个问题,就是当宕机的writeHost恢复后,怎么重新加入Mycat,要不要恢复为原来的写节点? 最佳建议方式是:保持现有状态不变,改旗易帜,恢复后的mysql节点作为从节点,跟随新的主节点,重新配置主从同步,原来跟随该节点做同步的从节点也同样换帅,重新配置同步源,这些节点的数据手工完成同步后,再加入Mycat里。
Mycat实现读写分离和高可用,需要MySQL的主从复制机制配合。
主从配置需要注意的地方
1、主DB server和从DB server数据库的版本一致
2、主DB server和从DB server数据库数据名称一致
3、主DB server开启二进制日志,主DB server和从DB server的server_id都必须唯一
1、修改 vi /etc/my.cnf 文件,在 [mysqld] 段下添加:
# 设置表名不区分大小写
lower_case_table_names=1
# 启用二进制日志
log-bin=mysql-bin
# 主服务器唯一ID,一般取IP最后一段
server-id=30
2、重启mysql服务:service mysqld restart
3、建立帐户并授权给用户:(不建议用root用户,% 表示所有客户端都可能连,不安全!此处是个人学习用,嫌麻烦才用root)
GRANT FILE ON *.* TO 'root'@'%' IDENTIFIED BY 'Root@123';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'root'@'%' IDENTIFIED BY 'Root@123';
# 嫌权限配置麻烦的话,可以赋全权出去,但是不太安全
# GRANT ALL PRIVILEGES ON *.* to 'root'@'%' IDENTIFIED BY 'Root@123';
4、刷新权限:FLUSH PRIVILEGES;
5、查询master的状态:show master status;
1、修改 vi /etc/my.cnf 文件,在 [mysqld] 段下添加:
# 设置表名不区分大小写
lower_case_table_names=1
# 主服务器唯一ID,一般取IP最后一段
server-id=203
2、配置从服务器:
# ''master_host'' 主库地址,''master_port''主库端口,''master_user'' 主库用户,''master_password'' 主库密码
# ''master_log_file'' 主库File号(见主库master状态),''master_log_pos'' 主库Position号(同见主库master状态)
change master to master_host='192.168.8.30',master_port=3306,master_user='root',master_password='Root@123',master_log_file='mysql-bin.000004',master_log_pos=5832;
3、启动从服务器复制功能:start slave;
4、检查从服务器复制功能状态:show slave status\G;
注:Slave_IO_Running 及 Slave_SQL_Running 进程必须正常运行,即 YES 状态,否则都是错误的状态(如:其中一个NO均属错误)。
* 问题排查:主从数据库不同步,导致数据不一致,查看从库状态,发现 Slave_IO_Running 一直处于 Connecting 状态?
* 问题解决:经过查看同步日志和状态,发现从库同步主库时,密码输入不正确,所以重新停止从库同步再重新链接到主库即可解决!
1、停止从库同步:stop slave;
2、重置主库:reset master;
3、重置从库:reset slave;
4、重新绑定主库:change master to master_host='192.168.8.30',master_port=3306,master_user='root',master_password='Root@123',master_log_file='mysql-bin.000004',master_log_pos=5832;
5、开启从库同步:start slave;
Mycat的配置非常简单,不用针对每个表进行配置,只需要在schema.xml中的元素上增加dataNode="defaultDN"属性,并配置此dataNode对应的真实物理数据库的database,然后dataHost开启读写分离功能即可。
1、将MyCat配置到环境变量中,vi /etc/profile ,增加以下内容:
MYCAT_HOME=/usr/local/mycat
PATH=$MYCAT_HOME/bin:$PATH
2、保存后退出,执行source命令使配置生效,source /etc/profile 。
3、server.xml和rule.xml不做修改,用默认的即可,简单配置下schema.xml,然后重启 mycat restart ,可通过 mycat console 查看启动日志。
select user()
配置说明:以下内容摘取于<<分布式数据库架构及企业实践基于Mycat中间件>>一书中的官方解析,度娘上找的很多都是错的!
1、balance属性:负载均衡类型
balance="0":不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
balance="1":所有读操作随机分发到当前 writeHost 对应的 readHost 和备用的 writeHost。这样就可以减轻主库的压力,高效地提供写操作,而由其他服务器承担耗费资源的读操作。
balance="2":所有读操作随机分发到所有的 writeHost 和 readHost 上。适用于主库压力不是很大时,也可以分担读操作,更合理地利用资源。
balance="3":所有读操作随机分发到当前 writeHost 对应的 readHost 上执行,writeHost 不负担读压力。此项只在Mycat1.4及之后版本才有,适用于双主热备、多个 slave 的情况。
2、writeType属性:负载均衡类型取值
writeType="0":所有写操作都发送到配置的第1个 writeHost 上,writeHost1 挂了则切到 writeHost2 上,重新恢复 writeHost1 节点后,不会再切回来,还是以 writeHost2 为准,切换记录在配置文件 dnindex.properties 中。
writeType="1":所有写操作都随机地发送到配置的 writeHost 上,Mycat1.5版本以后不再推荐使用该值。
3、switchType属性:切换模式
switchType="-1":表示不自动切换。
switchType="1":默认值,表示自动切换。
switchType="2":基于 MySQL 主从同步的状态决定是否切换,心跳语句为 show slave status 。
switchType="3":基于 Cluster 的切换机制(适合集群,Mycat 从1.4.1版本开始支持),心跳语句为 show status like 'wsrep%' 。
* 问题排查:完成读写分离配置后,通过Navicat进行数据测试,发现在主库新增表格,从库复制能成功,但是mycat的数据库打开表格时出现报错,如下:
[WARN ][$_NIOREACTOR-3-RW] execute sql err : errno:1146 Table 'testdb.company' doesn't exist con:MySQLConnection [id=12, lastTime=1584423906412, user=root, schema=mycat_db, old shema=mycat_db, borrowed=true, fromSlaveDB=false, threadId=52, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT * FROM `TESTDB`.`company` LIMIT 0, 1000}, respHandler=SingleNodeHandler [node=dn1{SELECT * FROM `TESTDB`.`company` LIMIT 0, 1000}, packetId=1], host=192.168.8.203, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=false] frontend host:192.168.8.46/53392/root (io.mycat.backend.mysql.nio.handler.SingleNodeHandler:SingleNodeHandler.java:249)
* 问题解决:经过 schema.xml 配置文件内容参数的排查,发现问题的根源在于 checkSQLschema 属性!当该值设置为 false 时(默认值),我们执行语句**SELECT * FROM company**,则Mycat会把 schema 字符增加进去,把 SQL 语句修改为**SELECT * FROM `TESTDB`.`company`**并发送到后端数据库执行,导致报错。只要把 checkSQLschema 属性改为 true 即可!
1、一般情况,查询会走slave节点,写入走master节点,对master节点数据库的增、删、改操作最终会同步到slave节点。
但这个同步所需要的时间不好掌握(网络延时等因素),如果延时太长,我们新增一条数据后立即去查询,很有可能会查询不到刚新增的的数据。
2、如果对数据的实时性要求比较高的查询,我们可以通过强制查询走master节点或slave节点。
#强制走master:
/*!mycat:db_type=master*/ SELECT * FROM company
#强制走slave:
/*!mycat:db_type=slave*/ SELECT * FROM company
1. Mycat - 实现数据库的读写分离与高可用
2. MySQL以及MyCat的安装和使用