龙空技术网

mysql_05/06晓桂科技分享

Poetry聆听 104

前言:

而今朋友们对“amoebaformysql源码”大概比较着重,我们都想要分析一些“amoebaformysql源码”的相关资讯。那么小编同时在网络上汇集了一些有关“amoebaformysql源码””的相关文章,希望我们能喜欢,我们一起来了解一下吧!

下面继续分享没有生气了数据库1-6节课,之05

mysql 代理层

(mysqlproxy, amoeba, cobar)

客户

web程序,游戏程序(c,php,java.......)

|

|

代理层 (mysqlproxy,amoeba)

|

|

mysql主 <----> mysql从

amoeba 变形虫

参考网址:

基于Amoeba的数据水平切分:

client 192.168.0.x

|

|

|

amoeba 192.168.0.3

|

|

|

|------------------------|

mysql mysql

192.168.0.1 192.168.0.2

架构前所有节点准备:

1,主机名三步,互相绑定

2,时间同步

3,关闭iptables,selinux

4, 配置好yum

5, 静态ip地址

第一步:在192.168.0.3安装amoeba

1,因为是java开发的,需要java运行环境,也就是jdk;我们这里自己下载安装jdk

/share/soft/amoeba/jdk-6u18-ea-bin-b02-linux-i586-09_sep_2009.bin

./jdk-6u18-ea-bin-b02-linux-i586-09_sep_2009.bin --直接./执行它,就可以安装,会自动解压成一个目录在当前目录下

敲空格,yes

--如果是在64位系统版本上安装这个jdk,可能会报缺少ld-linux.so.2的库,是因为这个jdk是32位的

--解决方法:在64位系统上安装32位的glibc,或者用下面的命令,直接yum安装库就可以了

# yum install ld-linux.so.2 -y

# mv jdk1.6.0_18/ /usr/local/java --把jdk的目录移到/usr/local下叫java

2,解压安装amoeba,软件包路径在下面

/share/soft/amoeba/amoeba-mysql-binary-2.2.0.tar.gz

因为这个软件打包的习惯不好,解压后,不会给你建立一个目录

所以:

# mkdir /usr/local/amoeba

# tar xf /share/soft/amoeba/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba

# ls /usr/local/amoeba/ --amoeba的所有文件在此目录下

benchmark changelogs.txt lib README.html

bin conf LICENSE.txt

# cd /usr/local/amoeba/

# ./bin/amoeba --直接用此命令启动,会报找不到java_home

Error: JAVA_HOME environment variable is not set.

#vim /usr/local/amoeba/bin/amoeba

--加上下面两行(把这两句加到最上面,不要加到最下面,因为这个脚本要用到这个变量的),让这个命令在启动时,就会去找/usr/local/java的jdk

export JAVA_HOME=/usr/local/java

export PATH=$PATH:$JAVA_HOME/bin

# /usr/local/amoeba/bin/amoeba start & --尝试启动,可以启动,但是我们并没有做任何配置,所以在这里ctrl+c取消掉

第二大步:

把两台mysql,关闭AB复制,把先前所有的内容都清空,然后两台mysql都新建下面的测试表

mysql> create database aaa;

Query OK, 1 row affected (0.00 sec)

mysql> use aaa;

Database changed

mysql> create table emp (emp_id int,ename varchar(20));

Query OK, 0 rows affected (0.01 sec)

--并对mysql进行授权,授权的IP为amoeba的IP

mysql> grant all on aaa.* to 'amoeba'@'192.168.0.%' identified by '123';

Query OK, 0 rows affected (0.04 sec)

mysql> flush privileges;

Query OK, 0 rows affected (0.00 sec)

授权后,可以去amoeba(192.168.0.3)这台去连接一下这两个mysql,需要能连才行

第三大步:

# vim /usr/local/amoeba/conf/dbServers.xml --修改此配置文件,定义代理哪些后台数据库

--下面我做了修改的行有23行(写上要操作的后台数据库的schema);26行和29行(授权的用户名和密码);48行和55行(写上后台数据库的IP)

19 <!-- mysql port -->

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

21

22 <!-- mysql schema -->

23 <property name="schema">aaa</property>

24

25 <!-- mysql user -->

26 <property name="user">amoeba</property>

27

28 <!-- mysql password -->

29 <property name="password">123</property>

45 <dbServer name="server1" parent="abstractServer">

46 <factoryConfig>

47 <!-- mysql ip -->

48 <property name="ipAddress">192.168.0.1</property>

49 </factoryConfig>

50 </dbServer>

51

52 <dbServer name="server2" parent="abstractServer">

53 <factoryConfig>

