1.1 相关参数介绍
balance指的负载均衡类型,目前的取值有4种:
1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
2. balance="1",全部的readHost与stand bywriteHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
3. balance="2",所有读操作都随机的在writeHost、readhost上分发。
4. balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
注意:balance=3只在1.4及其以后版本有,1.3没有。
writeType属性:
1.writeType=”0”,所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后以切换后的为准,切换记录在配置文件中:dnindex.properties.
2.writeType=”1”,所有写操作都随机地发送到配置的writeHost,1.5以后废弃不推荐。
switchType指的是切换的模式,目前的取值也有4种:
1. switchType='-1' 表示不自动切换
2. switchType='1' 默认值,表示自动切换
3. switchType='2' 基于MySQL主从同步的状态决定是否切换,心跳语句为 show slave status
4. switchType='3'基于MySQLgalary cluster的切换机制(适合集群)(1.4.1),心跳语句为 show status like 'wsrep%'。
注意:估计Mycat 1.4才开始支持switchType。1.3版本配置该属性的话,日志里会报错:org.xml.sax.SAXParseException;lineNumber: 61; columnNumber: 86; Attribute "switchType" must bedeclared for element type "dataHost"。
MyCAT心跳检查询句配置为 show slave status ,dataHost 上定义两个新属性: switchType="2" 与slaveThreshold="100",此时意味着开启MySQL主从复制状态绑定的读写分离与切换机制,Mycat心跳机制通过检测 show slave status 中的 "Seconds_Behind_Master", "Slave_IO_Running","Slave_SQL_Running" 三个字段来确定当前主从同步的状态及Seconds_Behind_Master主从复制时延,当Seconds_Behind_Master>slaveThreshold时,读写分离筛选器会过滤掉此Slave机器,防止读到很久以前的旧数据,当主节点宕机后,切换逻辑会检查Slave上的Seconds_Behind_Master是否为0,为0时则表示主仅同步,可安全切换,否则不会切换。
1.2 实验环境
双主复制:
10.192.203.201(hostname:PC)
10.192.203.202(hostname:slave2)
Mycat安装在10.192.203.202上。
1.3 实验步骤
本实验打算实现的功能:
只往10.192.203.201写,在10.192.203.202上读。且当10.192.203.201宕机时,自动切换到10.192.203.202上。
1.3.1 修改配置文件
cd /usr/local/mycat/conf
vi schema.xml
这里选择:balance="1",writeType=”0”,switchType='1'
dataHost处之前配置了只连接10.192.203.201mysql的用户名密码等信息:
现在配置读写分离相关设置。
修改后:
登录9066端口,使得配置生效:reload @@config_all;
1.3.2 验证读写分离
#验证是否写入到第一个配置的writeHost
连接mycat:
mysql -utest -ptest -h127.0.0.1 -P8066 -DUSERDB
操作之前配置过的一个表customer。
插入三条数据:
mysql> insert into customer(id,name) values(1,@@hostname),(1005,@@hostname),(2004,@@hostname);
Query OK, 3 rows affected (0.03 sec)
mysql> select * from customer where id in(1,1005,2004);
+------+------+
| ID | NAME |
+------+------+
| 2004 | PC |
| 1005 | PC |
| 1 | PC |
+------+------+
3 rows in set (0.03 sec)
说明数据插入到了10.192.203.201上了。
现在,主从都能查看到新插入的数据:
mysql> select * from db10.customer;
+------+------+
| ID | NAME |
+------+------+
| 1 | PC |
| 999 | dan |
| 1000 | jiao |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from db11.customer;
+------+------+
| ID | NAME |
+------+------+
| 1003 | song |
| 1005 | PC |
+------+------+
2 rows in set (0.01 sec)
mysql> select * from db12.customer;
+------+------+
| ID | NAME |
+------+------+
| 2002 | yang |
| 2004 | PC |
+------+------+
2 rows in set (0.00 sec)
#验证读自哪台机器
这里通过模拟主从数据不一致(停止slave,更新一些数据),来验证是从哪个节点读的。
停止10.192.203.201上的从库,在10.192.203.202上更新其中一条数据
10.192.203.201:
mysql> stop slave;
Query OK, 0 rows affected (0.02 sec)
10.192.203.202:
mysql> update db12.customer setname='slave2' where id= 2004;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update db11.customer setname='slave2' where id= 1005;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update db10.customer setname='slave2' where id= 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from db12.customer;
+------+--------+
| ID | NAME |
+------+--------+
| 2002 | yang |
| 2004 | slave2 |
+------+--------+
2 rows in set (0.00 sec)
再在mycat上查询:
mysql> select * from customer where id in(1,1005,2004);
+------+--------+
| ID | NAME |
+------+--------+
| 2004 | slave2 |
| 1005 | slave2 |
| 1 | slave2 |
+------+--------+
3 rows in set (0.19 sec)
说明是从10.192.203.202上读的。因为我们配置的balance为1,所以会在全部的readHost与stand by writeHost上读。
1.3.3 验证mycat是否自动切换
模拟10.192.203.201库宕机
[root@PC ~]# service mysql stop
Shutting down MySQL.... SUCCESS!
在mycat上插入几条数据,验证是否切换到了在10.192.203.202上插入。
mysql> insert into customer(id,name)values(2,@@hostname);
Query OK, 1 row affected (0.05 sec)
mysql> select * from customer where id =2;
+----+--------+
| ID | NAME |
+----+--------+
| 2| slave2 |
+----+--------+
1 row in set (0.03 sec)
说明切换成功。
主宕机后,读写都在从上进行。
切换后,Mycat会标记新的主从状态,主从状态保存在/conf/dnindex.properties文件
[root@slave2 conf]# cat dnindex.properties
#update
#Wed Aug 31 19:11:27 CST 2016
localhost1=1
现在localhost1值为1,切换前值为0.
#当原来的主10.192.203.201启动后,验证读写是在哪台机器上。
#验证写
[root@PC ~]# service mysql start
Starting MySQL... SUCCESS!
在mycat上插入塑胶:
mysql> insert into customer(id,name) values(3,@@hostname);
Query OK, 1 row affected (0.02 sec)
mysql> select * from customer where id =3;
+----+--------+
| ID | NAME |
+----+--------+
| 3| slave2 |
+----+--------+
1 row in set (0.02 sec)
看来原来的主再启动时,默认写还是在之前的从,即后来的主上面。
#验证读
关闭10.192.203.201上的从库,在10.192.203.202上做更新,看下是在哪台机器上读的:
10.192.203.201:
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)
10.192.203.202:
mysql> update db10.customer setname='PC' where id=3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from db10.customer where id = 3;
+----+------+
| ID | NAME |
+----+------+
| 3| PC |
+----+------+
1 row in set (0.00 sec)
在10.192.203.201上查询,还是原来的‘slave2’:
mysql> select * from db10.customer where id = 3;
+----+--------+
| ID | NAME |
+----+--------+
| 3| slave2 |
+----+--------+
1 row in set (0.00 sec)
在mycat上查询:
mysql> select * from customer where id =3;
+----+--------+
| ID | NAME |
+----+--------+
| 3| slave2 |
+----+--------+
1 row in set (0.02 sec)
在10.192.203.201上启动slave,再在mycat上查询,name又变成了PC(因为10.192.203.202上的更新同步到了10.192.203.201上)
mysql> select * from customer where id =3;
+----+------+
| ID | NAME |
+----+------+
| 3| PC |
+----+------+
1 row in set (0.02 sec)
说明主从切换后,写在10.192.203.202上写,读在10.192.203.201上读。
怎样再切换回来呢?关闭10.192.203.202库即可(确保10.192.203.201已启动)
[root@slave2 conf]# cat dnindex.properties
#update
#Wed Aug 31 19:56:08 CST 2016
localhost1=0
mysql> insert into customer(id,name)values(4,@@hostname);
Query OK, 1 row affected (0.03 sec)
mysql> select * from customer where id =4;
+----+------+
| ID | NAME |
+----+------+
| 4| PC |
+----+------+
1 row in set (0.02 sec)
说明现在已经切换到了原来的主。
对于mycat自身的高可用,官方建议是采用基于硬件的负载均衡器或者软件形式的HAproxy
注意:
我发现当switchType为2时,不能实现读写分离,读写都是在主节点上,即使设置了balance=1.
writeHost里面配置readHost情形:
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="hostM1" url="localhost:3306" user="root" password="123456"> <!-- can have multi read hosts --> <readHost host="hostS1" url="192.168.244.146:3306" user="root" password="123456" /> </writeHost> </dataHost>
这种方式有个问题,即master挂了以后,slave也不能提供服务
本篇文章参考了: