Amoeba是什么?

Amoeba(变形虫)项目,致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当SQL路由功能,专注于分布式数据库代理层(Database Proxy)开发。座落与 Client、DB Server(s)之间,对客户端透明。具有负载均衡、高可用性、SQL过滤、读写分离、可路由相关的到目标数据库、可并发请求多台数据库合并结果。

主要解决:

• 降低 数据切分带来的复杂多数据库结构

• 提供切分规则并降低 数据切分规则 给应用带来的影响

• 降低db 与客户端的连接数

• 多数据源的高可用、读写分离、负载均衡、数据切片功能。

为何要使用Amoeba?

随着传统的数据库技术日趋成熟、计算机网络技术的飞速发展和应用范围的扩充,数据库应用已经普遍建立于计算机网络之上。这时集中式数据库系统表现出它的不足:集中式处理,势必造成性能瓶颈;应用程序集中在一台计算机上运行,一旦该计算机发生故障,则整个系统受到影响,可靠性不高;集中式处理引起系统的规模和配置都不够灵活,系统的可扩充性差。在这种形势下,集中式数据库将向分布式数据库发展。而Amoeba的透明、简易配置及多个优点使其成为分布式数据库代理产品中的优秀选择。

分布式数据库代理的相关概念

Amoeba在分布式数据库领域将致力解决数据切分,应付客户端“集中式”处理分布式数据。这里集中式是一个相对概念,客户端不需要知道某种数据的物理存储地。避免这种逻辑出现在业务端,大大简化了客户端操作分布式数据的复杂程度。

分布式数据库系统的优点:

1.降低费用。分布式数据库在地理上可以式分布的。其系统的结构符合这种分布的要求。允许用户在自己的本地录用、查询、维护等操作,实行局部控制,降低通信代价,避免集中式需要更高要求的硬件设备。而且分布式数据库在单台机器上面数据量较少,其响应速度明显提升。

2.提高系统整体可用性。避免了因为单台数据库的故障而造成全部瘫痪的后果。

3.易于扩展处理能力和系统规模。分布式数据库系统的结构可以很容易地扩展系统,在分布式数据库中增加一个新的节点,不影响现有系统的正常运行。这种方式比扩大集中式系统要灵活经济。在集中式系统中扩大系统和系统升级,由于有硬件不兼容和软件改变困难等缺点,升级的代价常常是昂贵和不可行的。

Amoeba for MySQL

Amoeba for MySQL致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当query 路由功能,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户端透明。具有负载均衡、高可用性、Query过滤、读写分离、可路由相关的query到目标数据库、可并发请求多台数据库合并结果。在Amoeba上面你能够完成多数据源的高可用、负载均衡、数据切片的功能。

那么Amoeba for mysql 对客户端程序来说是什么呢?我们就当它是mysql吧,它是一个虚拟的mysql,对外提供mysql协议。客户端连接amoeba就象连接mysql一样。在amoeba内部需要配置相关的认证属性。

Amoeba不能做什么?

1.目前还不支持事务

2.暂时不支持存储过程(近期会支持)

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

4.暂时不支持分库分表,amoeba目前只做到分数据库实例,每个被切分的节点需要保持库表结构一致

安装和运行Amoeba

运行环境:CentOS6.3

安装jdk1.5以上版本

卸载centos服务器自带版本jdk

查看服务器自带jdk版本号

[root@amoeba1 ~]# java –version

查看java信息

[root@amoeba1 ~]# rpm -qa | grep java

卸载java文件

[root@amoeba1 ~]# rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.45.1.11.1.el6.x86_64

再次查看java版本,已经删除

[root@amoeba1 ~]# java –version

安装jdk

创建/usr/java文件夹,将jdk安装文件拷贝到此目录

[root@amoeba1 ~]# mkdir /usr/java

[root@amoeba1 ~]# cd /usr/java

赋予权限

