天天看点

Amoeba 实现Mysql的读写分离

一、简介

1、Amoeba简介

Amoeba(变形虫)项目,该开源框架于2008年开始发布一款 Amoeba for Mysql软件。这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的 时候充当SQL路由功能,专注于分布式数据库代理层(Database Proxy)开发。座落与 Client、DB Server(s)之间,对客户端透明。具有负载均衡、高可用性、SQL 过滤、读写分离、可路由相关的到目标数据库、可并发请求多台数据库合并结果。 通过Amoeba你能够完成多数据源的高可用、负载均衡、数据切片的功能,目前Amoeba已在很多企业的生产线上面使用

2、Amoeba的优缺点

优点:

(1)降低费用,简单易用

(2)提高系统整体可用性

(3)易于扩展处理能力与系统规模

(4)可以直接实现读写分离及负载均衡效果,而不用修改代码

缺点:

(1)不支持事务与存储过程

(2)暂不支持分库分表,amoeba目前只做到分数据库实例

(3)不适合从amoeba导数据的场景或者对大数据量查询的query并不合适(比如一次请求返回10w以上甚至更多数据的场合)

3、什么是读写分离

读写分离(Read/Write Splitting),基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。

数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

4、实现读写分离的方法

(1)程序修改mysql操作类

可以参考PHP实现的Mysql读写分离,阿权开始的本项目,以php程序解决此需求。

优点:直接和数据库通信,简单快捷的读写分离和随机的方式实现的负载均衡,权限独立分配

缺点:自己维护更新,增减服务器在代码处理

(2)Mysql-Proxy

参考 mysql-proxy。

优点:直接实现读写分离和负载均衡,不用修改代码,master和slave用一样的帐号

缺点:字符集问题,lua语言编程,还只是alpha版本,时间消耗有点高

(3)Amoeba#阿里巴巴的开源产品,充分证明它的稳定性不容置疑。

参考官网:http://amoeba.meidusa.com/

优点:直接实现读写分离和负载均衡,不用修改代码,有很灵活的数据解决方案

缺点:自己分配账户,和后端数据库权限管理独立,权限处理不够灵活

二、拓扑架构

1

2

3

4

<code>主机地址分配:</code>

<code>Master主机地址:192.168.0.149</code>

<code>Slave1主机地址:192.168.0.150</code>

<code>Slave2主机地址:192.168.0.135</code>

<a href="http://s3.51cto.com/wyfs02/M01/53/E0/wKiom1Ry2kiiz8nlAADZ-1hr70Q699.jpg" target="_blank"></a>

三、源码编译Mysql

1、编译Mysql的依赖包

<code>yum -y </code><code>install</code> <code>gcc gcc-c++ ncurses-devel openssl-devel bison</code>

2、创建mysql用户

<code>groupadd -r mysql</code>

<code>useradd</code> <code>-g mysql -r -d </code><code>/mydata/data</code> <code>mysql</code>

3、创建数据文件存储目录并赋予mysql权限

<code>mkdir</code> <code>/mydata/data</code>

<code>chown</code> <code>-R mysql.mysql </code><code>/mydata/data</code>

4、安装cmake

5

<code>tar</code> <code>xf cmake-2.8.11.2.</code><code>tar</code><code>.gz</code>

<code>cd</code> <code>cmake-2.8.11.2</code>

<code>.</code><code>/configure</code>

<code>make</code> <code>&amp;&amp; </code><code>make</code> <code>install</code>

<code>cd</code> <code>..</code>

5、源码编译Mysql

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<code>tar</code> <code>xf mysql-5.6.12.</code><code>tar</code><code>.gz </code>

<code>cd</code> <code>mysql-5.6.12</code>

<code>cmake . \</code>

<code> </code><code>-DCMAKE_INSTALL_PREFIX=</code><code>/usr/local/mysql</code> <code>\</code>

<code> </code><code>-DMYSQL_DATADIR=</code><code>/mydata/data</code> <code>\</code>

<code> </code><code>-DSYSCONFDIR=</code><code>/etc</code> <code>\</code>

<code> </code><code>-DWITH_INNOBASE_STORAGE_ENGINE=1 \</code>

<code> </code><code>-DWITH_MYISAM_STORAGE_ENGINE=1 \</code>

<code> </code><code>-DWITH_ARCHIVE_STORAGE_ENGINE=1 \</code>

<code> </code><code>-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \</code>

<code> </code><code>-DWITH_MEMORY_STORAGE_ENGINE=1 \</code>

<code> </code><code>-DWITH_READLINE=1 \</code>

<code> </code><code>-DWITH_SSL=system \</code>

