MySQL通过主从复制(Master-Slave)的方式来同步数据在现今中小型企业级应用中还算比较广泛,既然实现了数据在多台机器上的冗余,那么接下来就是考虑怎么来提升数据库的并发负载能力,读写分离通常是个不错的解决方法。
能实现为MySQL提供读写分离的工具(通常称为中间件)也不少,比如:MySQL官方提供的mysql-proxy、由淘宝提供的java应用程序(amoeba/cobar)、Qihoo 360的Atlas、gizzard等,下面就重点说下如何用amoeba为MySQL提供读写分离的配置过程。
一、Amoeba是什么?
amoeba(变形虫)项目由供职于淘宝的一程序员开发,于2008年开源出来的一款软件。这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当SQL路由功能,专注于分布式数据库代理层(Database Proxy)开发。座落与 Client、DB Server(s)之间,对客户端透明。具有负载均衡、高可用性、SQL过滤、读写分离、可路由相关的到目标数据库、可并发请求多台数据库合并结果。 通过amoeba你能够完成多数据源的高可用、负载均衡、数据切片的功能,目前amoeba已在很多企业的生产线上面使用。
上面说了amoeba是什么,并且能为我们提供那些功能,接下来简单的说下amoeba在提供服务的时候需要注意什么:
1、2.2以前版本不支持事务,2.2.x能支持事务但仅限于单机单库事务(目前处于3.x系列的测试版);
2、暂时不支持存储过程;
3、不适合从amoeba导数据的场景或者对大数据量查询的query并不合适(比如一次请求返回10w以上甚至更多数据的场合);
4、暂时不支持分库分表,amoeba目前只做到分数据库实例,每个被切分的节点需要保持库表结构一致;
二、Amoeba的安装配置
由于amoeba是java程序所开发,所以首先我们得配置java运行环境,再去下载amoeba来安装,我用的OS是ubuntu12.04;
A、安装jdk准备环境:
1、下载文件,jdk我选用的是jdk6系列的
http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-419409.html#jdk-6u45-oth-JPR
2、赋予执行权限,在 terminal 中输入:
chmod +x jdk-6u45-linux-x64.bin
3、解压,在 terminal 中输入:
./jdk-6u45-linux-x64.bin
4、创建 jvm 目录,在 terminal 中输入:
sudo mkdir /usr/lib/jvm -pv
5、移动解压文件,在 terminal 中输入:
sudo mv ~/jdk1.6.0_45/ /usr/lib/jvm/
6、启用 jdk 6,在 terminal 中输入:
sudo ln -s -b /usr/lib/jvm/jdk1.6.0_45/jre/bin/java /etc/alternatives/java
sudo ln -s -b /usr/lib/jvm/jdk1.6.0_45/jre/bin/java /usr/bin/java
7、修改环境变量
# vim ~/.bashrc
添加以下内容
# add java set
# export JAVA_HOME=/usr/lib/jvm/jdk1.6.0_45
# export JRE_HOME=${JAVA_HOME}/jre
# export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
# export PATH=${JAVA_HOME}/bin:$PATH
重新编译.bashrc
source ~/.bashrc
8、检验,在 terminal 中输入:
java -version
结果应显示:java version "1.6.0_45",再测试java_home设置是否有效
# echo $JAVA_HOME,如果显示 /usr/lib/jvm/jdk1.6.0_45 则表示java环境设置OK,否则后面运行amoeba时候会报 java_home 没有设置的错误;
B、下载并安装amoeba
1、下载amoeba,我在此测试中用的是2.2.0稳定版本
http://sourceforge.net/projects/amoeba/files/Amoeba%20for%20mysql/2.2.x/
2、解压至制定目录
# sudo mkdir /usr/local/amoeba-mysql-2.2.0 -pv
# sudo tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba-mysql-2.2.0
3、配置amoeba
在conf文件夹里可以看到不少以.xml后缀结尾文件,其中amoeba.xml是对amoeba代理的配置,dbServers.xml是对后端service的配置,rule.xml可以定义高级设置比如数据的水平、垂直切割等,log4j.xml定义日志等
3.1、配置amoeba.xml
# sudo vim /usr/local/amoeba/conf/amoeba.xml
在此配置中主要是配置连接到proxy 的端口、用户名、密码、ipAddress,以及路由(queryRouter)的默认池(defaultPool)、读池(readPool)、写池(writePool)
# <property name="port">3306</property> 提供给client连接的端口,默认为8066
# <property name="user">root</property> 提供给client连接的用户名
# <property name="password">amoebapass</property> 提供给client连接的密码,这里amoeba的配置与mysql-proxy不同,mysql-proxy用的是后端数据的连接账号及密码
# <property name="ipAddress">0.0.0.0</property> 指定本机服务地址,如果本机所有地址都允许的话就设置为0.0.0.0
# <property name="defaultPool">node-s1</property> 指定主节点(能写的那台server)
# <property name="writePool">node-s1</property>
# <property name="readPool">readPool</property> 指定后端dbServers设置的读池
3.2、配置dbServers.xml
此配置主要定义代理连接后端servers的配置,比如定义那些server,那些定义为写,那些定义为读,读池轮询设置等
负责写的后端server(master服务器),当然也可以读
<dbServer name="node-s1" parent="abstractServer">
<factoryConfig>
<property name="ipAddress">172.16.5.11</property>
<property name="password">123456</property> 此处如果写库跟读库密码一致,可以写在上面公共段,这里会继承上面的设置
</factoryConfig>
</dbServer>
负责读的后端server(slave服务器)
<dbServer name="node-s2" parent="abstractServer">
<factoryConfig>
<property name="ipAddress">172.16.5.12</property>
<property name="password">123456</property>
</factoryConfig>
</dbServer>
读池的设置
<dbServer name="readPool" virtual="true">
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA--> 1轮询,2
<property name="loadbalance">1</property>
<property name="poolNames">node-s2,node-s2,node-s2,node-s1</property> 表示读写服务器对读进行3:1的负载
</poolConfig>
</dbServer>
4、启动amoeba
# sudo /usr/local/amoeba/bin/amoeba start
测试在后台运行 sudo /usr/local/amoeba/bin/amoeba start & 怎么都不行,没办法只能切换到root用户下运行 /usr/local/amoeba/bin/amoeba &
不清楚amoeba以守护进程模式启动加什么参数,是否有此功能,有空再去查查~
# ss -tanl (查看3306端口是否启动)
# /usr/bin/mysql -uroot -pamoebapass -h172.16.5.112
5、到各后端servers抓包测试读写分离效果
测试100个查询,再在各后端server上抓包检查读的效果
# for I in {1..100}; do /usr/local/mysql/bin/mysql -uroot -pamoebapass -h172.16.5.112 -e 'select * from mydb1.table1 where id = 1;'; done
# tcpdump -i eth0 -s0 -nn -A tcp dst port 3306 and ip dst host 172.16.100.11
-i 表示监听那一个网卡 any代表所有
-s0 表示截取数据,s0抓整个包
-n 表示数字显示主机名
-nn 表示数字显示主机名跟端口号
-X 表示以ASCII码显示内容
-XX 表示以ASCII及16进制码显示内容
-A 表示显示原内容
-w 表示将抓取的内容保存到某个位置
-r 表示导入某
src 源端口、地址
dst 目标端口、地址
(备注:http://docs.hexnova.com/amoeba/ Amoeba使用指南 )
(http://www.guokr.com/blog/475765/ mysql中间件评估研究(Atlas,cobar,TDDL))