[root@amoeba1 java]# chmod 777 jdk-6u30-linux-x64-rpm.bin

安装jdk

[root@amoeba1 java]# ./jdk-6u30-linux-x64-rpm.bin

配置环境变量

[root@amoeba1 java]# vi /etc/profile

在配置文件最后面添加下面3条语句

export JAVA_HOME=/usr/java/jdk1.6.0_30

export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export PATH=$PATH:$JAVA_HOME/bin

配置完成后,重启服务器

[root@amoeba1 java]# reboot

重启完成后查看新安装jdk版本

[root@amoeba1 ~]# java –version

安装amoeba

下载amoeba,http://sourceforge.net/projects/amoeba/files/,我用的版本是amoeba-mysql-binary-2.2.0.tar

创建amoeba文件夹,将文件解压到此文件夹

[root@amoeba1 ~]# mkdir /usr/local/amoeba

[root@amoeba1 ~]# cd /usr/local/amoeba/

[root@amoeba1 amoeba]# tar -zxvf amoeba-mysql-binary-2.2.0.tar.gz

验证是否安装成功

[root@amoeba1 amoeba]# /usr/local/amoeba/bin/amoeba start

参数配置

[root@amoeba1 amoeba]# cd /usr/local/amoeba/conf/

[root@amoeba1 conf]# ls

Amoeba有哪些主要的配置文件?

1.想象Amoeba作为数据库代理层,它一定会和很多数据库保持通信,因此它必须知道由它代理的数据库如何连接,比如最基础的:主机IP、端口、Amoeba使用的用户名和密码等等。这些信息存储在$AMOEBA_HOME/conf/dbServers.xml中。

2.Amoeba为了完成数据切分提供了完善的切分规则配置,为了了解如何分片数据、如何将数据库返回的数据整合,它必须知道切分规则。与切分规则相关的信息存储在$AMOEBA_HOME/conf/rule.xml中。

3.当我们书写SQL来操作数据库的时候,常常会用到很多不同的数据库函数,比如:UNIX_TIMESTAMP()、SYSDATE()等等。这些函数如何被Amoeba解析呢?$AMOEBA_HOME/conf/functionMap.xml描述了函数名和函数处理的关系。

4.对$AMOEBA_HOME/conf/rule.xml进行配置时,会用到一些我们自己定义的函数,比如我们需要对用户ID求HASH值来切分数据,这些函数在$AMOEBA_HOME/conf/ruleFunctionMap.xml中定义。

5.Amoeba可以制定一些可访问以及拒绝访问的主机IP地址,这部分配置在$AMOEBA_HOME/conf/access_list.conf中

6.Amoeba允许用户配置输出日志级别以及方式,配置方法使用log4j的文件格式,文件是$AMOEBA_HOME/conf/log4j.xml。

配置一个DB节点

以下是配置一个DB节点,使用Amoeba做操作转发的步骤:

1.首先,在$AMOEBA_HOME/conf/dbServers.xml中配置一台数据库,如下:

Example 3.1. 简单的DB节点配置

<?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

-->

#这份dbServers配置文件中,我们定义了三个dbServer元素,这是第一个dbServer元素的定义。这个名为abstractServer的dbServer,其abstractive属性为true,这意味着这是一个抽象的dbServer定义,可以由其他dbServer定义拓展。

<dbServer name="abstractServer" abstractive="true">

<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">

<property name="manager">${defaultManager}</property>

#manager定义了该dbServer选择的连接管理器(ConnectionManager),这里引用了amoeba.xml的配置。

<property name="sendBufferSize">64</property>

<property name="receiveBufferSize">128</property>

#在第一个dbServer元素分别定义MySQL的端口号、数据库名、用户名以及密码。

<!-- 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>

#dbServer下有poolConfig的元素,这个元素的属性主要配置了与数据库的连接池。

<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>