<code> </code><code>-DWITH_ZLIB=system \</code>

<code> </code><code>-DWITH_LIBWRAP=0 \</code>

<code> </code><code>-DENABLED_LOCAL_INFILE=1 \</code>

<code> </code><code>-DMYSQL_UNIX_ADDR=</code><code>/tmp/mysql</code><code>.sock \</code>

<code> </code><code>-DDEFAULT_CHARSET=utf8 \</code>

<code> </code><code>-DDEFAULT_COLLATION=utf8_general_ci</code>

6、更改mysql的主目录为mysql组

<code>chown</code> <code>-R :mysql </code><code>/usr/local/mysql/</code>

7、初始化mysql数据库

<code>cd</code> <code>/usr/local/mysql/</code>

<code>.</code><code>/scripts/mysql_install_db</code> <code>--datadir=</code><code>/mydata/data/</code> <code>--basedir=</code><code>/usr/local/mysql/</code> <code>--user=mysql</code>

8、拷贝mysql脚本文件

<code>cp</code> <code>support-files</code><code>/mysql</code><code>.server </code><code>/etc/init</code><code>.d</code><code>/mysqld</code>

<code>chmod</code> <code>+x </code><code>/etc/init</code><code>.d</code><code>/mysqld</code> 

<code>chkconfig --add mysqld</code>

9、提供mysql配置文件

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

<code>cat</code> <code>&gt; </code><code>/etc/my</code><code>.cnf &lt;&lt; EOF</code>

<code>[client]</code>

<code>port            = 3306</code>

<code>socket          = </code><code>/tmp/mysql</code><code>.sock</code>

<code>[mysqld]</code>

<code>skip-external-locking</code>

<code>key_buffer_size = 256M</code>

<code>max_allowed_packet = 16M</code>

<code>table_open_cache = 256</code>

<code>sort_buffer_size = 1M</code>

<code>read_buffer_size = 1M</code>

<code>read_rnd_buffer_size = 4M</code>

<code>myisam_sort_buffer_size = 64M</code>

<code>thread_cache_size = 8</code>

<code>query_cache_size= 16M</code>

<code>thread_concurrency = 8</code>

<code>binlog-</code><code>format</code><code>=ROW</code>

<code>log-slave-updates=</code><code>true</code>

<code>gtid-mode=on</code>

<code>enforce-gtid-consistency=</code><code>true</code>

<code>master-info-repository=TABLE</code>

<code>relay-log-info-repository=TABLE</code>

<code>sync</code><code>-master-info=1</code>

<code>slave-parallel-workers=2</code>

<code>binlog-checksum=CRC32</code>

<code>master-verify-checksum=1</code>

<code>slave-sql-verify-checksum=1</code>

<code>binlog-rows-query-log_events=1</code>

<code>report-port=3306</code>

<code>datadir=</code><code>/mydata/data</code>

<code>report-host=master.allentuns.com</code>

<code>log-bin=mysql-bin</code>

<code>server-</code><code>id</code>       <code>= 10</code>

<code>[mysqldump]</code>

<code>quick</code>

<code>[mysql]</code>

<code>no-auto-rehash</code>

<code>[myisamchk]</code>

<code>key_buffer_size = 128M</code>

<code>sort_buffer_size = 128M</code>

<code>read_buffer = 2M</code>

<code>write_buffer = 2M</code>

<code>[mysqlhotcopy]</code>

<code>interactive-timeout</code>

<code>EOF</code>

10、配置mysql环境变量

<code>echo</code> <code>"export PATH=\$PATH:/usr/local/mysql/bin"</code> <code>&gt; </code><code>/etc/profile</code><code>.d</code><code>/mysql</code><code>.sh</code>

<code>source</code> <code>/etc/profile</code><code>.d</code><code>/mysql</code><code>.sh</code>

11、链接mysql库文件和头文件

<code>ln</code> <code>-sv </code><code>/usr/local/mysql/include</code> <code>/usr/include/mysql</code>

<code>echo</code> <code>"/usr/local/mysql/lib"</code> <code>&gt; </code><code>/etc/ld</code><code>.so.conf.d</code><code>/mysql</code><code>.conf</code>

<code>ldconfig -</code><code>v</code>

12、启动mysql服务

<code>service mysqld start</code>

13、删除匿名用户

<code># mysql</code>

<code>mysql&gt; drop user </code><code>""</code><code>@</code><code>"localhost"</code><code>;</code>

<code>mysql&gt; drop user </code><code>""</code><code>@</code><code>"master.com"</code><code>;</code>

<code>mysql&gt; drop user </code><code>"root"</code><code>@</code><code>"::1"</code><code>;</code>

