上一篇刚记录下MySQL的主从复制配置,这就要搞读取分离了,正好也记录下配置及遇到的小问题。
一、Amoeba 是什么
Amoeba(变形虫)项目,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户端透明。具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库、可并发请求多台数据库合并结果。
主要解决:
- 降低 数据切分带来的复杂多数据库结构
- 提供切分规则并降低 数据切分规则 给应用带来的影响
- 降低db 与客户端的连接数
- 读写分离
二、为什么要用Amoeba
目前要实现mysql的主从读写分离,主要有以下几种方案:
1、 通过程序实现,网上很多现成的代码,比较复杂,如果添加从服务器要更改多台服务器的代码。
2、 通过mysql-proxy来实现,由于mysql-proxy的主从读写分离是通过lua脚本来实现,目前lua的脚本的开发跟不上节奏,而写没有完美的现成的脚本,因此导致用于生产环境的话风险比较大,据网上很多人说mysql-proxy的性能不高。
3、 自己开发接口实现,这种方案门槛高,开发成本高,不是一般的小公司能承担得起。
4、 利用阿里巴巴的开源项目Amoeba来实现,具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库,并且安装配置非常简单。
三、快速架设amoeba,实现mysql主从读写分离
amoeba的前提条件:
- Java SE 1.5 或以上 Amoeba 框架是基于JDK1.5开发的,采用了JDK1.5的特性。
- 支持Mysql 协议版本10(mysql 4.1以后的版本)。
- 网络环境至少运行有一个mysql 4.1以上的服务(本文中使用的是MySQL5.5)
1、首先介绍下本文的实验环境。
- System: Windows
- Master mysql:192.168.1.194
- Slave mysql:192.168.1.223
- Amoeba server: 192.168.1.194
架构如如下所示:
本文只用了一个主、一个从服务器
2、安装配置mysql主从环境及用户,上一篇已介绍不再赘述,有需要烦请自行查找。
3、安装JDK环境
下载jdk1.5或者更新版本,地址 http://java.sun.com/javase/downloads/index.jsp
本文的是之前项目需要装的:jdk-8u151-windows-x64.exe
下载安装后,配置环境变量
4、下载解压Amoeba及配置代理读写分离
因为只有两台服务器,所以Amoeba安装在192.168.1.194上(即MySQL主服务器上)
本文使用2.0版本 请下载2.0
下载https://sourceforge.net/projects/amoeba/files/
修改配置文件:
1)、打开conf/ amoeba.xml配置文件,修改以下位置
这个service是提供给访问数据库的程序使用的.也就是别人连接数据库需要配置的东西
分别为,端口,默认为8066
用户名:可以随便写
密码:可以随便写
<!-- service class must implements com.meidusa.amoeba.service.Service -->
<service name="Amoeba for Mysql" class="com.meidusa.amoeba.net.ServerableConnectionManager">
<!-- port -->
<property name="port">8066</property>
<!-- bind ipAddress -->
<!-- <property name="ipAddress">192.168.1.194</property> -->
<property name="manager">${clientConnectioneManager}</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="authenticator">
<bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
<property name="user">root</property>
<property name="password">123456</property>
<property name="filter">
<bean class="com.meidusa.amoeba.server.IPAccessController">
<property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
</bean>
</property>
</bean>
</property>
</service>
最下边把注释打开,配置writePool,readPool,这里边对应的是dbServers.xml 配置文件里边的两个数据库dbServer的name
<!-- conf/rule.xml中的tableRule优先于此处的queryRouter,只有rule.xml中tableRule未匹配到数据库或表才次级匹配当前queryRouter -->
<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>
<property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
<property name="LRUMapSize">1500</property>
<!--这里配置了默认的数据库节点,一些除了SELECT\UPDATE\INSERT\DELETE的语句都会在defaultPool执行 -->
<property name="defaultPool">writePool</property>
<!--这里配置了数据库写库,通常配为Master,如这里就配置为之前定义的Master数据库 -->
<property name="writePool">writePool</property>
<!--这里配置了数据库读库,通常配为Slave或者Slave组成的数据库池,如这里就配置conf/dbServer.xml的virtualSlave数据库池-->
<property name="readPool">virtualslave</property>
<property name="needParse">true</property>
</queryRouter>
打开dbServers.xml,配置 端口,用户名,密码
<!--配置数据库端口、用户名、密码,如两个服务器端口、用户名、密码不一致,需再增加一个以便于读写配置继承;本次两个服务器数据库均一致,所以只配置了一个-->
<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 schema -->
<property name="schema">test</property>
<!-- mysql user -->
<property name="user">root</property>
<!-- mysql password -->
<property name="password">123456</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="testWhileIdle">true</property>
</poolConfig>
</dbServer>
增加读写的不同dbServer, 这里边的name对应上一个配置文件(amoeba.xml)里边的server 读写的配置; 192.168.1.194是写入数据库,192.168.1.223是读取数据库,因为两个库的用户名密码都一样的,所以直接继承上面的server配置的信息就可以了.如果不一样需要单独配置.最下边是连接池配置.
<!-- 写入服务器-->
<dbServer name="writePool" parent="abstractServer" virtual="true">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.1.194</property>
</factoryConfig>
</dbServer>
<!-- 读取服务器 -->
<dbServer name="readPool" parent="abstractServer" virtual="true">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.1.223</property>
</factoryConfig>
</dbServer>
<!-- 交替读写 -->
<dbServer name="virtualslave" virtual="true">
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<!-- Loadbalancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
<property name="loadbalance">1</property>
<!--Separated by commas,such as: server1,server2,server1 -->
<property name="poolNames">writePool,readPool,readPool,readPool</property>
</poolConfig>
</dbServer>
然后保存,启动
打开cmd 切换到Amoeba目录下的bin目录,执行如下命令启动:
amoeba start
如果配置环境变量了,可以直接启动.否则需要切换到程序目录下.
5、 测试
测试之前先要保证amoeba-server有访问两个主从服务器test库的权限,在主从mysql上都执行:
grant all on test.* to 'root'@'192.168.1.%' identified by '123456';
测试的时候和平时使用一样,amoeba-mysql对应用透明,就是个mysql的代理!
登录mysql使用如下命令(用户名密码和上面配置(amoeba.xml中authenticator下的user和password)的要一致):
mysql -uroot -p123456 -h192.168.1.194 -P8066
登录上去后,为了测试读和写必须,先把mysql的主从复制停掉,才能更清楚地看出读写的服务器是哪台,在从服务器上使用
stop slave;
登录到amoeba-mysql上,使用命令
mysql -uroot -ppassword -h192.168.1.159 -P8066
然后执行写和读操作,查看写的是哪台服务器,读的是哪台服务器,
实验结果显示:写只在主上进行,读在主和从都进行,比率是1:1
1)、测试步骤:
还没有停掉从同步之前,创建一个表:
create table zhang (id int(10) ,name varchar(10),address varchar(20));
在从服务器上执行
stop slave;
然后在主从服务器数据库上各插入一条不同数据(供测试读的时候用),
在主上插入:
insert into zhang values('1','zhang','this_is_master');
在从上插入:
insert into zhang values('2','zhang','this_is_slave');
接下来通过登录amoeba-mysql上来测试读写:
—-至此,基于Amoeba的MySQL读取分离基本配置完成,以后遇到问题会再次补充。
—-另外,关于Amoeba的数据切分规则配置认知还不完全,了解后有机会也会进行补充。