同事 Struct Chen 的 Amoeba For MySQL 项目已经 出来不短时间了,可一直没有时间好好体验,最近一直在做一些软件和硬件的功能以及性能相关的测试工作,Amoeba For MySQL自然也将被列入计划之内。
对 Amoeba For MySQL 的测试到目前位置主要还是功能方面的测试,配置了一套四台机器的环境:
Server A: Amoeba Server
Server B: MySQL Master
Server C: MySQL Slave1
Server D: MySQL Slave2
软件环境:RHEL5.2 (X86_64),JAVA 1.5.0_16, Amoeba For MySQL 0.31
测试功能:
1、读写分离
2、数据垂直切分
3、数据水平切分
amoeba.xml配置如下:
< ?xml version="1.0" encoding="gbk"?>
< !DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba :configuration xmlns:amoeba="http://amoeba.meidusa.com/">
<server>
<property name="port">8066</property>
<property name="ipAddress">10.0.38.21</property>
<!-- proxy server net IO Read thread size -->
<property name="readThreadPoolSize">500</property>
<!-- proxy server client process thread size -->
<property name="clientSideThreadPoolSize">500</property>
<!-- mysql server data packet process thread size -->
<property name="serverSideThreadPoolSize">500</property>
<!-- socket Send and receive BufferSize(unit:K) -->
<property name="netBufferSize">200</property>
<!-- Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). -->
<property name="tcpNoDelay">true</property>
<property name="user">user</property>
<property name="password">password</property>
</server>
<connectionmanagerlist>
<connectionmanager name="defaultManager">
<classname>com.meidusa.amoeba.net.AuthingableConnectionManager</classname>
</connectionmanager>
</connectionmanagerlist>
<dbserverlist>
<dbserver name="master">
<factoryconfig>
<classname>com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory</classname>
<property name="manager">defaultManager</property>
<property name="port">3306</property>
<property name="ipAddress">10.0.38.37</property>
<property name="schema">test</property>
<property name="user">root</property>
<property name="password">password</property>
</factoryconfig>
<poolconfig>
<classname>com.meidusa.amoeba.net.poolable.PoolableObjectPool</classname>
<property name="maxActive">500</property>
<property name="maxIdle">200</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="slave1">
<factoryconfig>
<classname>com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory</classname>
<property name="manager">defaultManager</property>
<property name="port">3306</property>
<property name="ipAddress">10.0.38.22</property>
<property name="schema">test</property>
<property name="user">root</property>
<property name="password">password</property>
</factoryconfig>
<poolconfig>
<classname>com.meidusa.amoeba.net.poolable.PoolableObjectPool</classname>
<property name="maxActive">500</property>
<property name="maxIdle">200</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="slave2">
<factoryconfig>
... ...
</factoryconfig>
<poolconfig>
... ...
</poolconfig>
</dbserver>
<dbserver name="virtualSlave" virtual="true">
<poolconfig>
<classname>com.meidusa.amoeba.server.MultipleServerPool</classname>
<!-- 1=ROUNDROBIN , 2=WEIGHTBASED -->
<property name="loadbalance">1</property>
<property name="poolNames">slave1,slave2</property>
</poolconfig>
</dbserver>
</dbserverlist>
<queryrouter>
<classname>com.meidusa.amoeba.mysql.parser.MysqlQueryRouter</classname>
<property name="ruleConfig">${amoeba.home}/conf/rule.xml</property>
<property name="functionConfig">${amoeba.home}/conf/functionMap.xml</property>
<property name="ruleFunctionConfig">${amoeba.home}/conf/ruleFunctionMap.xml</property>
<property name="LRUMapSize">1500</property>
<property name="defaultPool">master</property>
<property name="writePool">master</property>
<property name="readPool">virtualSlave</property>
<property name="needParse">true</property>
</queryrouter>
</amoeba>
< !DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba :configuration xmlns:amoeba="http://amoeba.meidusa.com/">
<server>
<property name="port">8066</property>
<property name="ipAddress">10.0.38.21</property>
<!-- proxy server net IO Read thread size -->
<property name="readThreadPoolSize">500</property>
<!-- proxy server client process thread size -->
<property name="clientSideThreadPoolSize">500</property>
<!-- mysql server data packet process thread size -->
<property name="serverSideThreadPoolSize">500</property>
<!-- socket Send and receive BufferSize(unit:K) -->
<property name="netBufferSize">200</property>
<!-- Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). -->
<property name="tcpNoDelay">true</property>
<property name="user">user</property>
<property name="password">password</property>
</server>
<connectionmanagerlist>
<connectionmanager name="defaultManager">
<classname>com.meidusa.amoeba.net.AuthingableConnectionManager</classname>
</connectionmanager>
</connectionmanagerlist>
<dbserverlist>
<dbserver name="master">
<factoryconfig>
<classname>com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory</classname>
<property name="manager">defaultManager</property>
<property name="port">3306</property>
<property name="ipAddress">10.0.38.37</property>
<property name="schema">test</property>
<property name="user">root</property>
<property name="password">password</property>
</factoryconfig>
<poolconfig>
<classname>com.meidusa.amoeba.net.poolable.PoolableObjectPool</classname>
<property name="maxActive">500</property>
<property name="maxIdle">200</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="slave1">
<factoryconfig>
<classname>com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory</classname>
<property name="manager">defaultManager</property>
<property name="port">3306</property>
<property name="ipAddress">10.0.38.22</property>
<property name="schema">test</property>
<property name="user">root</property>
<property name="password">password</property>
</factoryconfig>
<poolconfig>
<classname>com.meidusa.amoeba.net.poolable.PoolableObjectPool</classname>
<property name="maxActive">500</property>
<property name="maxIdle">200</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="slave2">
<factoryconfig>
... ...
</factoryconfig>
<poolconfig>
... ...
</poolconfig>
</dbserver>
<dbserver name="virtualSlave" virtual="true">
<poolconfig>
<classname>com.meidusa.amoeba.server.MultipleServerPool</classname>
<!-- 1=ROUNDROBIN , 2=WEIGHTBASED -->
<property name="loadbalance">1</property>
<property name="poolNames">slave1,slave2</property>
</poolconfig>
</dbserver>
</dbserverlist>
<queryrouter>
<classname>com.meidusa.amoeba.mysql.parser.MysqlQueryRouter</classname>
<property name="ruleConfig">${amoeba.home}/conf/rule.xml</property>
<property name="functionConfig">${amoeba.home}/conf/functionMap.xml</property>
<property name="ruleFunctionConfig">${amoeba.home}/conf/ruleFunctionMap.xml</property>
<property name="LRUMapSize">1500</property>
<property name="defaultPool">master</property>
<property name="writePool">master</property>
<property name="readPool">virtualSlave</property>
<property name="needParse">true</property>
</queryrouter>
</amoeba>
rule.xml配置:
< ?xml version="1.0" encoding="gbk"?>
< !DOCTYPE amoeba:rule SYSTEM "rule.dtd">
<amoeba :rule xmlns:amoeba="http://amoeba.meidusa.com/">
<tablerule name="test_horiz" schema="test" defaultPools="master">
<rule name="rule1">
<parameters>ID</parameters>
<expression>< ![CDATA[ ID <= 100000000]]></expression>
<defaultpools>master</defaultpools>
<readpools>slave1</readpools>
<writepools>master</writepools>
</rule>
<rule name="rule2">
<parameters>ID</parameters>
<expression>< ![CDATA[ ID between 100000001 and 200000000 ]]></expression>
<defaultpools>master</defaultpools>
<writepools>master2</writepools>
<readpools>slave2</readpools>
</rule>
<rule name="rule3">
<parameters>ID</parameters>
<expression>< ![CDATA[ ID > 200000000 ]]></expression>
<defaultpools>master</defaultpools>
</rule>
</tablerule>
<tablerule name="master" schema="test" defaultPools="master"/>
<tablerule name="slave1" schema="test" defaultPools="slave1"/>
<tablerule name="slave2" schema="test" defaultPools="slave2"/>
<tablerule name="master" schema="t" defaultPools="master"/>
</amoeba>
< !DOCTYPE amoeba:rule SYSTEM "rule.dtd">
<amoeba :rule xmlns:amoeba="http://amoeba.meidusa.com/">
<tablerule name="test_horiz" schema="test" defaultPools="master">
<rule name="rule1">
<parameters>ID</parameters>
<expression>< ![CDATA[ ID <= 100000000]]></expression>
<defaultpools>master</defaultpools>
<readpools>slave1</readpools>
<writepools>master</writepools>
</rule>
<rule name="rule2">
<parameters>ID</parameters>
<expression>< ![CDATA[ ID between 100000001 and 200000000 ]]></expression>
<defaultpools>master</defaultpools>
<writepools>master2</writepools>
<readpools>slave2</readpools>
</rule>
<rule name="rule3">
<parameters>ID</parameters>
<expression>< ![CDATA[ ID > 200000000 ]]></expression>
<defaultpools>master</defaultpools>
</rule>
</tablerule>
<tablerule name="master" schema="test" defaultPools="master"/>
<tablerule name="slave1" schema="test" defaultPools="slave1"/>
<tablerule name="slave2" schema="test" defaultPools="slave2"/>
<tablerule name="master" schema="t" defaultPools="master"/>
</amoeba>
由于第一步主要还只是测试读写分离与数据的垂直切分,所以水平切分的规则设置的很简单,仅仅是按照ID的范围设置简单的规则。而设置一些更为复杂的规则。
总体测试效果还是比较满意的,预期的功能都全部正常,当然所用于测试的SQL语句也大都比较简单,主要还是根据当前工作中遇到的一些SQL。
这次测试没有进行性能测试,等后面再找时间测试一下,不知道有没有哪位朋友已经做过了相应的性能测试没?性能测试之后就要开始规划应用到某些应用上面去了