14、修改用户root密码

<code>mysql&gt; update user </code><code>set</code> <code>password=password(</code><code>"123456"</code><code>) where user=</code><code>"root"</code><code>;</code>

<code>mysql&gt; flush privileges;</code>

15、本地免密码登陆Mysql

<code>ERROR 1045 (28000): Access denied </code><code>for</code> <code>user </code><code>'root'</code><code>@</code><code>'localhost'</code> <code>(using password: NO)</code>

<code># cat &gt; ~/.my.cnf &lt;&lt; EOF</code>

<code>&gt; [client]</code>

<code>&gt; user = </code><code>"root"</code>

<code>&gt; password = </code><code>"123456"</code>

<code>&gt; host = </code><code>"127.0.0.1"</code>

<code>&gt; EOF</code>

<code>mysql&gt; show databases;</code>

<code>+--------------------+</code>

<code>| Database           |</code>

<code>| information_schema |</code>

<code>| mysql              |</code>

<code>| performance_schema |</code>

<code>| </code><code>test</code>               <code>|</code>

-------------------------------------------------------------------------------------------

开始配置主从异步同步

1、修改my.cnf配置文件

<code>Master主机:</code>

<code>server-</code><code>id</code> <code>= 1</code>

<code>log-bin = mysql-bin</code>

<code>Slave1主机</code>

<code>server-</code><code>id</code> <code>= 10</code>

<code>relay-log = relay-log</code>

<code>read</code><code>-only = on</code>

<code>Slave2主机</code>

<code>server-</code><code>id</code> <code>= 20</code>

2、三台主机修改配置文件后并重启Mysql服务

<code>/etc/init</code><code>.d</code><code>/mysqld</code> <code>restart</code>

3、Master主机添加授权用户并查看pos偏移位

<code>mysql&gt; grant replication slave,replication client on *.* to </code><code>"slave"</code><code>@</code><code>"192.168.1.%"</code> <code>identified by </code><code>"slavepass"</code><code>;</code>

<code>mysql&gt; show master status;</code>

<code>+------------------+----------+--------------+------------------+------------------------------------------+</code>

<code>| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |</code>

<code>| mysql-bin.000002 |      595 |              |                  | 381c5272-73b6-11e4-baba-000c29267a8d:1-7 |</code>

4、Slave的两台主机添加Master主机

54

55

56

57

58

59

60

61

62

63

64

65

66

<code>mysql&gt; help change master to;</code>

<code>mysql&gt; CHANGE MASTER TO</code>

<code>  </code><code>MASTER_HOST=</code><code>'192.168.1.150'</code><code>,</code>

<code>  </code><code>MASTER_USER=</code><code>'slave'</code><code>,</code>

<code>  </code><code>MASTER_PASSWORD=</code><code>'slavepass'</code><code>,</code>

<code>  </code><code>MASTER_PORT=3306,</code>

<code>  </code><code>MASTER_LOG_FILE=</code><code>'mysql-bin.000003'</code><code>,</code>

<code>  </code><code>MASTER_LOG_POS=191</code>

<code>mysql&gt; start slave;</code>

<code>mysql&gt; show slave status\G</code>

<code>*************************** 1. row ***************************</code>

<code>               </code><code>Slave_IO_State: Waiting </code><code>for</code> <code>master to send event</code>

<code>                  </code><code>Master_Host: 192.168.1.150</code>

<code>                  </code><code>Master_User: slave</code>

<code>                  </code><code>Master_Port: 3306</code>

<code>                </code><code>Connect_Retry: 60</code>

<code>              </code><code>Master_Log_File: mysql-bin.000003</code>

<code>          </code><code>Read_Master_Log_Pos: 191</code>

<code>               </code><code>Relay_Log_File: slave-relay-bin.000002</code>

<code>                </code><code>Relay_Log_Pos: 314</code>

<code>        </code><code>Relay_Master_Log_File: mysql-bin.000003</code>

<code>             </code><code>Slave_IO_Running: Yes</code>

<code>            </code><code>Slave_SQL_Running: Yes</code>

<code>              </code><code>Replicate_Do_DB: </code>

<code>          </code><code>Replicate_Ignore_DB: </code>

<code>           </code><code>Replicate_Do_Table: </code>

<code>       </code><code>Replicate_Ignore_Table: </code>

<code>      </code><code>Replicate_Wild_Do_Table: </code>

<code>  </code><code>Replicate_Wild_Ignore_Table: </code>

<code>                   </code><code>Last_Errno: 0</code>

<code>                   </code><code>Last_Error: </code>

<code>                 </code><code>Skip_Counter: 0</code>

