首页 > 代码库 > 实现mysql 数据集群的读写分离之 amoeba

实现mysql 数据集群的读写分离之 amoeba

服务器配置:

amoeba    :192.168.240.130

master写服务器:192.168.240.129

slave读服务器 :192.168.240.128


mysql主从配置............略,可参照:http://752030200.blog.51cto.com/8936921/1853460


Amoeba数据库代理

前提条件应该把所有数据库节点的密码进行统一,并允许将要配置的amoeba的IP进行连接。


以下说明和配置文件信息引用自https://my.oschina.net/u/1169079/blog/390726 并自己在dbServer.xml和amoeba.xml部分做注释,用蓝色字体标识


mysql> GRANT ALLPRIVILEGES ON *.* TO ‘root‘@‘192.168.240.130‘ IDENTIFIED BY ‘root‘ WITH GRANTOPTION;

mysql> FLUSHPRIVILEGES;

Amoeba作为数据库代理,以中间件的形式存在,拓扑图如下所示:


技术分享


图片来源于Amoeba官网。


目前Amoeba for Mysql最新版本为amoeba-mysql-3.0.5-RC-distribution.zip。

安装过程很简单,只需要将zip压缩包解压至/usr/local/即可。若没有安装zip和unzip,可以通过centOS yum安装。


[root@chenllcentos ~]# yum -y install zip unzip

接下来,解压Amoeba压缩包。


[root@chenllcentos ~]# unzip amoeba-mysql-3.0.5-RC-distribution.zip

[root@chenllcentos ~]# cp -rf amoeba-mysql-3.0.5-RC /usr/local

用 Amoeba 实现 mysql 读写分离,只需要分别对dbServers.xml和amoeba.xml两个配置文件进行配置即可,这有利于系统扩展和维护。


首先是配置dbServers.xml,主要是配置真实Mysql数据库连接信息。


<?xml version="1.0" encoding="gbk"?>

<!DOCTYPE amoeba:dbServers SYSTEM“dbserver.dtd”> <amoeba:dbServers xmlns:amoeba=“http://amoeba.meidusa.com/”>


    <!-- 

        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节点abstractive="true",包含Mysql的公共配置信息,其他dbServer节点都继承该节点 -->

<!-- 设置节点配置的继承结构,可以避免重复配置相同信息,减少配置文件冗余 -->

<dbServer name="abstractServer" abstractive="true">

    <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">

        <property name="connectionManager">${defaultManager}</property>

        <property name="sendBufferSize">64</property>

        <property name="receiveBufferSize">128</property>

 

        <!-- mysql port -->

        <!-- Mysql默认端口 -->

        <property name="port">3306</property>

 

        <!-- mysql schema -->

        <!-- 默认连接的数据库,若不存在需要事先创建,否则Amoeba启动报错 -->

        <property name="schema">test</property>

 

        <!-- mysql user  mysql用户名-->

        <property name="user">root</property>

       <!-- mysql password  mysql密码-->

        <property name="password">root</property>

    </factoryConfig>

 

    <poolConfig class="com.meidusa.toolkit.common.poolable.PoolableObjectPool">

        <property name="maxActive">500</property>

        <property name="maxIdle">500</property>

        <property name="minIdle">1</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>

<!--以上是mysql节点公共信息设置-->

<!--下是真实MYSQL服务器master和slave相关信息-->

    <!-- master节点继承abstractServer -->

<dbServer name="master"  parent="abstractServer">

    <factoryConfig>

        <!-- mysql ip -->

        <!-- master数据库主机地址 -->

        <property name="ipAddress">192.168.240.129</property>

    </factoryConfig>

</dbServer>

 

        <!-- slave 节点继承abstractServer -->

<dbServer name="slave"  parent="abstractServer">

    <factoryConfig>

        <!-- mysql ip -->

       <!-- slave数据库主机地址 -->

        <property name="ipAddress">192.168.240.128</property>

    </factoryConfig>

