基于amoeba和GTID功能实现mysql5.6读写分离
一.amoeba简介
1.Amoeba介绍
Amoeba是一个以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy。它集中地响应应用的请求,依据用户事先设置的规则,将SQL请求发送到特定的数据库上执行。基于此可以实现负载均衡、读写分离、高可用性等需求。与MySQL官方的MySQL Proxy相比,作者强调的是amoeba配置的方便(基于XML的配置文件,用SQLJEP语法书写规则,比基于lua脚本的MySQL Proxy简单)。
Amoeba相当于一个SQL请求的路由器,目的是为负载均衡、读写分离、高可用性提供机制,而不是完全实现它们。用户需要结合使用MySQL的Replication等机制来实现副本同步等功能。amoeba对底层数据库连接管理和路由实现也采用了可插拨的机制,第三方可以开发更高级的策略类来替代作者的实现。
2.amoeba主要解决的问题
(1).数据切分后复杂数据源整合;
(2).提供数据切分规则并降低数据切分规则给数据库带来的影响;
(3).降低数据库与客户端连接;
(4).读写分离路由;
3.amoeba与mysql-proxy在读写分离上的区别
在MySQLproxy6.0版本上面如果想要读写分离并且读集群、写集群机器比较多情况下,用mysqlproxy需要相当大的工作量,目前mysqlproxy没有现成的lua脚本。
mysqlproxy根本没有配置文件,lua脚本就是它的全部,当然lua是相当方便的。那么同样这种东西需要编写大量的脚本才能完成一个复杂的配置。而Amoeba只需要进行相关的配置就可以满足需求。
4.amoeba工作原理
用户访问amoeba服务器,其中读操作被amoeba服务器路由到从服务器(这里要求从服务器只负责读操作,主服务器只负责写操作),写操作被路由到主服务器,又由于主从复制的功能,主服务器将用户的写操作再复制到从服务器上,从而实现读写分离;
二.配置过程
1.配置环境
主服务器:192.168.85.144 node1.a.com
从服务器:192.168.85.145 node2.a.com
amoeba服务器:192.168.85.128 proxy.a.com
已配置好mysql5.6基于GTID的主从复制环境,详见:
http://blog.chinaunix.net/uid-30212356-id-5580259.html
2.java环境的安装
Amoeba框架是基于Java SE1.5开发的,建议使用Java SE 1.5版本。目前Amoeba经验证在JavaTM SE1.5和Java SE1.6能正常运行
这里使用:
[root@proxy ~]# ls | grep jdk
jdk-6u45-linux-i586-rpm.bin
2.1先赋给jdk包可执行权限然后运行
[root@proxy ~]# chmod +x jdk-6u45-linux-i586-rpm.bin
[root@proxy ~]# ./jdk-6u45-linux-i586-rpm.bin
2.2配置JAVA环境
[root@proxy ~]# cat /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/latest
export PATH=$JAVA_HOME/bin:$PATH
[root@proxy ~]# . /etc/profile.d/java.sh
2.3验证JAVA安装:
[root@proxy ~]# java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) Client VM (build 20.45-b01, mixed mode, sharing)
3.安装amoeba
3.1因为amoeba解压后不会自己创建目录,因此手动创建
[root@proxy ~]# mkdir -pv /usr/local/amoeba
mkdir: created directory `/usr/local/amoeba'
3.2解压到指定目录
[root@proxy ~]# tar xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
Amoeba有哪些主要的配置文件?
(1)想象Amoeba作为数据库代理层,它一定会和很多数据库保持通信,因此它必须知道由它代理的数据库如何连接,比如最基础的:主机IP、端口、Amoeba使用的用户名和密码等等。这些信息存储在$AMOEBA_HOME/conf/dbServers.xml中;
(2)Amoeba为了完成数据切分提供了完善的切分规则配置,为了了解如何分片数据、如何将数据库返回的数据整合,它必须知道切分规则。与切分规则相关的信息存储在$AMOEBA_HOME/conf/rule.xml中;
(3)当我们书写SQL来操作数据库的时候,常常会用到很多不同的数据库函数,比如:UNIX_TIMESTAMP()、SYSDATE()等等。这些函数如何被Amoeba解析呢?$AMOEBA_HOME/conf/functionMap.xml描述了函数名和函数处理的关系;
(4)对$AMOEBA_HOME/conf/rule.xml进行配置时,会用到一些我们自己定义的函数,比如我们需要对用户ID求HASH值来切分数据,这些函数在$AMOEBA_HOME/conf/ruleFunctionMap.xml中定义;
(5)Amoeba可以制定一些可访问以及拒绝访问的主机IP地址,这部分配置在$AMOEBA_HOME/conf/access_list.conf中;
(6)Amoeba允许用户配置输出日志级别以及方式,配置方法使用log4j的文件格式,文件是$AMOEBA_HOME/conf/log4j.xml;
4.编辑amoeba配置文件
4.1 编辑dbServer.xml文件
-
<?xml version="1.0" encoding="gbk"?>
-
-
<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
-
<amoeba:dbServers xmlns:amoeba="">
-
-
<!--
-
Each dbServer needs to be configured into a Pool,
-
If you need to configure multiple dbServer with load balancing that can be simplified by the following configuration:
-
add attribute with name virtual = "true" in dbServer, but the configuration does not allow the element with name factoryConfig
-
such as 'multiPool' dbServer
-
-->
-
-
<dbServer name="abstractServer" abstractive="true">
-
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
-
<property name="manager">${defaultManager}</property>
-
<property name="sendBufferSize">64</property>
-
<property name="receiveBufferSize">128</property>
-
-
<!-- mysql port -->
-
<property name="port">3306</property> #设置mysql数据库的端口;
-
-
<!-- mysql schema -->
-
<property name="schema">test</property> #连接amoeba后,默认的数据库;
-
-
#设置amoeba连接后端mysql服务器的账号和密码,需在后端数据库器上创建该用户,并授权amoeba连接;
-
<!-- mysql user -->
-
<property name="user">root</property>
-
-
<!-- mysql password
-
<property name="password">password</property>
-
-->
-
<property name="password">amoeba</property>
-
</factoryConfig>
-
-
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
-
<property name="maxActive">500</property>
-
<property name="maxIdle">500</property>
-
<property name="minIdle">10</property>
-
<property name="minEvictableIdleTimeMillis">600000</property>
-
<property name="timeBetweenEvictionRunsMillis">600000</property>
-
<property name="testOnBorrow">true</property>
-
<property name="testOnReturn">true</property>
-
<property name="testWhileIdle">true</property>
-
</poolConfig>
-
</dbServer>
-
-
#设置后端一个服务器的名;
-
<dbServer name="master" parent="abstractServer">
-
<factoryConfig>
-
<!-- mysql ip -->
-
<property name="ipAddress">192.168.85.144</property>
-
</factoryConfig>
-
</dbServer>
-
-
<dbServer name="slave" parent="abstractServer">
-
<factoryConfig>
-
<!-- mysql ip -->
-
<property name="ipAddress">192.168.85.145</property>
-
</factoryConfig>
-
</dbServer>
-
-
#指定一个虚拟的dbServer,将上面定义的dbserver加入这个虚拟的dbserver,相当于组成一个dbServer组;
#名称虽然可以任意取,但是最好不要取为readPool,这会产生不必要的错误;
-
-
<dbServer name="myreadPool" virtual="true">
-
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
-
<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
-
<property name="loadbalance">1</property>
-
#对该虚拟dbServer中后端服务器的调度方法,1为轮询,2为权值,3为HA;
-
<!-- Separated by commas,such as: server1,server2,server1 -->
-
<property name="poolNames">slave,slave,master</property>
-
#定义该虚拟dbServer的使用顺序,即读操作先路由到slave然后slave最后master,这里可实现负载均衡功能;
-
</poolConfig>
-
</dbServer>
-
-
</amoeba:dbServers>
4.2 编辑amoeba.xml文件
5.此时amoeba还无法启动,需要配置其环境变量
[root@proxy conf]# cat /etc/profile.d/amoeba.sh
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$AMOEBA_HOME/bin:$PATH
[root@proxy conf]# . /etc/profile.d/amoeba.sh
验证能否启动:
[root@proxy conf]# amoeba
amoeba start|stop #出现了这些提示,就说明能正常启动amoeba了;
6.在主服务器上创建amoeba用户
这个用户是用来让amoeba连接后端数据库的,而且要赋予一定的权限:
mysql>
grant all privileges on *.* to 'root'@'192.168.85.%' identified by 'amoeba';
启动amoeba:
[root@proxy conf]# amoeba start
log4j:WARN log4j config load completed from file:/usr/local/amoeba/conf/log4j.xml
2016-01-06 09:51:18,806 INFO context.MysqlRuntimeContext - Amoeba for Mysql current versoin=5.1.45-mysql-amoeba-proxy-2.2.0
log4j:WARN ip access config load completed from file:/usr/local/amoeba/conf/access_list.conf
2016-01-06 09:51:22,244 INFO net.ServerableConnectionManager - Amoeba for Mysql listening on 0.0.0.0/0.0.0.0:3306.
2016-01-06 09:51:22,258 INFO net.ServerableConnectionManager - Amoeba Monitor Server listening on /127.0.0.1:40759.
7.读写分离测试(通过抓包来测试)
7.1 测试能否登录
使用node1当作客户端连接amoeba:
[root@node1 ~]# mysql -u root -h192.168.85.128 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 17824568
Server version: 5.1.45-mysql-amoeba-proxy-2.2.0
mysql>
7.1 读测试(只有主上有)
客户端登陆后创建一个数据库:
mysql> create database mydb;
主服务器上的包:
[root@node1 ~]# tcpdump -i eth0 -s0 -nn -A tcp dst port 3306 and dst host 192.168.85.144
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:31:46.642361 IP 192.168.85.128.46480 > 192.168.85.144.3306: Flags [P.], seq 1820300201:1820300226, ack 4278332093, win 457, options [nop,nop,TS val 90317748 ecr 71428717], length 25
E..M..@.@.*T..U...U.....l.....*.....H......
.b#..A.m.....
create database mydb #可以看到,刚刚的写操作被路由到了主上;
从服务器上的包:
[root@node2 ~]# tcpdump -i eth0 -s0 -nn -A tcp dst port 3306 and dst host 192.168.85.145
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
而从服务器上没有相应包;
7.2 读测试(主从上都有)
继续使用刚才登陆的客户端进行select操作:
mysql> select host from mysql.user; #连续进行了三次该操作
主服务器上的包:
[root@node1 ~]# tcpdump -i eth0 -s0 -nn -A tcp dst port 3306 and dst host 192.168.85.144
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:40:26.010942 IP 192.168.85.128.46480 > 192.168.85.144.3306: Flags [P.], seq 1820300281:1820300313, ack 4278332304, win 490, options [nop,nop,TS val 90837118 ecr 71935679], length 32
E..T..@.@.*G..U...U.....l.....+.....7......
.j.~.I.......
select host from mysql.user #只出现了一次
从服务器上的包:
[root@node2 ~]# tcpdump -i eth0 -s0 -nn -A tcp dst port 3306 and dst host 192.168.85.145
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:51:53.865350 IP 192.168.85.128.57664 > 192.168.85.145.3306: Flags [P.], seq 312144217:312144249, ack 177973825, win 457, options [nop,nop,TS val 91524949 ecr 71346629], length 32
E..T&m@.@.....U...U..@.....Y
..A.....b.....
.t.U.@.......
select host from mysql.user #出现第一次
10:51:53.879848 IP 192.168.85.128.57664 > 192.168.85.145.3306: Flags [.], ack 214, win 490, options [nop,nop,TS val 91524958 ecr 71373706], length 0
E..4&n@.@.....U...U..@.....y
..............
.t.^.A..
10:51:56.498157 IP 192.168.85.128.57664 > 192.168.85.145.3306: Flags [P.], seq 32:64, ack 214, win 490, options [nop,nop,TS val 91527582 ecr 71373706], length 32
E..T&o@.@.....U...U..@.....y
........>.....
.t...A.......
select host from mysql.user #出现第二次
通过上述抓包的情况,可以看到,这很符合myreadPool中定义的两次slave一次master规则;
中文帮助文档:
参考资料:
http://634871.blog.51cto.com/624871/1335129?utm_source=tuicool&utm_medium=referral