<code>          </code><code>Exec_Master_Log_Pos: 191</code>

<code>              </code><code>Relay_Log_Space: 518</code>

<code>              </code><code>Until_Condition: None</code>

<code>               </code><code>Until_Log_File: </code>

<code>                </code><code>Until_Log_Pos: 0</code>

<code>           </code><code>Master_SSL_Allowed: No</code>

<code>           </code><code>Master_SSL_CA_File: </code>

<code>           </code><code>Master_SSL_CA_Path: </code>

<code>              </code><code>Master_SSL_Cert: </code>

<code>            </code><code>Master_SSL_Cipher: </code>

<code>               </code><code>Master_SSL_Key: </code>

<code>        </code><code>Seconds_Behind_Master: 0</code>

<code>Master_SSL_Verify_Server_Cert: No</code>

<code>                </code><code>Last_IO_Errno: 0</code>

<code>                </code><code>Last_IO_Error: </code>

<code>               </code><code>Last_SQL_Errno: 0</code>

<code>               </code><code>Last_SQL_Error: </code>

<code>  </code><code>Replicate_Ignore_Server_Ids: </code>

<code>             </code><code>Master_Server_Id: 1</code>

<code>                  </code><code>Master_UUID: 381c5272-73b6-11e4-baba-000c29267a8d</code>

<code>             </code><code>Master_Info_File: mysql.slave_master_info</code>

<code>                    </code><code>SQL_Delay: 0</code>

<code>          </code><code>SQL_Remaining_Delay: NULL</code>

<code>      </code><code>Slave_SQL_Running_State: Slave has </code><code>read</code> <code>all relay log; waiting </code><code>for</code> <code>the slave I</code><code>/O</code> <code>thread to update it</code>

<code>           </code><code>Master_Retry_Count: 86400</code>

<code>                  </code><code>Master_Bind: </code>

<code>      </code><code>Last_IO_Error_Timestamp: </code>

<code>     </code><code>Last_SQL_Error_Timestamp: </code>

<code>               </code><code>Master_SSL_Crl: </code>

<code>           </code><code>Master_SSL_Crlpath: </code>

<code>           </code><code>Retrieved_Gtid_Set: </code>

<code>            </code><code>Executed_Gtid_Set: 397e7449-73b6-11e4-baba-000c29ccc719:1-5</code>

<code>                </code><code>Auto_Position: 0</code>

<code>1 row </code><code>in</code> <code>set</code> <code>(0.00 sec)</code>

5、主从复制测试

<code>#首先在Master主机上创建mydbtest数据库</code>

<code>[root@master ~]</code><code># mysqladmin create mydbtest;</code>

<code>[root@master ~]</code><code># mysql -e "show databases;"</code>

<code>| mydbtest           |</code>

<code>#其次在Slave1和Slave2上分别查看是否有数据库同步</code>

<code>[root@slave ~]</code><code># mysql -e "show databases;"</code>

<code>haha,数据库mydbtest同步成功</code>

四、安装Amoeba

因为Amoeba是Java程序开发的,所以要安装JDK

1、安装JDK

<code>tar</code> <code>xf jdk-7u60-bin-linux-x64-16.</code><code>tar</code><code>.gz -C </code><code>/usr/local/</code>

<code>cat</code> <code>&gt; </code><code>/etc/profile</code><code>.d</code><code>/jdk</code><code>.sh &lt;&lt; EOF</code>

<code>JAVA_HOME=</code><code>/usr/local/jdk1</code><code>.7.0_60</code>

<code>PATH=\$JAVA_HOME</code><code>/bin</code><code>:\$PATH</code>

<code>CLASSPATH=.:\$JAVA_HOME</code><code>/lib/dt</code><code>.jar:\$JAVA_HOME</code><code>/lib/tools</code><code>.jar</code>

<code>export</code> <code>JAVA_HOME PATH CLASSPATH</code>

<code>source</code> <code>/etc/profile</code>

<code>java -version</code>

2、安装Amoeba

<code># mkdir /usr/local/amoeba</code>

<code># tar xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/</code>

<code># cat &gt; /etc/profile.d/amoeba.sh &lt;&lt; EOF</code>

<code>&gt; </code><code>export</code> <code>AMOEBA_HOME=</code><code>/usr/local/amoeba</code>

<code>&gt; </code><code>export</code> <code>PATH=\$AMOEBA_HOME</code><code>/bin</code><code>:\$PATH</code>

<code># source /etc/profile.d/amoeba.sh </code>

<code># amoeba</code>

<code>**********************************</code>

<code>启动amoeba报错</code>