</dbServer>

 

    <!--配置 读取数据库节点池 -->

<dbServer name="readPool" virtual="true">

    <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">

        <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->

        <property name="loadbalance">1</property>

 

        <!-- Separated by commas,such as: server1,server2,server1 -->

        <property name="poolNames">slave</property>

    </poolConfig>

</dbServer>

</amoeba:dbServers>


可以看出,对dbServers.xml文件的配置,主要就是对dbServer节点的配置。其中,readPool节点需要特别注意,因为Amoeba实现读写分离就是根据它来实现。


接下来是 amoeba.xml,主要是配置代理数据库连接信息。


<?xml version="1.0" encoding="gbk"?>

 

<!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">

<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">

 

    <proxy>

 

        <!-- service class must implements com.meidusa.amoeba.service.Service -->

        <service name="Amoeba for Mysql" class="com.meidusa.amoeba.mysql.server.MySQLService">

            <!-- port -->

            <property name="port">8066</property>

 

            <!-- bind ipAddress amoeba 服务IP 单网卡可以不配置,双网卡必须配置-->

           

            <property name="ipAddress">192.168.240.130</property>             

            <property name="connectionFactory">

                <bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory">

                    <property name="sendBufferSize">128</property>

                    <property name="receiveBufferSize">64</property>

                </bean>

            </property>

 

            <property name="authenticateProvider">

                <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">

                  <!—-登录amoeba的用户名 -->

                    <property name="user">root</property>

                          <!—-登录amoeba的密码 -->

                    <property name="password">root</property>

                         <!—-设置amoeba过滤信息(安全控制) -->

                    <property name="filter">

                        <bean class="com.meidusa.toolkit.net.authenticate.server.IPAccessController">

                            <property name="ipFile">${amoeba.home}/conf/access_list.conf</property>

                   <!--允许登录amoeba的列表文件 -->

                        </bean>

                    </property>

                </bean>

            </property>

 

        </service>

 

        <runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">

 

            <!-- proxy server client process thread size 设置客户端及数据库服务器端的线程数-->

            <property name="executeThreadSize">128</property>

 

            <!-- per connection cache prepared statement size  -->

            <property name="statementCacheSize">500</property>

 

            <!-- default charset 设置amoeba默认字符集-->

            <property name="serverCharset">utf8</property>

             

   <!-- query timeout( default: 60 second , TimeUnit:second) 设置登录amoeba超时时间,单位秒-->

            <property name="queryTimeout">60</property>

        </runtime>

 

    </proxy>

 

    <!-- 

        Each ConnectionManager will start as thread

        manager responsible for the Connection IO read , Death Detection

    -->

    <connectionManagerList>

        <connectionManager name="defaultManager" class="com.meidusa.toolkit.net.MultiConnectionManagerWrapper">

            <property name="subManagerClassName">com.meidusa.toolkit.net.AuthingableConnectionManager</property>

        </connectionManager>

    </connectionManagerList>

 

        <!-- default using file loader -->

    <dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader">

        <property name="configFile">${amoeba.home}/conf/dbServers.xml</property>

                          <!—-调用dbServers.xml配置文件 -->

    </dbServerLoader>

 

    <queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">

        <property name="ruleLoader">

            <bean class="com.meidusa.amoeba.route.TableRuleFileLoader">

                <property name="ruleFile">${amoeba.home}/conf/rule.xml</property>

                <property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>

            </bean>

        </property>

             <!—- sql解析功能调用-->

        <property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>

        <property name="LRUMapSize">1500</property>

           <!—- 设置默认数据库节点,当然是写的节点-->

        <property name="defaultPool">master</property>

             <!—- 设置写数据库节点-->

        <property name="writePool">master</property>

              <!—-设置只读数据库节点 -->

        <property name="readPool">readPool</property>

     <!—-设置是否需要解析sql语句,当然是要的(true),要不怎么实现读写分离呢,是吧 -->

        <property name="needParse">true</property>

    </queryRouter>