54 <!-- mysql ip -->

55 <property name="ipAddress">192.168.0.2</property>

56 </factoryConfig>

57 </dbServer>

# vim /usr/local/amoeba/conf/amoeba.xml --再修改这个文件,修改了30行和32行(授权的用户和密码),注意这里的用户名和密码跟数据库授权的用户名和密码无关,可以写成不一样的用户和密码来测试

--上一个配置文件里配置的用户名和密码是数据库授权给amoeba连接的用户名和密码,而这个用户名和密码是amoeba给客户端(php,java,web程序等)连接的

30 <property name="user">amoeba</property>

31

32 <property name="password">123</property>

# vim /usr/local/amoeba/conf/rule.xml --修改第三个配置文件,定义数据切分的规则

--下面我是按aaa.emp表里的emp_id这一列来切分,当它为奇数就给server2,为偶数就给server1

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

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

<amoeba:rule xmlns:amoeba="">

<tableRule name="emp" schema="aaa" defaultPools="server1,server2">

<rule name="rule1" ruleResult="POOLNAME">

<parameters>emp_id</parameters>

<expression><![CDATA[

var division = emp_id % 2;

case division when 1 then 'server1';

when 0 then 'server2';

end case;

]]></expression>

</rule>mysql>

</tableRule>

</amoeba:rule>

--直接复制粘贴上去,格式空格之类的太多;可以先在vim里:set paste再insert模式粘贴上去就可以了

第四大步:

在amoeba的代理服务器上启动amoeba服务

# /usr/local/amoeba/bin/amoeba start &

第五大步:

客户端测试

在客户端连接进行测试,连接的IP为amoeba的IP,端口为8066

# mysql -h 192.168.0.3 -u amoeba -p123 -P 8066

注意:amoeba是根据sql解析来进行数据切分的,所以需要把切分的关键字段(这里是emp_id),加入到sql中.否则切分规则无效。无效后,会在 server1,server2 均都插入数据。

mysql> insert into aaa.emp values (1,'aaa'); --这样做是错误的,会在两个后台数据库里都插入数据

--正确的插入方法

mysql> insert into aaa.emp(emp_id,ename) values (1,'aaa');

mysql> insert into aaa.emp(emp_id,ename) values (2,'bbb');

mysql> insert into aaa.emp(emp_id,ename) values (3,'ccc');

mysql> insert into aaa.emp(emp_id,ename) values (4,'ddd');

然后去server1(192.168.0.1)上查看,只有1,3两条数据

去server2(192.168.0.2)上查看,只有2,4两条数据

数据切分成功

在客户端select去查这张表,得到的是两个数据库数据的综合

mysql> select * from aaa.emp;

mysql> select * from emp;

delete和update操作经测试也都OK

==================================

--按照上面的配置文件,只修改rule.xml规则文件如下,做成以emp_id值的范围来进行水平切分

--下面实现的是emp_id小于等于100的任何操作都在server1,大于100的任何操作都是在server2

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

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

<amoeba:rule xmlns:amoeba="">

<tableRule name="emp" schema="aaa" defaultPools="server1,server2">

<rule name="rule1">

<parameters>emp_id</parameters>

<expression><![CDATA[ emp_id <= 100]]></expression>

<defaultPools>server1</defaultPools>

<readPools>server1</readPools>

<writePools>server1</writePools>

</rule>

<rule name="rule2">

<parameters>emp_id</parameters>

<expression><![CDATA[ emp_id > 100]]></expression>

<defaultPools>server2</defaultPools>

<readPools>server2</readPools>

<writePools>server2</writePools>

</rule>

</tableRule>

</amoeba:rule>

=========================================================================

基于Amoeba的数据垂直切分:

架构图和上面的一样

client 192.168.0.x

|

|

amoeba 192.168.0.3

|

|

|------------------------|

mysql mysql

192.168.0.1 192.168.0.2

aaa表 bbb表

第一大步:

1,先把两个mysql(不做AB复制的)以前的数据删掉,新建两个表来做测试

192.168.0.1上

mysql> create databases aaa;

mysql> use aaa;

mysql> create table aaa (id int);

mysql> grant all on aaa.* to 'amoeba'@'192.168.0.%' identified by '123';

mysql> flush privileges;

192.168.0.2上

mysql> create databases aaa;

mysql> use aaa;

mysql> create table bbb (id int);

mysql> grant all on aaa.* to 'amoeba'@'192.168.0.%' identified by '123';

mysql> flush privileges;

第二大步:

# vim /usr/local/amoeba/conf/rule.xml --清空配置,加上下面一段

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

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