<code>The stack size specified is too small, Specify at least 228k</code>

<code>Error: Could not create the Java Virtual Machine.</code>

<code>Error: A fatal exception has occurred. Program will </code><code>exit</code><code>.</code>

<code>解决办法</code>

<code>将一下行的128修改成大于228K</code>

<code>#DEFAULT_OPTS="-server -Xms256m -Xmx256m -Xss128k"</code>

<code>DEFAULT_OPTS=</code><code>"-server -Xms256m -Xmx256m -Xss256k"</code>

3、启动amoeba的方法

<code>amoeba start|stop</code>

<code># amoeba start</code>

<code>log4j:WARN log4j config load completed from </code><code>file</code><code>:</code><code>/usr/local/amoeba/conf/log4j</code><code>.xml</code>

<code>2014-11-23 23:41:37,528 INFO  context.MysqlRuntimeContext - Amoeba </code><code>for</code> <code>Mysql current versoin=5.1.45-mysql-amoeba-proxy-2.2.0</code>

<code>log4j:WARN ip access config load completed from </code><code>file</code><code>:</code><code>/usr/local/amoeba/conf/access_list</code><code>.conf</code>

<code>2014-11-23 23:41:38,016 INFO  net.ServerableConnectionManager - Amoeba </code><code>for</code> <code>Mysql listening on 0.0.0.0</code><code>/0</code><code>.0.0.0:8066.</code>

<code>2014-11-23 23:41:38,047 INFO  net.ServerableConnectionManager - Amoeba Monitor Server listening on </code><code>/127</code><code>.0.0.1:37103.</code>

4、查看Amoeba配置文件

<code># cd /usr/local/amoeba/conf/</code>

<code>amoeba.xml      </code><code>#定义数据库读写分离及节点管理信息等</code>

<code>dbServers.xml   </code><code>#定义连接后端Mysql服务器信息</code>

67

68

69

70

71

72

73

74

75

76

77

78

<code>[root@Amoeba conf]</code><code># cat dbServers.xml </code>

<code>&lt;?xml version=</code><code>"1.0"</code> <code>encoding=</code><code>"gbk"</code><code>?&gt;</code>

<code>&lt;!DOCTYPE amoeba:dbServers SYSTEM </code><code>"dbserver.dtd"</code><code>&gt;</code>

<code>&lt;amoeba:dbServers xmlns:amoeba=</code><code>"http://amoeba.meidusa.com/"</code><code>&gt;</code>

<code>        </code><code>&lt;!-- </code>

<code>            </code><code>Each dbServer needs to be configured into a Pool,</code>

<code>            </code><code>If you need to configure multiple dbServer with load balancing that can be simplified by the following configuration:</code>

<code>             </code><code>add attribute with name virtual = </code><code>"true"</code> <code>in</code> <code>dbServer, but the configuration does not allow the element with name factoryConfig</code>

<code>             </code><code>such as </code><code>'multiPool'</code> <code>dbServer   </code>

<code>        </code><code>--&gt;</code>

<code>        </code> 

<code>    </code><code>&lt;dbServer name=</code><code>"abstractServer"</code> <code>abstractive=</code><code>"true"</code><code>&gt;</code>

<code>        </code><code>&lt;factoryConfig class=</code><code>"com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory"</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"manager"</code><code>&gt;${defaultManager}&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"sendBufferSize"</code><code>&gt;64&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"receiveBufferSize"</code><code>&gt;128&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>#定义连接后端集群mysql的端口  </code>

<code>            </code><code>&lt;!-- mysql port --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"port"</code><code>&gt;3306&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>#连接的默认数据库</code>

<code>            </code><code>&lt;!-- mysql schema --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"schema"</code><code>&gt;</code><code>test</code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code> 

<code>            </code><code>&lt;!-- mysql user --&gt;</code>

<code>            </code><code>#连接后端数据库的用户名和密码,需要后端数据库授权</code>

<code>            </code><code>&lt;property name=</code><code>"user"</code><code>&gt;amoeba&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"password"</code><code>&gt;111111&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;!--  mysql password</code>

<code>            </code><code>&lt;property name=</code><code>"password"</code><code>&gt;password&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>--&gt;</code>

<code>        </code><code>&lt;</code><code>/factoryConfig</code><code>&gt;</code>

<code>        </code><code>&lt;poolConfig class=</code><code>"com.meidusa.amoeba.net.poolable.PoolableObjectPool"</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"maxActive"</code><code>&gt;500&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"maxIdle"</code><code>&gt;500&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"minIdle"</code><code>&gt;10&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"minEvictableIdleTimeMillis"</code><code>&gt;600000&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"timeBetweenEvictionRunsMillis"</code><code>&gt;600000&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"testOnBorrow"</code><code>&gt;</code><code>true</code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"testOnReturn"</code><code>&gt;</code><code>true</code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"testWhileIdle"</code><code>&gt;</code><code>true</code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>/poolConfig</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>/dbServer</code><code>&gt;</code>

