amoeba实现MySQL读写分离

测试环境:
centos6+mysql5.1+amoeba2.2.0

测试拓扑:

qq20161206144252

#在mysql-amoeba上操作
amoeba需要java的支持,首先安装java

#下载解压安装jdk

mkdir -p /usr/local/amoeba
cd /usr/local/amoeba
tar xf jdk-8u111-linux-x64.tar.gz

[root@webserve1 jdk]# tail -3 /etc/profile
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin

[root@webserve1 jdk]# java -version
java version “1.8.0_111”
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
mkdir -p /usr/local/amoeba
cd /usr/local/amoeba/
wget http://sourceforge.net/projects/amoeba/files/Amoeba%20for%20mysql/2.2.x/amoeba-mysql-binary-2.2.0.tar.gz
tar xf amoeba-mysql-binary-2.2.0.tar.gz

#amoeba的启动
nohup /usr/local/amoeba/bin/amoeba start &
#amoeba的停止
/usr/local/amoeba/bin/amoeba stop

#amoeba开机自启动
[root@webserve1 ~]# tail -2 /etc/rc.local
#amoeba的启动
nohup /usr/local/amoeba/bin/amoeba start &

amoeba的主要就是对这个2个配置文件做操作[amoeba.xml和dbServers.xml]
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.net.ServerableConnectionManager">
 <!-- port -->
 <property name="port">1107</property>
 
 <!-- bind ipAddress -->
 
 <property name="ipAddress">192.168.10.252</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">99web</property>
 
 <property name="password">99web</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>
 
 <!-- server class must implements com.meidusa.amoeba.service.Service -->
 <service name="Amoeba Monitor Server" class="com.meidusa.amoeba.monitor.MonitorServer">
 <!-- port -->
 <!-- default value: random number
 <property name="port">9066</property>
 -->
 <!-- bind ipAddress -->
 <property name="ipAddress">127.0.0.1</property>
 <property name="daemon">true</property>
 <property name="manager">${clientConnectioneManager}</property>
 <property name="connectionFactory">
 <bean class="com.meidusa.amoeba.monitor.net.MonitorClientConnectionFactory"></bean>
 </property>
 
 </service>
 
 <runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">
 <!-- proxy server net IO Read thread size -->
 <property name="readThreadPoolSize">20</property>
 
 <!-- proxy server client process thread size -->
 <property name="clientSideThreadPoolSize">30</property>
 
 <!-- mysql server data packet process thread size -->
 <property name="serverSideThreadPoolSize">30</property>
 
 <!-- per connection cache prepared statement size -->
 <property name="statementCacheSize">500</property>
 
 <!-- query timeout( default: 60 second , TimeUnit:second) -->
 <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="clientConnectioneManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
 <property name="subManagerClassName">com.meidusa.amoeba.net.ConnectionManager</property>
 <!-- 
 default value is avaliable Processors 
 <property name="processors">5</property>
 -->
 </connectionManager>
 <connectionManager name="defaultManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
 <property name="subManagerClassName">com.meidusa.amoeba.net.AuthingableConnectionManager</property>
 
 <!-- 
 default value is avaliable Processors 
 <property name="processors">5</property>
 -->
 </connectionManager>
 </connectionManagerList>
 
 <!-- default using file loader -->
 <dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader">
 <property name="configFile">${amoeba.home}/conf/dbServers.xml</property>
 </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>
 <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">readservers</property>
 
 <property name="needParse">true</property>
 </queryRouter>
</amoeba:configuration>

 

dbServers.xml.xml完整的配置文件如下:

<?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 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">99web</property>


<property name="password">99web</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="testOnReturn">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>

<dbServer name="master" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.10.230</property>
</factoryConfig>
</dbServer>

<dbServer name="slave" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.10.229</property>
</factoryConfig>
</dbServer>

<dbServer name="readservers" 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">master,slave</property>
</poolConfig>
</dbServer>

</amoeba:dbServers>

 

登陆mysql-amoeba:
mysql -h 192.168.10.252 -u99web -p’99web’ -P 1107

登陆master:
mysql -uroot -p’123456′

登陆slave:
mysql -uroot -p’123456′

测试之前先要保证amoeba-server有访问两个主从服务器test库的权限,在主从mysql上都执行:
grant all on test.* to 99web@’192.168.10.%’ identified by ’99web’;
flush privileges;

