Mysql主从复制及读写分离的实现-MyCat

MyCat介绍

什么是MyCat

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

MyCat官网:http://www.mycat.org.cn/

优势

copy官方的说明:
基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得MYCAT一开始就拥有一个很好的起点,站在巨人的肩膀上,我们能看到更远。业界优秀的开源项目和创新思路被广泛融入到MYCAT的基因中,使得MYCAT在很多方面都领先于目前其他一些同类的开源项目,甚至超越某些商业产品。

MYCAT背后有一支强大的技术团队,其参与者都是5年以上资深软件工程师、架构师、DBA等,优秀的技术团队保证了MYCAT的产品质量。

MYCAT并不依托于任何一个商业公司,因此不像某些开源项目,将一些重要的特性封闭在其商业产品中,使得开源项目成了一个摆设(猜测是说的淘宝的TDDL,只开源动态数据源,分表分库部分还未开源)。

Mysql主从配置

##环境介绍:

两台Mysql数据库实现主从配置
Mycat:172.16.14.1
Mysql Master:172.16.14.2
Mysql Slave:172.16.14.3

##在Master服务器上安装并配置Mysql

1
2
3
4
5
6
7
8
9
10
#安装Mysql并加入到系统服务
[root@master ~]# tar xf mysql-5.6.13-linux-glibc2.5-x86_64.tar.gz -C /usr/local/
[root@master ~]# cd /usr/local/
[root@master local]# ln -s mysql-5.6.13-linux-glibc2.5-x86_64 mysql
[root@master local]# cd mysql
[root@master mysql]# cp support-files/mysql.server /etc/init.d/mysqld
[root@master mysql]# chmod +x /etc/init.d/mysqld
[root@master mysql]# chkconfig --add mysqld
[root@master mysql]# echo "PATH=/usr/local/mysql/bin:$PATH" >> /etc/profile
[root@master mysql]# . /etc/profile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#提供主配置文件
[root@master mysql]# vim /etc/my.cnf
[client]
#定义mysql client的密码
#password = your_password
port = 3306
socket = /tmp/mysql.sock
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 256M
max_allowed_packet = 1M
table_open_cache = 256
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
thread_concurrency = 8
binlog-format=ROW
#开启GTID模式
log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=2
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
report-port=3306
datadir=/data
report-host=172.16.14.2
log-bin=mysql-bin
server-id = 10
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
1
2
3
4
5
6
7
#初始化Mysql
[root@master mysql]# useradd -r mysql
[root@master mysql]# mkdir /data
[root@master mysql]# chown -R mysql.mysql /data
[root@master mysql]# chown -R root.mysql /usr/local/mysql/*
[root@master mysql]# ./scripts/mysql_install_db --user=mysql --datadir=/data/
[root@master ~]# service mysqld start
1
2
3
4
#在Slave服务器上安装Mysql与在Master服务器上安装方法相同,而在Slave服务器上安装Mysql有两个参数与Master服务器不同;如下
server-id=11
report-host=172.16.14.3
[root@slave ~]# service mysqld start

##在Master服务器上为Slave创建复制用户并测试连接

1
2
3
4
5
6
[root@master ~]# mysql
mysql> grant replication slave,replication client on *.* to 'slave'@'172.16.%.%' identified by 'passwd';
mysql> flush privileges;
------------------------------------------------------------------------
######测试连接
[root@slave ~]# mysql -uslave -ppasswd -h 172.16.14.2

##启动从节点的复制线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@slave ~]# mysql
mysql> change master to master_host='172.16.14.2',master_user='slave',master_password='passwd',master_auto_position=1;
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.14.2
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 191
Relay_Log_File: slave-relay-bin.000003
Relay_Log_Pos: 401
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes #主要看这两项为“YES”说明成功
Slave_SQL_Running: Yes

##在Master服务器创建数据库查看Slave服务器是否更新

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master ~]# mysql -e 'create database allen;'
------------------------------------------------------------------------
[root@slave ~]# mysql -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| allen |
| mysql |
| performance_schema |
| test |
+--------------------+
#由上可见,新创建的"allen"数据库已成功同步

至此Mysql 5.6 基于GTID的复制已经完成,下面将介绍如何基于Mysql的主从复制架构做读写分离

#读写分离配置
基于前面做的Mysql主从架构,然后在前端加一台服务器,用于实现Mysql的读写分离,IP地址为:172.16.14.1;由于Mycat是java程序所研发,所以需要先安装JDK程序

##安装JDK

1
2
3
4
5
6
7
8
9
10
11
12
[root@amoeba ~]# tar xzvf jdk-7u72-linux-x64.tar.gz
[root@amoeba ~]# chown -R /usr/local/java
[root@amoeba ~]# mv jdk1.7.0_72 /usr/local/java
[root@amoeba ~]# vim /etc/profile
export JAVA_HOME=/usr/local/java/jdk1.7.0_72
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
[root@amoeba ~]# source /etc/profile
[root@amoeba ~]# java -version
java version "1.7.0_72"
Java(TM) SE Runtime Environment (build 1.7.0_72-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.72-b04, mixed mode)