<code>        </code><code>#定义"master"数据库节点,"name"名称可以自定义</code>

<code>    </code><code>&lt;dbServer name=</code><code>"master"</code>  <code>parent=</code><code>"abstractServer"</code><code>&gt;</code>

<code>        </code><code>&lt;factoryConfig&gt;</code>

<code>            </code><code>&lt;!-- mysql ip --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"ipAddress"</code><code>&gt;192.168.1.150&lt;</code><code>/property</code><code>&gt;</code>

<code>    </code><code>#定义"slave1"数据库节点</code>

<code>    </code><code>&lt;dbServer name=</code><code>"slave1"</code>  <code>parent=</code><code>"abstractServer"</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"ipAddress"</code><code>&gt;192.168.1.151&lt;</code><code>/property</code><code>&gt;</code>

<code>    </code><code>#定义"slave2"数据库节点</code>

<code>    </code><code>&lt;dbServer name=</code><code>"slave2"</code>  <code>parent=</code><code>"abstractServer"</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"ipAddress"</code><code>&gt;192.168.1.135&lt;</code><code>/property</code><code>&gt;</code>

<code>    </code><code>&lt;dbServer name=</code><code>"multiPool"</code> <code>virtual=</code><code>"true"</code><code>&gt;</code>

<code>        </code><code>&lt;poolConfig class=</code><code>"com.meidusa.amoeba.server.MultipleServerPool"</code><code>&gt;</code>

<code>            </code><code>&lt;!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA--&gt;                       </code><code>#定义选择哪一种算法进行负载均衡调度</code>

<code>            </code><code>&lt;property name=</code><code>"loadbalance"</code><code>&gt;1&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;!-- Separated by commas,such as: server1,server2,server1 --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"poolNames"</code><code>&gt;slave1,slave2&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>#定义数据库池,用于实现负载均衡."slave"为上面定义的从数据库节点,可以写多个用","分隔;</code>

<code>&lt;</code><code>/amoeba</code><code>:dbServers&gt;</code>

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

<code>[root@Amoeba conf]</code><code># cat amoeba.xml</code>

<code>&lt;!DOCTYPE amoeba:configuration SYSTEM </code><code>"amoeba.dtd"</code><code>&gt;</code>

<code>&lt;amoeba:configuration xmlns:amoeba=</code><code>"http://amoeba.meidusa.com/"</code><code>&gt;</code>

<code>    </code><code>&lt;proxy&gt;</code>

<code>    </code> 

<code>        </code><code>&lt;!-- service class must implements com.meidusa.amoeba.service.Service --&gt;</code>

<code>        </code><code>&lt;service name=</code><code>"Amoeba for Mysql"</code> <code>class=</code><code>"com.meidusa.amoeba.net.ServerableConnectionManager"</code><code>&gt;</code>

<code>            </code><code>&lt;!-- port --&gt;</code>

<code>            </code><code>#定义amoeba代理服务器的对外连接监听端口</code>

<code>            </code><code>&lt;!-- bind ipAddress --&gt;</code>

<code>            </code><code>&lt;!-- </code>

<code>            </code><code>&lt;property name=</code><code>"ipAddress"</code><code>&gt;127.0.0.1&lt;</code><code>/property</code><code>&gt;</code>

<code>             </code><code>--&gt;</code>

<code>             </code><code>#定义amoeba代理服务器对外连接的监听IP</code>

<code>            </code><code>&lt;property name=</code><code>"ipAddress"</code><code>&gt;0.0.0.0&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"manager"</code><code>&gt;${clientConnectioneManager}&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"connectionFactory"</code><code>&gt;</code>

<code>                </code><code>&lt;bean class=</code><code>"com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory"</code><code>&gt;</code>

<code>                    </code><code>&lt;property name=</code><code>"sendBufferSize"</code><code>&gt;128&lt;</code><code>/property</code><code>&gt;</code>

<code>                    </code><code>&lt;property name=</code><code>"receiveBufferSize"</code><code>&gt;64&lt;</code><code>/property</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>/bean</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"authenticator"</code><code>&gt;</code>

<code>                </code><code>&lt;bean class=</code><code>"com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator"</code><code>&gt;</code>

<code>                    </code><code>#定义amoeba连接用户名和密码,客户端或程序只需要使用此用户名和密码连接即可</code>