<amoeba:rule xmlns:amoeba="">

<tableRule name="aaa" schema="aaa" defaultPools="server1"/>

<tableRule name="bbb" schema="aaa" defaultPools="server2"/>

</amoeba:rule>

第三大步:

重启amoeba

# /usr/local/amoeba/bin/amoeba stop

# /usr/local/amoeba/bin/amoeba start &

第四大步:

在客户端测试

# mysql -h 192.168.0.3 -u amoeba -p123 -P8066

mysql> use aaa;

mysql> insert into aaa values (1); --这一条被插入到192.168.0.1上的aaa.aaa表

mysql> insert into bbb values (2); --这一条被插入到192.168.0.2上的aaa.bbb表

mysql> select * from aaa;

+------+

| id |

+------+

| 1 |

+------+

1 row in set (0.01 sec)

mysql> select * from bbb;

+------+

| id |

+------+

| 2 |

+------+

1 row in set (0.00 sec)

===============================================================

使用amoeba实现读写分离功能(queryrouter)

参考网址:

在上面的基础上,把垂直切分,改成读写分离的架构

client 192.168.0.x

|

|

amoeba 192.168.0.3

|

|------------------------|------------|

mysql mysql mysql

192.168.0.1 192.168.0.2 192.168.0.4

1 2 3

写 读 读

master slave slave

第一大步:

1,先把三个mysql(读写分离应该要做AB复制,但我们在这里不做AB复制,是为了方便测试)

把以前的数据删掉,新建三个相同的表来做测试,插入三条不同的数据

192.168.0.1上

mysql> create databases aaa;

mysql> use aaa;

mysql> create table aaa (id int);

mysql> insert into aaa values (1);

192.168.0.2上

mysql> create databases aaa;

mysql> use aaa;

mysql> create table aaa (id int);

mysql> insert into aaa values (2);

192.168.0.4上

mysql> create databases aaa;

mysql> use aaa;

mysql> create table aaa (id int);

mysql> insert into aaa values (3);

第二大步:

# vim /usr/local/amoeba/conf/dbServers.xml --在原来配置的两个dbserver的情况下,再增加一段server3,对应的IP为192.168.0.4

--然后把两个从(server2,server3)加入到一个pool,我这里poolname为slavepool

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

<factoryConfig>

<!-- mysql ip -->

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

</factoryConfig>

</dbServer>

<dbServer name="slavepool" 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">server2,server3</property>

</poolConfig>

</dbServer>

--1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA,算法:1,轮循(一人一次做循环) 2,加权 3,高可用

# vim /usr/local/amoeba/conf/amoeba.xml

--打开amoeba.xml文件,在原来的基础上修改,把117行和120行的注释去掉,修改115行和118行为server1(也就是mysql主,默认池和写池)

--改119行为server(也就是mysql从,读池)

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

115 <property name="defaultPool">server1</property>

116

117

118 <property name="writePool">server1</property>

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

120

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

--注意:如果只读写分离的话,不做数据切分,那么rule.xml文件就不要配置,保持刚装完amoeba时的原始配置文件就好了(如果清空rule.xml,启动时会报错)

第三大步:

重启amoeba

# /usr/local/amoeba/bin/amoeba stop

# /usr/local/amoeba/bin/amoeba start &

第四大步:

在客户端测试

# mysql -h 192.168.0.3 -u amoeba -p123 -P8066

mysql> use aaa;

mysql> insert into aaa values (3); --写入的数据只会被插入到server1(这里是没有做复制的,如果做复制会被复制到server2和server2)

--读的测试,一次读server2的数据,一次读server3的数据,读时,不要执行use aaa这条语句

mysql> select * from aaa;

+------+

| id |

+------+

| 2 |

+------+

mysql> select * from aaa;

+------+

| id |

+------+

| 3 |

+------+

读写分离成功

扩展讨论:

把dbServer.xml配置文件池的配置修改一下,把server2写两个,server3写一个,算法还是rr

<property name="poolNames">server2,server2,server3</property>

--测试的结果是select查询时,两次得到server2的结果,一次得到server3的结果

==========================================================

数据切分加读写分离综合讨论

client 192.168.0.x

|

|

amoeba 192.168.0.3

|

|

|------------------|------------------|--------------|

mysqlA mysqlB mysqlC mysqlD

192.168.0.1 192.168.0.2 192.168.0.4 192.168.0.5

读写分离: 写 读 写 读

数据切分: 奇数 奇数 偶数 偶数

135246 135 135246 246

mysqlA(master) <-----> mysqlC(master) 双主

| |

| |

mysqlB(slave) mysqlD(slave)

99 100 199 200