del.icio.us
网站重新开张了?挺好
开张了开张了,多谢捧场啊,哈哈
能具体讲讲这个读写分离是怎么实现的吗??拆表了?
TO Nova:
对于数据库层面来说,主要是通过MySQL Replication来实现数据复制之后,对外提供读写分离的服务。
但这对于应用系统来说是透明的,因为应用系统只有一个入口:Amoeba 对外提供的访问路径。
而对于应用端请求的Query,则是通过Amoeba来进行统一的解析,然后再将读的Query路由到提供读的Slave上,写的Query则路由到Master上。
TO 朝阳
也就是说,这个rule.xml的配置,是产生路由读写的配置文件吗?那这个可以起到负载的作用吗?比如Query的读,负载到读的slave上,来实现均衡的读操作?
TO Nova:
当然可以有负载均衡的作用,多个slave之间可以有多种负载均衡策略,如ROUNDROBIN,WEIGHTBASED等
slave和master之间可能会有延时,那么读写分流之后,读取slave的结果可能就会有问题。这个问题怎么解决呢?多谢
TO wayne:
对于这个问题,其实与Amoeba并没有多大实际的关系。当然,也确实是一个问题。一般来说,只要Slave主机上的负载不是太大,延时时间是非常少的,当然,如果遇到大事务要另当别论了。很多时候,产生这个问题主要是因为需要读取刚刚写入的数据,所以对于这类问题一般只能通过应用程序来控制,如果是读取刚刚写入的数据,只能通过从Master中读取才能保证肯定能找到。
实际上,很多时候读写分离并不是将读和写完全分离,Master仍然还是需要承担一部分读的服务,就比如这种刚刚写入的数据的读取。毕竟 MySQL Replication 并不是实时同步,人家的定义本来就只是Replication而已。
您好,向您请教个问题:
amoeba运行的时候必须有 命令提示符(cmd)界面吗?有没有可以设置的地方,设置成没有界面、开机即运行的服务?
另外,在命令提示行里 每隔一段时间(10分钟)就出现一些DEBUG信息(向数据库服务器发送、接收数据的信息),这些信息可不可以取消?
2004-07-29 01:06:31,030 DEBUG net.MysqlServerConnection – authing result packet from server:192.168.2.203:3306
2004-07-29 01:06:31,055 DEBUG net.MysqlServerConnection – receive HandshakePacket packet from server:192.168.2.203:3306
2004-07-29 01:06:31,056 DEBUG net.MysqlServerConnection – authing packet sent to server:192.168.2.203:3306
2004-07-29 01:06:31,057 DEBUG net.MysqlServerConnection – authing result packet from server:192.168.2.203:3306
2004-07-29 01:16:26,622 DEBUG net.MysqlServerConnection – receive HandshakePacket packet from server:192.168.2.211:3306
2004-07-29 01:16:26,622 DEBUG net.MysqlServerConnection – authing packet sent to server:192.168.2.211:3306
我想写入一条数据到多个数据库(每个数据库都有这个数据)怎么配置?
非常着急。配置了很久没有成功!
我想写入一条数据到多个数据库(db1,db2,db3)每个数据库(bd1,db2,db3)都有这个数据,怎么配置?
实在不好意思,关于Amoeba的各种问题还是建议大家到 Amoeba 开发者博客 (http://amoeba.sourceforge.net) 去寻求作者本人的帮助
陈思儒加入Alibaba了?他不是盛大的么?
我采用Amoeba for mysql作为集群数据库的代理,在用户量的少的情况下,数据和性能没有问题,但是在大数据量的时候有丢失数据库的现象,今天测试结果为:
在有使用代理的情况下,3台手机同时同步500条数据,连续3次有丢失数据现象。
后来直接把数据库连接改为主库进行测试,3台手机同时同步500条数据,连续3次没有数据现象。初步断定为有amoeba性能瓶颈。目前我还么有找到解决问题的办法。
请给予指点,感谢
TO wayne:
对于这个问题,其实与Amoeba并没有多大实际的关系。当然,也确实是一个问题。一般来说,只要Slave主机上的负载不是太大,延时时间是非常少的,当然,如果遇到大事务要另当别论了。很多时候,产生这个问题主要是因为需要读取刚刚写入的数据,所以对于这类问题一般只能通过应用程序来控制,如果是读取刚刚写入的数据,只能通过从Master中读取才能保证肯定能找到。
实际上,很多时候读写分离并不是将读和写完全分离,Master仍然还是需要承担一部分读的服务,就比如这种刚刚写入的数据的读取。毕竟 MySQL Replication 并不是实时同步,人家的定义本来就只是Replication而已。
===============
MySQL不是有同步复制、异步复制和半异步复制的么?用同步复制不会出现数据不同步的问题吧?当然,同步复制会给Master造成性能下降。
我采用Amoeba for mysql做水平切分,为什么没有奏效呢?
环境:1主2从,主和amoeba在一台机器上。
rule.xml文件
ID
<![CDATA[ ID
Master
Slave1
Master
ID
Master
Master2
Slave2
ID
20 ]]>
Master
dbservers.xml
192.168.10.34
192.168.10.35
192.168.10.36
Slave1,Slave2
amoeba.xml
1500
Master
Master
virtualSlave
true
弄了很久也没搞出来。而且rule.xml的readpool,wirtepool,也不是很明白怎么设置,请您指点下!!谢谢