<code>                    </code><code>&lt;property name=</code><code>"user"</code><code>&gt;root&lt;</code><code>/property</code><code>&gt;</code>

<code>                    </code> 

<code>                    </code><code>&lt;property name=</code><code>"password"</code><code>&gt;222222&lt;</code><code>/property</code><code>&gt;</code>

<code>                    </code><code>&lt;property name=</code><code>"filter"</code><code>&gt;</code>

<code>                        </code><code>&lt;bean class=</code><code>"com.meidusa.amoeba.server.IPAccessController"</code><code>&gt;</code>

<code>                            </code><code>&lt;property name=</code><code>"ipFile"</code><code>&gt;${amoeba.home}</code><code>/conf/access_list</code><code>.conf&lt;</code><code>/property</code><code>&gt;</code>

<code>                        </code><code>&lt;</code><code>/bean</code><code>&gt;</code>

<code>                    </code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>/service</code><code>&gt;</code>

<code>        </code><code>&lt;!-- server class must implements com.meidusa.amoeba.service.Service --&gt;</code>

<code>        </code><code>&lt;service name=</code><code>"Amoeba Monitor Server"</code> <code>class=</code><code>"com.meidusa.amoeba.monitor.MonitorServer"</code><code>&gt;</code>

<code>            </code><code>&lt;!--  default value: random number</code>

<code>            </code><code>&lt;property name=</code><code>"port"</code><code>&gt;9066&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"daemon"</code><code>&gt;</code><code>true</code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>                </code><code>&lt;bean class=</code><code>"com.meidusa.amoeba.monitor.net.MonitorClientConnectionFactory"</code><code>&gt;&lt;</code><code>/bean</code><code>&gt;</code>

<code>        </code><code>&lt;runtime class=</code><code>"com.meidusa.amoeba.mysql.context.MysqlRuntimeContext"</code><code>&gt;</code>

<code>            </code><code>&lt;!-- proxy server net IO Read thread size --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"readThreadPoolSize"</code><code>&gt;20&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;!-- proxy server client process thread size --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"clientSideThreadPoolSize"</code><code>&gt;30&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;!-- mysql server data packet process thread size --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"serverSideThreadPoolSize"</code><code>&gt;30&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;!-- per connection cache prepared statement size  --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"statementCacheSize"</code><code>&gt;500&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;!-- query timeout( default: 60 second , TimeUnit:second) --&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"queryTimeout"</code><code>&gt;60&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>/runtime</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>/proxy</code><code>&gt;</code>

<code>    </code><code>&lt;!-- </code>

<code>        </code><code>Each ConnectionManager will start as thread</code>

<code>        </code><code>manager responsible </code><code>for</code> <code>the Connection IO </code><code>read</code> <code>, Death Detection</code>

<code>    </code><code>--&gt;</code>

<code>    </code><code>&lt;connectionManagerList&gt;</code>

<code>        </code><code>&lt;connectionManager name=</code><code>"clientConnectioneManager"</code> <code>class=</code><code>"com.meidusa.amoeba.net.MultiConnectionManagerWrapper"</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"subManagerClassName"</code><code>&gt;com.meidusa.amoeba.net.ConnectionManager&lt;</code><code>/property</code><code>&gt;</code>

<code>              </code><code>default value is avaliable Processors </code>

<code>            </code><code>&lt;property name=</code><code>"processors"</code><code>&gt;5&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>/connectionManager</code><code>&gt;</code>

<code>        </code><code>&lt;connectionManager name=</code><code>"defaultManager"</code> <code>class=</code><code>"com.meidusa.amoeba.net.MultiConnectionManagerWrapper"</code><code>&gt;</code>

<code>            </code><code>&lt;property name=</code><code>"subManagerClassName"</code><code>&gt;com.meidusa.amoeba.net.AuthingableConnectionManager&lt;</code><code>/property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>/connectionManagerList</code><code>&gt;</code>

<code>        </code><code>&lt;!-- default using </code><code>file</code> <code>loader --&gt;</code>

<code>    </code><code>&lt;dbServerLoader class=</code><code>"com.meidusa.amoeba.context.DBServerConfigFileLoader"</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"configFile"</code><code>&gt;${amoeba.home}</code><code>/conf/dbServers</code><code>.xml&lt;</code><code>/property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>/dbServerLoader</code><code>&gt;</code>

<code>    </code><code>&lt;queryRouter class=</code><code>"com.meidusa.amoeba.mysql.parser.MysqlQueryRouter"</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"ruleLoader"</code><code>&gt;</code>