</amoeba:configuration>

在amoeba.xml中,主要完成连接信息和SQL路由配置。在queryRouter节点中,通过配置writePool和readPool可以实现读写分离。

配置完成后,重启Amoeba。


[root@chenllcentos ~]# /usr/local/amoeba-mysql-3.0.5-RC/bin/shutdown

[root@chenllcentos ~]# /usr/local/amoeba-mysql-3.0.5-RC/bin/launcher

至此,Mysql主从复制和使用Amoeba实现数据库读写分离全部配置完成。


启动amoeba:

[root@chenllcentos ~]# chmod +x /usr/local/amoeba-mysql-3.0.5-RC/bin/launcher

[root@chenllcentos ~]# /usr/local/amoeba-mysql-3.0.5-RC/bin/launcher&

启动amoeba需要将amoeba进程丢到后台,要不会一直停留在前台,做不了其他事。这时可以用CTRL+Z 暂停amoeba进程,再输入bg命令进行后台继续运行。


读写分离验证

思 路:在不进行主从备份的情况下,登录amoeba进行新建一个数据库,这时应该只要master写服务器存在新建的数据库,从是没有的。然后登录slave服务器在上面新建一个数据库AA,然后在amoeba上进程use AA 是可以切换数据库的,但是是不能操作的。


登录amoeba :

[root@chenllcentos ~]mysql -u root -p root -h192.168.240.130 -P8066

技术分享

登录master

技术分享


登录slave,可以看到slave 上并没有刚才新建master数据库。

技术分享


现在登录slave节点,并新建一个slave数据库

技术分享


登录amoeba查看,是否有slave这个数据库,再试试是否可以切换到slave这个数据库:

技术分享

从上面可以看到,虽然show不出slave数据库 ,但是可以切换到slave数据库。虽然看起来有点矛盾,因为show也算是查询的一种操作,却没有从slave节点上显示slave数据库,这点应该是dbServer.xml里将master写服务器设置,而不是将slave读服务器设为默认造成的。


至此目的算是达到了。


附两个实验中遇到的错误信息及解决方法:


1.启动时提示:

The stack size specified is too small, Specify at least 228k

Error: Could not create the Java Virtual Machine.

Error: A fatal exception has occurred. Program will exit

从错误文字上看,应该是由于stack size太小,导致JVM启动失败


其实Amoeba已经考虑到这个问题,并将JVM参数配置写在属性文件里。现在,让我们通过该属性文件修改JVM参数。

修改jvm.properties文件JVM_OPTIONS参数。


[root@chenllcentos ~]# vi /usr/local/amoeba-mysql-3.0.5-RC/jvm.properties

将内容:

JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss196k -XX:PermSize=16m -XX:MaxPermSize=96m"

替换为:


JVM_OPTIONS="-server -Xms1024m -Xmx1024m -Xss256k -XX:PermSize=16m -XX:MaxPermSize=96m"


2.可以登录amoeba却不可能做任何操作,哪怕只是show databases; 也会提示出错信息:
ERROR 1044 (42000): poolName=multiPool, no valid pools 或其他

查看amoeba安装目录下的日志文件root.log,发现在大量的error:Access denied for user 

‘root‘@‘192.168.240.130‘ (using password: YES),hashCode=1496580638,由此可以推断是amoeba连接上mysql服务节点没有权限而造成拒绝访问。


解决办法是更新各mysql节点中amoeba.xml文件里的对应的用户和密码信息。


mysql> update user set password=password("root") where user="root";


这里是因为amoeba的登录信息和mysql的节点是一致的,所以就更新root的信息了,其实还是有必要让amoeba的帐号区别于mysql的帐号的,这样也方便管理。


本文出自 “烂笔头博客” 博客,转载请与作者联系!

实现mysql 数据集群的读写分离之 amoeba