#命名为server1的dbServer元素,正如你设想的那样,这个server1是abstractServer的拓展,parent属性配置了拓展的抽象dbServer,它拓展了abstractServer的ipAddress属性来指名数据库的IP地址,而在端口、用户名密码、连接池配置等属性沿用了abstractServer的配置。

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

<factoryConfig>

<!-- mysql ip -->

#server1拓展了abstractServer的ipAddress属性。

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

</factoryConfig>

</dbServer>

#这一段其实并不需要配置,并不会影响到基本使用。以下大致介绍下此配置的含义:multiPool是一个虚拟的数据库节点,可以将这个节点配置成好几台数据库组成的数据库池。比如上面这个配置中仅配置了一台server1,负载均衡策略为ROUNDROBIN(轮询)。与虚拟数据库节点相关的详细教程会在后面的章节中介绍。

<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>

由此,你大概可以理解定义abstractServer的原因:当我们有一个数据库集群需要管理,这个数据库集群中节点的大部分信息可能是相同的,比如:端口号、用户名、密码等等。因此通过归纳这些共性定义出的abstractServer极大地简化了dbServers配置文件:

Example 3.2. 一个利用定义抽象节点配置集群的例子

<?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>

2.再配置完dbServer.xml后,继续配置amoeba.xml文件:

Example 3.3. 一个基本的amoeba.xml例子

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

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

<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">

<proxy>

<!-- server class must implements com.meidusa.amoeba.service.Service -->

#Service节点定义了需要启动的服务,在本配置中其class属性为“com.meidusa.amoeba.net.ServerableConnectionManager”,这意味着这是一个Proxy Service。在这个元素下的connectionFactory元素中定义其class属性为“com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory”,这意味着这是一个MySQL Proxy Service。相应的也会有MongoDB Proxy Service以及Aladdin Proxy Service。

<service name="Amoeba for Mysql" class="com.meidusa.amoeba.net.ServerableConnectionManager">

#这里定义了之前我们所定义的MySQL Proxy Service的服务端口和主机地址。

#Caution:通常Proxy Service服务的主机地址并不需要定义,如果Amoeba所在的服务器在多个网络环境内你可以定义该机器的其中一个IP来指定Amoeba所服务的网络环境。如果设置为127.0.0.1将导致其他机器无法访问Amoeba的服务。

<!-- port --

<property name="port">8066</property>

<!-- bind ipAddress -->

<!--

<property name="ipAddress">127.0.0.1</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>

#这里配置了MySQL Proxy Service的认证器,user和passwd属性分别定义Amoeba对外服务的用户名和密码。你的程序或者数据库客户端需要使用该用户名和密码来通过Amoeba连接之前定义的dbServer。

<property name="authenticator">

<bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">

<property name="user">root</property>

<property name="password">password</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元素定义了一些Proxy相关的运行期配置,如客户端及数据库服务器端的线程数以及SQL超时时间设定等等。

<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定义了一系列连接管理器,这些连接管理器可以在其他地方被引用,比如clientConnectioneManager在amoeba.xml中被引用作为MySQL Proxy Service的客户端连接管理器;defaultManager在dbServers.xml中被引用作为dbServer的数据库服务器端连接管理器。连接管理器主要配置了用于网络处理的CPU核数,默认其processor属性为Amoeba所在主机的CPU核数。

<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>

#最后一部分dbServerLoader定义了dbServers.xml的位置。queryRouter定义了规则配置及函数配置等相关文件的位置。

<!-- 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">server1</property>

<!--

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

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

-->

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

</queryRouter>

</amoeba:configuration>

在Master/Slave结构下的读写分离

首先说明一下amoeba 跟 MySQL proxy在读写分离的使用上面的区别:

在MySQL proxy 6.0版本上面如果想要读写分离并且读集群、写集群机器比较多情况下,用mysql proxy 需要相当大的工作量,目前mysql proxy没有现成的 lua脚本。mysql proxy根本没有配置文件, lua脚本就是它的全部,当然lua是相当方便的。那么同样这种东西需要编写大量的脚本才能完成一个复杂的配置。而Amoeba只需要进行相关的配置就可以满足需求。

