Amoeba(变形虫)项目,该开源框架于2008年 开始发布一款 Amoeba for Mysql软件。这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的 时候充当SQL路由功能,专注于分布式数据库代理层(Database Proxy)开发。座落与 Client、DB Server(s)之间,对客户端透明。具有负载均衡、高可用性、SQL 过滤、读写分离、可路由相关的到目标数据库、可并发请求多台数据库合并结果。 通过Amoeba你能够完成多数据源的高可用、负载均衡、数据切片的功能,目前Amoeba已在很多 企业的生产线上面使用。
随着传统的数据库技术日趋成熟、计算机网络技术的飞速发展和应用范围的扩充,数据库应用 已经普遍建立于计算机网络之上。这时集中式数据库系统表现出它的不足:集中式处理,势必造成性 能瓶颈;应用程序集中在一台计算机上运行,一旦该计算机发生故障,则整个系统受到影响,可靠性 不高;集中式处理引起系统的规模和配置都不够灵活,系统的可扩充性差。在这种形势下,集中式数 据库将向分布式数据库发展。而Amoeba的透明、简易配置及多个优点使其成为分布式数据库代理产品中的优秀选择。
Amoeba在分布式数据库领域将致力解决数据切分,应付客户端“集中式”处理分布式数据。这 里集中式是一个相对概念,客户端不需要知道某种数据的物理存储地。避免这种逻辑出现在业务端, 大大简化了客户端操作分布式数据的复杂程度。
分布式数据库系统的优点:
Amoeba for MySQL致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当query 路由功能,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户端透明。具有负载均衡、高可用性、Query过滤、读写分离、可路由相关的query到目标数据库、可并发请求多台数据库合并结果。 在Amoeba上面你能够完成多数据源的高可用、负载均衡、数据切片的功能。目前在很多企业的生产线上面使用。
那么Amoeba for mysql 对客户端程序来说是什么呢? 我们就当它是mysql吧,它是一个虚拟的mysql,对外提供mysql协议。客户端连接amoeba就象连接mysql一样。在amoeba内部需要配置相关的认证属性。具体请参阅后面的章节。
与Amoeba for MySQL 类似,客户端连接Aladdin必须用MySQL 协议,之所以用MySQL协议,主要是想借助mysql使用的广泛程度以及对各种开发语言的支持。Aladdin后端可以同时连接各种数据库。只要这些数据库提供jdbc驱动。aladdin的出现可以解决企业在数据库整合上面提供积极的帮助。使用者不需要知道后端到底使用了什么类型的数据库、数据库的物理地址什么,这些由aladdin来分析sql语句,并且获得相应的要查询的表跟条件,然后由这些规则结合这些条件进行路由到相关的物理数据库。
随着NoSQL的日益兴起,mongoDB作为一款nosql数据库以其优异的性能得到了广泛的关注。可以说,mongoDB填补了传统关系型数据库以及传统键值型数据库的空白,并且兼具两者优秀特质。Amoeba for MongoDB将提供与Amoeba for MySQL类似的,完全自主、可控的切分方式、并尝试完成同样的auto sharding的功能。 基于Amoeba框架,跟以往的产品一样具备心跳检测、负载均衡、故障转移、查询聚合等功能,保留了之前的配置方式,只要熟悉amoeba其中一款产品的配置,那么上手将非常容易的。
在MySQL proxy 6.0版本 上面如果想要读写分离并且 读集群、写集群 机器比较多情况下,用mysql proxy 需要相当大的工作量,目前mysql proxy没有现成的 lua脚本。mysql proxy根本没有配置文件, lua脚本就是它的全部,当然lua是相当方便的。那么同样这种东西需要编写大量的脚本才能完成一 个复杂的配置。而Amoeba for Mysql只需要进行相关的配置就可以满足需求。
mongodb中的数据切分有一个chunk的概念,每个chunk代表一个数据段(range),当一个chunk的大小到达了指定的数据大小,就会自动切分成两个。 Mongos是根据数据段(chunk)进行切分的,且切分依据的字段必须是一个key。而目前大多的应用中,id(尤其是用户ID)是无序化的,可能有些用户是手机号、有些是会员卡号等等。这使得proxy的range切分难以实施。 因此,虽然mongodb的mongos提供了automatic sharding的功能,但由于数据切分的不可控,常常不能满足我们的需要。 Amoeba for MongoDB提供完全自主、可控的切分方式。
Amoeba框架是基于Java SE1.6开发的,建议使用Java SE 1.6版本。% java -version
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing)
目前Amoeba经验证在JavaTM SE 1.5和Java SE 1.6能正常运行,(可能包括其他未经验证的版本)。
如果你的机器上没有安装JavaTM环境,可以访问http://www.oracle.com/technetwork/java/javase/downloads/index.html进行下载。可以根据你的操作系统等详情安装JavaTM环境。
你可以在Amoeba在SourceForge的主页下载Amoeba,http://sourceforge.net/projects/amoeba/files/。
当你下载的时候,请确保选择Amoeba的最新版本。Amoeba目前有三个开源产品,分别是适用于拥有JDBC Driver的数据库的Amoeba for Aladdin、适用于MySQL数据库的Amoeba for MySQL以及适用于mongoDB数据库的Amoeba for mongoDB。本指南编写时,Amoeba for Aladdin的最新版本是amoeba-aladdin-0.7.0-BETA.tar.gz,Amoeba for MySQL的最新版本是amoeba-mysql-binary-2.0.1-BETA.tar.gz,Amoeba for mongoDB的最新版本是amoeba-mongodb-binary-1.2.0-BETA.tar.gz,请选择合适的版本下载。
不同操作系统因其实现不同而有较大差异,以下小节概括了在常见系统中安装Amoeba的最佳实践。
以下的安装过程仅仅以Amoeba for MySQL作为例子,Amoeba for Aladdin和Amoeba for MongoDB的安装方式是类似的。
你可以从http://sourceforge.net/projects/amoeba/files/下载Amoeba的最新版本。找个地方存放它,并解压到你需要安装的位置。这里假设你将存档文件解压到C:\Program Files\amoeba-mysql-binary-2.0.1-BETA,解压到其他路径是一样的。进入Ameoba运行目录:C:\Users\Admin > cd c:\Program Files\amoeba-mysql-binary-2.0.1-BETA\bin
与在Microsoft Windows系统上安装的过程类似,下载后存放并解压到安装的位置。这里假设你将存档文件解压到/usr/local/amoeba-mysql-binary-2.0.1-BETA,解压到其他路径也是一样的。进入Ameoba运行目录:[]$ cd AMOEBA_HOME=/usr/local/amoeba-mysql-binary-2.0.1-BETA/bin
参照第3.2节。
参照第3.2节。
安装完成后,你可以通过命令确定Amoeba是否成功安装。$ amoeba
amoeba start|stop
请按任意键继续. . .
本小节的主要目的是帮助你在修改最少配置并且仅仅有最少资源的情况下,快速的搭建起一个可用的,通过Amoeba连接的数据库。本节并不会讲述Amoeba的一些更实用的功能(比如分片等等)但相信这节会给你一个极大的使用Amoeba的信心,你会发现Amoeba的使用比想象的简单地多。
根据上一章文档,相信你应该已经配置完成了Amoeba的环境。执行以下命令:$ $AMOEBA_HOME/bin/amoeba
amoeba start|stop
请按任意键继续. . .当出现如上提示,表示Amoeba可以正常启动。
要通过Amoeba来连接数据库首先数据库需要正常对外提供服务,根据不同的数据库类型按以下方式进行验证。
$ mysql -uroot -ppassword -h127.0.0.1 -P3306
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 125
Server version: 5.5.9 MySQL Community Server (GPL)
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
这里只是一个命令的例子,其中*-u选项后是MySQL用户名、-p选项后是MySQL密码、-h选项后是MySQL所在主机地址以及-P{*}选项后是MySQL服务的端口号。 |
通过以上命令你可以验证MySQL的正常对外服务。
需要注意的是,以上命令需要在Amoeba所在的机器执行。因为iptables等配置很容易使得Amoeba无法访问MySQL。
$ mongo 127.0.0.1:27017
MongoDB shell version: 1.6.2
connecting to: 127.0.0.1:27017/test
>
里只是一个mongodb登录命令的示例,其中的主机地址以及端口号需根据你的实际情况。 |
需要注意的是,以上命令需要在Amoeba所在的机器执行。因为iptables等配置很容易使得Amoeba无法访问mongoDB。
在这一节主要包含对Amoeba进行最基本的配置使得你可以通过Amoeba对一台数据库进行操作,当然借由这个机会本节也将对Amoeba的配置文件梗概性地介绍。
Amoeba有哪些主要的配置文件?
以下是配置一个DB节点,使用Amoeba做操作转发的步骤:
<?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">root</property>
<!-- mysql password -->
<property name="password">password</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="server1" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">127.0.0.1</property>
</factoryConfig>
</dbServer>
<dbServer name="multiPool" 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">server1</property>
</poolConfig>
</dbServer>
</amoeba:dbServers>
这份dbServers配置文件中,我们定义了三个dbServer元素,这是第一个dbServer元素的定义。这个名为abstractServer的dbServer,其abstractive属性为true,这意味着这是一个抽象的dbServer定义,可以由其他dbServer定义拓展。 | |
在第一个dbServer元素分别定义MySQL的端口号、数据库名、用户名以及密码。 | |
manager定义了该dbServer选择的连接管理器(ConnectionManager),这里引用了amoeba.xml的配置,稍后介绍。 | |
dbServer下有poolConfig的元素,这个元素的属性主要配置了与数据库的连接池,与此相关的具体配置会在后面的章节中详细介绍。 | |
命名为server1的dbServer元素,正如你设想的那样,这个server1是abstractServer的拓展,parent属性配置了拓展的抽象dbServer,它拓展了abstractServer的ipAddress属性来指名数据库的IP地址,而在端口、用户名密码、连接池配置等属性沿用了abstractServer的配置。 | |
server1拓展了abstractServer的ipAddress属性。 | |
这一段其实并不需要配置,并不会影响到基本使用。以下大致介绍下此配置的含义:multiPool是一个虚拟的数据库节点,可以将这个节点配置成好几台数据库组成的数据库池。比如上面这个配置中仅配置了一台server1,负载均衡策略为ROUNDROBIN(轮询)。与虚拟数据库节点相关的详细教程会在后面的章节中介绍。 |
由此,你大概可以理解定义abstractServer的原因:当我们有一个数据库集群需要管理,这个数据库集群中节点的大部分信息可能是相同的,比如:端口号、用户名、密码等等。因此通过归纳这些共性定义出的abstractServer极大地简化了dbServers配置文件:
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">
<dbServer name="abstractServerForBilling" 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>
<property name="port">3306</property>
<property name="schema">test</property>
<property name="user">root</property>
<property name="password">password</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="billing1" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.0.1</property>
</factoryConfig>
</dbServer>
<dbServer name="billing2" parent="abstractServer">
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.0.2</property>
</factoryConfig>
</dbServer>
......
</amoeba:dbServers>