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

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:




服务器配置:

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 ALL PRIVILEGES ON *.* TO 'amoeba'@'192.168.240.130' IDENTIFIED BY 'amoeba' WITH  GRANT OPTION;

mysql> FLUSH  PRIVILEGES;

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


wKiom1fyVxPDej7tAAEqMnQoOWY154.png


图片来源于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">amoeba</property>

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

                    <property name="password">amoeba</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

wKiom1fycTvy7RWqAAA78gAiM3k690.png-wh_50

登录master

wKiom1fycQbxGnqoAAAptO_WP-g391.png-wh_50


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

wKioL1fycYfi-wrnAAAmGK9H4XI594.png-wh_50


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

wKiom1fycouiDHShAAA1hRUQB0s784.png-wh_50


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

wKiom1fyfEPTTs2AAABjAobs7qI668.png

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


至此目的算是达到了。


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


1.提示:ERROR:JAVA_HOME environment variable is not set

[root@chenllcentos ~]dir /usr/java/    看看是什么版本号,我的是jdk1.8.0_91,没有就去下载安装吧。要1.5以上http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html


[root@chenllcentos ~]vim /etc/profile       在文件最末添加以下三行。

JAVA_HOME=/usr/java/jdk1.8.0_91/
PATH=$PATH:JAVA_HOME/bin 
export JAVA_HOME PATH 


2.启动时提示:

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的帐号的,这样也方便管理。






      本文转自笔下生辉  51CTO博客,原文链接:http://blog.51cto.com/752030200/1858652,如需转载请自行联系原作者




相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
13天前
|
缓存 NoSQL 关系型数据库
13- Redis和Mysql如何保证数据⼀致?
该内容讨论了保证Redis和MySQL数据一致性的几种策略。首先提到的两种方法存在不一致风险:先更新MySQL再更新Redis,或先删Redis再更新MySQL。第三种方案是通过MQ异步同步以达到最终一致性,适用于一致性要求较高的场景。项目中根据不同业务需求选择不同方案,如对一致性要求不高的情况不做处理,时效性数据设置过期时间,高一致性需求则使用MQ确保同步,最严格的情况可能涉及分布式事务(如Seata的TCC模式)。
37 6
|
20天前
|
SQL 关系型数据库 MySQL
轻松入门MySQL:保障数据完整性,MySQL事务在进销存管理系统中的应用(12)
轻松入门MySQL:保障数据完整性,MySQL事务在进销存管理系统中的应用(12)
|
27天前
|
关系型数据库 MySQL
elasticsearch对比mysql以及使用工具同步mysql数据全量增量
elasticsearch对比mysql以及使用工具同步mysql数据全量增量
21 0
|
29天前
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
20 1
|
29天前
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
15 1
|
26天前
|
关系型数据库 MySQL
MySQL查询当天昨天明天本月上月今年等数据
MySQL查询当天昨天明天本月上月今年等数据
19 2
|
26天前
|
关系型数据库 MySQL 开发工具
MySQL分组后,组内排序,然后取每组的第一条数据
MySQL分组后,组内排序,然后取每组的第一条数据
15 1
|
27天前
|
canal SQL 关系型数据库
MySQL数据直接实时同步到ES
MySQL数据直接实时同步到ES
32 0
|
29天前
|
Java 数据库连接 mybatis
Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
19 1
|
29天前
Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)
Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)
15 1