假设有这样的使用场景,有三个数据库节点分别命名为Master、Slave1、Slave2如下:

Master: Master (可读写)

Slaves:Slave1、Slave2 (2个平等的数据库。只读/负载均衡)

针对这样的使用方式,首先在dbServers.xml中将Slave1和Slave2配置在一个虚拟的dbServer节点中,使他们组成一个数据库池。

Example 4.3. 数据库池在dbServers.xml的定义与配置

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

<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">

<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">

...

#定义了Master节点,parent为abstractServer,关于abstractServer的定义方式参照第三章。

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

<factoryConfig>

<!-- mysql ip -->

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

</factoryConfig>

</dbServer>

#定义了Slave1和Slave2节点。

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

<factoryConfig>

<!-- mysql ip -->

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

</factoryConfig>

</dbServer>

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

<factoryConfig>

<!-- mysql ip -->

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

</factoryConfig>

</dbServer>

#定义了virtualSlave的虚拟节点,这是由Slave1和Slave2组成的一个数据库池。

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

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

#loadbalance元素设置了loadbalance策略的选项,这里选择第一个“ROUNDROBIN”轮询策略,该配置提供负载均衡、failOver、故障恢复功能。

<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->

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

#poolNames定义了其中的数据库节点配置(当然也可以是虚拟的节点)。此外对于轮询策略,poolNames还定义了其轮询规则,比如设置成“Slave1,Slave1,Slave2”那么Amoeba将会以两次Slave1,一次Slave2的顺序循环对这些数据库节点转发请求。

<!-- Separated by commas,such as: server1,server2,server1 -->

<property name="poolNames">Slave1,Slave2</property>

</poolConfig>

</dbServer>

...

</amoeba:dbServers>

如果不需要配置规则那么可以不使用rule.xml而直接配置amoeba.xml中的queryRouter,配置如下:

Example 4.4. 配置amoeba.xml不使用切分功能直接配置queryRouter以读写分离

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

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

<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">

...

<queryRouter class=”com.meidusa.amoeba.mysql.parser.MysqlQueryRouter”>

#LRUMapSize属性定义了Amoeba缓存的SQL语句解析的条数。

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

#defaultPool配置了默认的数据库节点,一些除了SELECT\UPDATE\INSERT\DELETE的语句都会在defaultPool执行。

<property name="defaultPool">Master</property>

#writePool配置了数据库写库,通常配为Master,如这里就配置为之前定义的Master数据库。

<property name="writePool">Master</property>

#readPool配置了数据库读库,通常配为Slave或者Slave组成的数据库池,如这里就配置之前的virtualSlave数据库池。

<property name="readPool">virtualSlave</property>

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

</queryRouter>

...

</amoeba:configuration>

通过Amoeba对数据进行简单的分片

配置dbServers.xml

首先根据前一小节的配置,在dbServers.xml中增加一个dbServer元素(即是我们新增用于水平切分的数据库)如下:

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

<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">

<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">

...

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

<factoryConfig>

<!-- mysql ip -->

#这里仅仅在之前的dbServers.xml文件中增加了一段新的节点配置,server2同样继承了abstractServer的配置,唯一不同的是其主机地址不一样,因此它有自己的主机地址属性,你需要按自己的实际需求配置这个主机地址。

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

</factoryConfig>

</dbServer>

...

</amoeba:dbServers>

配置rule.xml

Example 3.4. 一个基本的rule.xml配置示例

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

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

<amoeba:rule xmlns:amoeba="http://amoeba.meidusa.com/">

#tableRule的name属性定义了表名、schema为数据库名、defaultPools定义了该表的默认库。

<tableRule name="staff" schema="test" defaultPools="server1,server2">

#在tableRule中定义了名为rule1的规则,规则的返回结果为POOLNAME,在这里ruleResult还有其他配置项,将在后面介绍。

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