ps:主库和从库使用相同的用户,但授予不同的权限,这样就显得更专业
主库:
grant all on 99health.* to 99web@”192.168.1.%” identified by “!@#$mysql99″;
从库:
grant select on 99health.* to 99web@”192.168.1.%” identified by ‘!@#$mysql99’;

测试步骤:
还没有停掉从同步之前,创建一个表:
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上来测试读写:

###第一次执行显示在主上读取的数据!
mysql> select * from zhang;
+——+——-+—————-+
| id | name | address |
+——+——-+—————-+
| 1 | zhang | this_is_master |
+——+——-+—————-+
1 row in set (0.01 sec)
####第二次执行select语句显示是在从上读取的数据
mysql> select * from zhang;
+——+——-+—————+
| id | name | address |
+——+——-+—————+
| 2 | zhang | this_is_slave |
+——+——-+—————+
1 row in set (0.00 sec)
主从库的读比例是1:1
###插入一条数据,
mysql> insert into zhang values(‘3′,’hhh’,’test_write’);
Query OK, 1 row affected (0.01 sec)

###我们可以看到插入的数据被添加到了主上!
mysql> select * from zhang;
+——+——-+—————-+
| id | name | address |
+——+——-+—————-+
| 1 | zhang | this_is_master |
| 3 | hhh | test_write |
+——+——-+—————-+
2 rows in set (0.00 sec)

###从上还是没有插入,因为执行了stop slave;
mysql> select * from zhang;
+——+——-+—————+
| id | name | address |
+——+——-+—————+
| 2 | zhang | this_is_slave |
+——+——-+—————+
1 row in set (0.00 sec

大家可能会想到,我们加入只有两台数据库服务器,一台主,一台从,按照上面的配置只能是主和从的读取比率是1:1,而写又全部在主上进行,这样主的压力就很大了,所以如果能让主和从的读设置权重,比如设置成1:3,这样就可以很好的解决主从不压力均衡的问题!通过研究确实可以!
配置就是将上面的读的池的配置更改一下:
将server1,server2更改成
server1,server2,server2,server2

参考:http://blog.chinaunix.net/uid-20639775-id-154600.html

PS.在实际的生产环境下,默认的amoeba的配置参数可能需要调整和优化一下,同时要考虑服务器的硬件配置,网站的规模和并发。以下是我的线上的参数设置:

a.设置Amoeba启动脚本来调整内存参数

在Amoeba的启动脚本中找到DEFAULT_OPTS变量所在的行

DEFAULT_OPTS=”-server -Xms1024m -Xmx1024m -Xss256k”

一般在server端的应用程序上面设置-Xms 跟 -Xmx的值一致将有效提升应用程序的性能。 -Xms小于等于-Xmx的值。
将DEFAULT_OPTS设置如上将使得JVM获得更大的内存从而提升Amoeba的性能。

b.配置amoeba.xml的多线程相关选项

 ...
 <runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">
 <!-- proxy server net IO Read thread size -->
 <property name="readThreadPoolSize">500</property>-1
 
 <!-- proxy server client process thread size -->
 <property name="clientSideThreadPoolSize">300</property> -2
 
 <!-- mysql server data packet process thread size -->
 <property name="serverSideThreadPoolSize">300</property> -3
 
 <!-- per connection cache prepared statement size -->
 <property name="statementCacheSize">500</property> -4
 
 <!-- query timeout( default: 60 second , TimeUnit:second) -->
 <property name="queryTimeout">90</property> -5
 </runtime>
 ...

1.readThreadPoolSize –用于处理客户端连接发送过来的数据,跟数据库服务器返回的数据的线程数 量这个可以根据客户端连接数量来调整。
2.clientSideThreadPoolSize –在读线程读完客户端的请求数据包以后,这个线程将会接手处理具体 的业务逻辑(比如:解析SQL、SQL 路由)。
3.serverSideThreadPoolSize –在server端读取数据库返回的数据包,合并多数据库返回的数据,将数 据包发送到客户端。
4.statementCacheSize –连接池缓存的Prepared Statement数量。
5.queryTimeout –语句执行超时时间设置。

c.调整读写buffersize的大小


<property name=”connectionFactory”>
<bean class=”com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory”>
<property name=”sendBufferSize”>1024</property>
<property name=”receiveBufferSize”>512</property>
</bean>
</property>

 

此条目发表在MySql分类目录,贴了, 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注