--上图中:

对数据进行水平切分,并做读写分离

我们这里测试是用aaa.aaa表的id列来进行水平切分

id为奇数的查询路由mysqlA和mysqlB(mysqlA写,mysqlB读)

id为偶数的查询路由mysqlC和mysqld(mysqlC写,mysqlD读)

第一大步:

四台mysql都建立aaa.aaa表,这里不做AB复制(实际环境应该做)

mysql> create database aaa;

mysql> use aaa;

mysql> create table aaa (id int);

--四个mysql都要对amoeba服务器授权

mysql> grant all on aaa.* to 'amoeba'@'192.168.0.3' identified by '123';

mysql> flush privileges;

第二大步:

# vim /usr/local/amoeba/conf/dbServers.xml

--下面四段是配置四台mysql服务器,名字分别为mysqla,mysqlb,mysqlc,mysqld;对应的ip分别为4,5,6,7

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

<factoryConfig>

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

</factoryConfig>

</dbServer>

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

<factoryConfig>

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

</factoryConfig>

</dbServer>

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

<factoryConfig>

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

</factoryConfig>

</dbServer>

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

<factoryConfig>

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

</factoryConfig>

</dbServer>

--下面两段定义了1个pool叫ddlpool(也就是说除了DML操作外的其它操作大部分为ddl操作,如create表或库等操作就给这个池),用的是1算法,所以一次给mysqla,一次给mysqlc;如果其中一个挂了,它会把DDL操作全给另一个

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

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

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

<property name="poolNames">mysqla,mysqlc</property>

</poolConfig>

</dbServer>

# vim /usr/local/amoeba/conf/amoeba.xml --定义DML的读写之外的所有操作给ddlpool(由上面的dbServer.xml定义),DML的读写操作在这里不定义(所以下面把wirtePool和readPool这两句给注释掉不用),因为我们要定义到rule.xml里

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

115 <property name="defaultPool">ddlpool</property>

116

117 <!--

118 <property name="writePool">server1</property>

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

120 -->

读写注释掉

# vim /usr/local/amoeba/conf/rule.xml --定义DML的读写操作的规则文件如下

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

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

<amoeba:rule xmlns:amoeba="">

<tableRule name="aaa" schema="aaa" >

<rule name="rule1" ruleResult="POOLNAME">

<parameters>id</parameters>

<expression><![CDATA[

var division = id % 2;

case division when 0 then (isReadStatement?'mysqld':'mysqlc');

when 1 then (isReadStatement?'mysqlb':'mysqla');

end case;

]]></expression>

</rule>

</tableRule>

</amoeba:rule>

第三大步:

启动amoeba

# /usr/local/amoeba/bin/amoeba stop

# /usr/local/amoeba/bin/amoeba start &

第四大步:

在客户端测试

# mysql -h 192.168.0.3 -u amoeba -p123 -P8066

测试1:

测试DDL写操作

mysql > create table bbb(id int);

mysql > create table ccc(id int);

mysql > create table ddd(id int);

mysql > create table eee(id int);

......

测试结果为:一次在mysqla,一次在mysqlc轮循操作;如果mysqla挂掉,则只会在mysqlc上操作,如果mysqla再启起来,则又会回到1算法的轮循

测试2:

测试DML写操作时,最好奇偶和大小顺序搞乱来测

mysql> insert into aaa(id) values (2);

mysql> insert into aaa(id) values (4);

mysql> insert into aaa(id) values (1);

mysql> insert into aaa(id) values (6);

mysql> insert into aaa(id) values (3);

mysql> insert into aaa(id) values (5);

测试结果为:奇写在mysqla,偶写在mysqlc

测试3;

测试DML读操作

在mysqlb上插入一条奇数据,一条偶数据(不是在客户端操作)

mysql> insert into aaa(id) values (99);

mysql> insert into aaa(id) values (100);

同理在mysqld上也插入一条奇数据,一条偶数据(不是在客户端操作)

mysql> insert into aaa(id) values (199);

mysql> insert into aaa(id) values (200);

在客户端连上amoeba,测试

mysql > use aaa

mysql > select * from aaa where id=99; --结果可以查出来

mysql > select * from aaa where id=100; --结果查不出来,因为你这是偶读操作,会给mysqld,但mysqld上没有这条记录

mysql > select * from aaa where id=199; --结果查不出来,因为你这是奇读操作,会给mysqlb,但mysqlb上没有这条记录

mysql > select * from aaa where id=200; --结果可以查出来

测试结果:从上面这样的验证,可以确认奇读给mysqlb,偶读给mysqld,一切OK

标签: #amoebaformysql源码