#parameters元素定义了切分的参数,比如在例子的场景中就是按照员工号来进行切分。通常parameters的配置为该表的某列列名或几列列名。

<parameters>ID</parameters>

#expression元素定义了类似VB Script的切分表达式。在本例中,Amoeba对ID(员工号)取余,如果员工号是单数则存储在server2中,员工号是双数则存储在server1中。

<expression><![CDATA[

var division = ID % 2;

case division when 0 then 'server1';

when 1 then 'server2';

end case;

]]></expression>

</rule>

</tableRule>

</amoeba:rule>

基于Amoeba的数据水平切分

数据水平切分这种方式应该是大家都能想到的,但数据切分以后我们如何访问我们的应用,我们应用如何按照规则做实时的数据切分?在应用层面还是其他层?这个难题可以托付给Amoeba来解决。 Amoeba提供对dba非常友好的数据切分规则表达式。

之前已经有一个通过Amoeba将员工ID通过奇偶不同水平切分到两台机器上的实例。这里会使用一些稍稍复杂一些的函数来完成。

假设我们messagedb 需要根据id hash进行水平切分,我们可以根据hash范围分成2台:

规则1: abs(hash(id)) mod 2 = 0 → blogdb-1

规则2: abs(hash(id)) mod 2 = 1 → blogdb-2

这里abs、hash 都是amoeba 规则中使用到的函数,amoeba允许开发人员增加新的规则函数,这在本章节的Amoeba自定义函数配置详解小节中介绍。

数据的水平切分主要通过对rule.xml文件的配置,如以下这个配置示例:

Example 4.1. 通过配置rule.xml完成水平分区

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

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

<amoeba:rule xmlns:amoeba="http://amoeba.meidusa.com/">

...

#配置该表的表明和数据库名,defaultPools为需要MESSAGE表被分片到的两个数据库节点以逗号分隔符。defaultPools属性中的数据库节点须是dbServers.xml中配置的虚拟数据库节点或真实数据库节点。

<tableRule name="MESSAGE" schema="test" defaultPools="blogdb-1,blogdb-2">

<rule name="rule1">

#parameters元素定义了用作分区规则的字段,这里是MESSAGE.ID。

<parameters>ID</parameters>

#expression元素定义了分区规则,可以从这里了解到rule1中ID哈希取绝对值后模2为0的数据被分片到blogdb-1上。

<expression><![CDATA[ abs(hash(id)) mod 2 = 0 ]]></expression>

<defaultPools>blogdb-1</defaultPools>

</rule>

<rule name="rule2">

<parameters>ID</parameters>

<expression><![CDATA[ abs(hash(id)) mod 2 = 1 ]]></expression>

<defaultPools>blogdb-2</defaultPools>

</rule>

</tableRule>

...

</amoeba:rule>

基于Amoeba的数据垂直切分

垂直切分(纵向)数据是数据按照网站业务、产品进行切分,比如用户数据、博客文章数据、照片数据、标签数据、群组数据等等每个业务一个独立的数据库或者数据库服务器。

如果一个应用只针对单纯的业务功能模块。那么可以直接连接相应的被垂直切分的数据库。但一些复杂的应用需要用到相当多的业务数据,涉及到几乎所有的业务数据。那么垂直切分将会给应用带来一定的复杂度,而且对工程师开发也会有一定影响。整个应用的复杂度将上升。

Amoeba在其中充当了门面功能,相当于水利枢纽。疏通应用与多个数据库数据通讯。

假设有3个数据库:userdb、blogdb、otherdb

userdb:包含有user表

blogdb:包含有message、event

otherdb:其他表所在的数据库

数据的垂直切分主要通过对rule.xml文件的配置,如以下这个配置示例:

Example 4.2. 通过配置rule.xml完成垂直分区

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

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

<amoeba:rule xmlns:amoeba="http://amoeba.meidusa.com/">