##安装MyCat

1
2
[root@amoeba ~]# tar xzvf Mycat-server-1.5-RELEASE-20160309173032-linux.tar.gz
[root@amoeba ~]# mv Mycat /usr/local/

##授权Mysql用户,用于实现前端MyCat连接
由于上面授权的主从复制帐号不能同步”mysql”数据库,所以用户名也无法同步,要在两台数据库上同时授权,用户名密码保持一致

1
2
3
4
5
6
7
8
9
#主mysql
[root@master ~]# mysql
mysql> grant all on *.* to 'mycat'@'172.16.%.%' identified by '123456';
mysql> flush privileges;
#备mysql
[root@slave ~]# mysql
mysql> grant all on *.* to 'mycat'@'172.16.%.%' identified by '123456';
mysql> flush privileges;

##配置MyCat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[root@mycat ~]# cd /usr/local/mycat/conf/ #主要配置文件为以下两个
schema.xml #定义数据库读写分离及节点管理信息等
server.xml #保存了所有mycat需要的系统配置信息,mycat服务用户密码等
[root@mycat ~]# vi schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">
<!--schema标签用于定义MyCat实例中的逻辑库,MyCat可有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用 schema 标签来划分不同的逻辑库。-->
<!--这里定义一个TESTDB的逻辑库,包含dn1这个分片 -->
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<!--可配置分片规则,user表根据latest-month-calldate规则分片到dn2,dn3节点,其他没定义的表默认在dn1节点-->
<!-- auto sharding by id (long) -->
<!-- <table name="user" primaryKey="ID" dataNode="dn2,dn3" rule="latest-month-calldate" /> -->
</schema>
<!--定义数据分片节点,使用名字为localhost1库实例上的wytest物理数据库,就组成一个数据分片,可配置多个 -->
<dataNode name="dn1" dataHost="localhost1" database="wytest" />
<!--<dataNode name="dn4" dataHost="sequoiadb1" database="SAMPLE" />
<dataNode name="jdbc_dn1" dataHost="jdbchost" database="db1" />
<dataNode name="jdbc_dn2" dataHost="jdbchost" database="db2" />
<dataNode name="jdbc_dn3" dataHost="jdbchost" database="db3" /> -->
<!--定义具体的数据实例-->
<!--balance 负载均衡类型,目前的取值有 3 种:
1. balance="0",不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
2. balance="1",全部的readHost与stand by writeHost参与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 没有。-->
<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 -->
<!--在一个dataHost内可定义多个writeHost和readHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,由于这个writeHost宕机,系统会自动的检测到,并切换到备用的writeHost上去-->
<writeHost host="hostM1" url="172.16.14.2:3306" user="mycat" password="123456">
<!-- can have multi read hosts -->
<readHost host="hostS1" url="172.16.14.3:3306" user="mycat" password="123456" />
</writeHost>
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
</mycat:schema>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[root@mycat ~]# vi server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
<system>
<property name="defaultSqlParser">druidparser</property>
<!-- <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
<!-- <property name="processorBufferChunk">40960</property> -->
<!--
<property name="processors">1</property>
<property name="processorExecutor">32</property>
-->
<!--默认是65535 64K 用于sql解析时最大文本长度 -->
<!--<property name="maxStringLiteralLength">65535</property>-->
<!--<property name="sequnceHandlerType">0</property>-->
<!--<property name="backSocketNoDelay">1</property>-->
<!--<property name="frontSocketNoDelay">1</property>-->
<!--<property name="processorExecutor">16</property>-->
<!--
<property name="mutiNodeLimitType">1</property> 0:开启小数量级(默认) ;1:开启亿级数据排序
<property name="mutiNodePatchSize">100</property> 亿级数量排序批量
<property name="processors">32</property>
<property name="processorExecutor">32</property>
<property name="serverPort">8066</property>
<property name="managerPort">9066</property>
<property name="idleTimeout">300000</property>
<property name="bindIp">0.0.0.0</property>
<property name="frontWriteQueueSize">4096</property>
<property name="processors">32</property> -->
</system>
<!--定义test用户,访问TESTDB的逻辑库(schema.xml中定义)-->
<user name="test">
<property name="password">test</property>
<property name="schemas">TESTDB</property>
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>
<!--
<quarantine>
<whitehost>
<host host="127.0.0.1" user="mycat"/>
<host host="127.0.0.2" user="mycat"/>
</whitehost>
<blacklist check="false"></blacklist>
</quarantine>
-->
</mycat:server>