<code>            </code><code>&lt;bean class=</code><code>"com.meidusa.amoeba.route.TableRuleFileLoader"</code><code>&gt;</code>

<code>                </code><code>&lt;property name=</code><code>"ruleFile"</code><code>&gt;${amoeba.home}</code><code>/conf/rule</code><code>.xml&lt;</code><code>/property</code><code>&gt;</code>

<code>                </code><code>&lt;property name=</code><code>"functionFile"</code><code>&gt;${amoeba.home}</code><code>/conf/ruleFunctionMap</code><code>.xml&lt;</code><code>/property</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>/bean</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"sqlFunctionFile"</code><code>&gt;${amoeba.home}</code><code>/conf/functionMap</code><code>.xml&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"LRUMapSize"</code><code>&gt;1500&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>#定义默认池,一些sql语句默认会在此定义的服务器上执行</code>

<code>        </code><code>&lt;property name=</code><code>"defaultPool"</code><code>&gt;master&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>#定义只写数据库</code>

<code>        </code><code>&lt;property name=</code><code>"writePool"</code><code>&gt;master&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>#定义只读数据库,此处定义的是在"dbServer.xml"文件中定义的后端服务器名称,也可以定义数据库池的名称,实现负载均衡</code>

<code>        </code><code>&lt;property name=</code><code>"readPool"</code><code>&gt;multiPool&lt;</code><code>/property</code><code>&gt;</code>

<code>        </code><code>&lt;property name=</code><code>"needParse"</code><code>&gt;</code><code>true</code><code>&lt;</code><code>/property</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>/queryRouter</code><code>&gt;</code>

<code>&lt;</code><code>/amoeba</code><code>:configuration&gt;</code>

5、测试Amoeba读写分离

测试方法:通过tcpdump在本地网卡抓包来分析执行的命令

<code>yum -y </code><code>install</code> <code>tcpdump</code>

<code>tcpdump -i eth1 -s0 -nn -A tcp dst port 3306 and ip dst host 192.168.1.150</code>

<code>-i   表示监听那一个网卡 any代表所有</code>

<code>-s0  表示截取数据,s0抓整个包</code>

<code>-n   表示数字显示主机名</code>

<code>-nn  表示数字显示主机名跟端口号</code>

<code>-X   表示以ASCII码显示内容</code>

<code>-XX  表示以ASCII及16进制码显示内容</code>

<code>-A   表示显示原内容</code>

<code>-w   表示将抓取的内容保存到某个位置</code>

<code>-r   表示导入某</code>

<code>src  源端口、地址</code>

<code>dst  目标端口、地址</code>

首先,我们来查看默认情况下终端是如下所示:

<a href="http://s3.51cto.com/wyfs02/M02/53/E4/wKiom1RzDRCiRMBTAAHOXkg6YN0927.jpg" target="_blank"></a>

我们通过Amoeba代理的方式登录mysql

<code>[root@Amoeba ~]</code><code># mysql -uroot -p222222 -h192.168.1.149</code>

<code>mysql&gt; use mydbtest;</code>

<code>mysql&gt; show tables;</code>

<code>Empty </code><code>set</code> <code>(0.01 sec)</code>

<code>mysql&gt; create table tab(</code><code>id</code> <code>int,name char(20));</code>

<code>Query OK, 0 rows affected (0.04 sec)</code>

<code>mysql&gt; </code><code>select</code> <code>* from tab;</code>

<code>mysql&gt; insert into tab values(1,</code><code>'jerry'</code><code>);</code>

<code>Query OK, 1 row affected (0.01 sec)</code>

<code>mysql&gt; insert into tab values(2,</code><code>'scott'</code><code>);</code>

<code>Query OK, 1 row affected (0.09 sec)</code>

<code>+------+-------+</code>

<code>| </code><code>id</code>   <code>| name  |</code>

<code>|    1 | jerry |</code>

<code>|    2 | scott |</code>

<code>2 rows </code><code>in</code> <code>set</code> <code>(0.00 sec)</code>

<a href="http://s3.51cto.com/wyfs02/M02/53/E2/wKioL1RzD73Dc8qnAAMsbnka9mk542.jpg" target="_blank"></a>

<a href="http://s3.51cto.com/wyfs02/M02/53/E4/wKiom1RzD0DyYeZTAATBdpxLEBM778.jpg" target="_blank"></a>

如果大家想跟深入的了解Amoeba可以参考这个文档:

http://docs.hexnova.com/amoeba/rw-splitting.html

好了,今天就到这里了;后续会继续补充一些细节知识点。

     本文转自zys467754239 51CTO博客,原文链接:http://blog.51cto.com/467754239/1581954,如需转载请自行联系原作者