...

文章大部分参考于amoeba的首页文档:

http://docs.hexnova.com/amoeba/

Amoeba for MySQL---分布式数据库Proxy解决方案的更多相关文章

  1. Amoeba:开源的分布式数据库Porxy解决方案

    http://www.biaodianfu.com/amoeba.html 什么是Amoeba? Amoeba(变形虫)项目,该开源框架于2008年 开始发布一款 Amoeba for Mysql软件 ...

  2. Mycat分布式数据库架构解决方案--Mycat实现读写分离

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 安装完 ...

  3. Mycat分布式数据库架构解决方案--Mycat实现数据库分表

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 准备工 ...

  4. Mycat分布式数据库架构解决方案--schema.xml详解

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文件 ...

  5. Mycat分布式数据库架构解决方案--Server.xml详解

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文件 ...

  6. Mycat分布式数据库架构解决方案--rule.xml详解

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文件 ...

  7. Mycat分布式数据库架构解决方案--搭建MySQL读写分离环境--一主多从

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 本文主 ...

  8. MySQL分布式数据库架构:分库、分表、排序、分页、分组、实现教程

    MySQL分库分表总结: 单库单表 : 单库单表是最常见的数据库设计,例如,有一张用户(user)表放在数据库db中,所有的用户都可以在db库中的user表中查到. 单库多表 : 随着用户数量的增加, ...

  9. mysql分布式数据库中间件对比

    目前数据库中间件有很多,基本这些中间件在下都有了解和使用,各种中间件优缺点及使用场景也都有些心的.所以总结一个关于中间件比较的系列,希望可以对大家有帮助. 1. 什么是中间件 传统的架构模式就是 应用 ...

随机推荐

  1. 使用VS Code 开发.NET Core 应用程序 部署到Linux 跨平台

    使用VS Code 开发.NET Core 应用程序 部署到Linux 跨平台. 前面讲解了VSCode开发调试 .NET Core.都只是在windows下运行. .NET Core真正的核心是跨平 ...

  2. iOS的QuickTime Plugin

    当UIWebView播放视频时,可以看到view hierarchy里有FigPluginView的身影.这个类来自于QuickTime Plugin,plugin的路径为: /Application ...

  3. jquery简单原则器(匹配索引为指定值的元素)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. mysql对表操作的各种语句

    创建表 create table tb_user( id int(类型)primary key(设置为主键) auto_increment (设置id自增长), 每一个字段用逗号隔开, name va ...

  5. 项目总结笔记系列 Maven Session2

    主题:Maven插件 1.三个生命周期. 2.猛然间,一回首,竟然发现.之前的maven插件报错的原因,不是download的问题.是没有连接上网.在HP公司连接外网,用eclipse,是需要配置代理 ...

  6. [moka同学笔记]三、Yii2.0课程笔记(魏曦老师教程)关联字段增加搜索

    关联字段增加搜索 post表关联adminuser表,通过post.author_id  adminuser.id关联,在YII2.0生成搜索,关联字段搜索时,需要输入关联字段author的id才能搜 ...

  7. HTTP狀態碼

    1xx消息 这一类型的状态码,代表请求已被接受,需要继续处理.这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束.由于HTTP/1.0协议中没有定义任何1xx状态码,所以除非在某些试 ...

  8. linux kernel: possible SYN flooding on port 8080. Sending cookie

    possible SYN flooding on port 7244. Sending cookie

  9. 代理模式的java实现

    1.  简介 代理模式(Proxy Pattern)是常用设计模式之一.代理模式的定义:Provide a surrogate or placeholder for another object to ...

  10. hibernate(四)__由表逆向创建Domain对象和对象关系映射文件

    之前我们是手写Domain对象和对象关系映射文件->然后生成数据库中的Table. 现在我们反过来先在数据库中建好Table->然后用工具生成Domain对象和对象关系映射文件. 步骤: ...