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系列的

       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  目标端口、地址

   (备注:   Amoeba使用指南 )

   (   mysql中间件评估研究(Atlas,cobar,TDDL))