学习资料: 陈思儒——《Amoeba》
分布式数据库系统的优点:
1、降低费用。分布式数据库在地理上可以式分布的。其系统的结构符合这种分布的要求。允许用
户在自己的本地录用、查询、维护等操作,实行局部控制,降低通信代价,避免集中式需要更高要求
的硬件设备。而且分布式数据库在单台机器上面数据量较少,其响应速度明显提升。
2、提高系统整体可用性。避免了因为单台数据库的故障而造成全部瘫痪的后果。
3、易于扩展处理能力和系统规模。分布式数据库系统的结构可以很容易地扩展系统,在分布式数
据库中增加一个新的节点,不影响现有系统的正常运行。这种方式比扩大集中式系统要灵活经济。在
集中式系统中扩大系统和系统升级,由于有硬件不兼容和软件改变困难等缺点,升级的代价常常是昂
贵和不可行的。
Amoeba 是什么 [英][əˈmi:bə][美][əˈmibə]
Amoeba(变形虫)项目,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户
端透明。具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库、可并发请
求多台数据库合并结果。
主要解决问题:
- Built on Java NIO:采用java NIO 框架无阻塞模式,不像传统的Socket编程在大量并发的情况非常浪费系统资源、
而且可扩展性也较差
注:Java NIO 简介
nio是java New IO的简称,在jdk1.4里提供的新api。Sun官方标榜的特性如下:
– 为所有的原始类型提供(Buffer)缓存支持。
– 字符集编码解码解决方案。
– Channel:一个新的原始I/O抽象。
– 支持锁和内存映射文件的文件访问接口。
– 提供多路(non-bloking)非阻塞式的高伸缩性网络I/O。
- Reusable Server Connection(可重复使用的服务器连接):Amoeba 提供与数据库连接的可重用度非常高,在Amoeba系统内Database Connection同时共享给所有连接到Amoeba的客户端
- 提供读写分离、数据切分
1. 传统的读写分离技术需要通过客户端或者相关的Database Driver技术才能解决,而且客户端的
配置也比较复杂
2. 单台Database 性能总是有限制的,基于Amoeba上面可以寻找一种可线性扩展的多数据库支持。
Amoeba为DBA提供一种非常友好的类似SQL语法的数据切分规则同时客户端不用担心过多的
DataBase Server会给应用带来更多的配置。
- 支持高可用性、负责均衡
1. Amoeba 提供Database 连接的异常检测与连接恢复功能。
2. 用户可节省使用其他昂贵的负载均衡的硬件设备,Amoeba提供多台Database Server负载均衡策略
(轮询、当前活动连接数量)
Amoeba For Mysql
先决条件:
- Java SE 1.5 或以上 Amoeba 框架是基于JDK1.5开发的,采用了JDK1.5的特性。
- 支持Mysql 协议版本10(mysql 4.1以后的版本)。
- 您的网络环境至少运行有一个mysql 4.1以上的服务。
快速配置
- 配置Server
配置项 | 是否必选 | 默认值 | 说明 |
否 | 8066 | amoeba server绑定的对外端口 | |
ipAddress | 否 | 空 | Amoeba绑定的IP |
user | 是 | 空 | 客户端连接到Amoeba的用户名 |
password | 否 | 空 | 客户端连接到Amoeba的密码 |
readThreadPoolSize | 否 | 16 | 负责读客户端、database server端网络数据包线程数 |
clientSideThreadPoolSize | 否 | 16 | 负责读执行客户端请求的线程数 |
serverSideThreadPoolSize | 否 | 16 | 负责处理服务端返回数据包的线程数 |
2. 配置 ConnectionManager:需要至少配置一个ConnectionManager,每个ConnectionManager将作为一个线程启动,ConnectionManager负责管理所注册在自身的Connection,负责他们的空闲检测、死亡检测、IO Event
<!-- 每个ConnectionManager都将作为一个线程启动。 manager负责Connection IO读写/死亡检测 --> <connectionManagerList> <connectionManager name="defaultManager" class=”com.meidusa.amoeba.net.AuthingableConnectionManager”/> <connectionManager name="default"/> </connectionManagerList>
3. 配置 dbServer:需要至少配置一个dbServer,每个dbServer将是物理数据库Server的衍射
factoryConfig——目标物理数据库衍射配置情况:
配置项 | 是否必选 | 默认值 | 说明 |
manager | 是 | 空 | 表示该dbServer将注册到指定的ConnectionManager |
port | 否 | 3306 | 目标数据库端口 |
ipAddress | 否 | 127.0.0.1 | 目标数据库IP |
schema | 否 | 空 | 连接初始化的Schema |
user | 是 | 空 | 用于登录目标数据库的用户名 |
password | 否 | 空 | 用于登录目标数据库的密码 |
class | 是 | 空 |
连接工厂实现类 (com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory) |
4. poolConfig——连接池配置:
配置项 | 是否必选 | 默认值 | 说明 |
className | 否 | com.meidusa.amoeba.net.poolable.PoolableObjectPool |
连接池实现类 |
maxActive | 否 | 8 | 最大活动连接数,如果达到最大活动连接数,则会等待 |
maxIdle | 否 | 8 | 最大空闲连接数,如果超过则将会关闭多余的空闲连接 |
minIdle | 否 | 0 | 最小空闲连接数,连接池将保持最小的空闲连接,即使这些连接长久不用 |
testOnBorrow | 否 | false | 当连接在使用前 |
testWhileIdle | 否 | false | 是否检测空闲连接数,这个参数启动的时候下列两个参数才有效 |
minEvictableIdleTimeMillis | 否 | 30分钟 | 连接空闲数多少时间将被驱逐(关闭)(time Unit:ms) |
timeBetweenEvictionRunsMillis | 否 | -1 | 用于关闭空闲连接每间隔多少时间检查一次空闲连接(time Unit:ms) |
dbServer Tag Configuration
<dbServerList> <!-- 一台mysqlServer 需要配置一个pool, 如果多台 平等的mysql需要进行loadBalance, 平台已经提供一个具有负载均衡能力的objectPool:com.meidusa.amoeba.mysql.server.MultipleServerPool 简单的配置是属性加上 virtual="true",该Pool 不允许配置factoryConfig 或者自己写一个ObjectPool。 --> <dbServer name="userdb"> <!-- PoolableObjectFactory实现类 --> <factoryConfig class=”com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory”> <property name="manager">defaultManager</property> <!-- 真实mysql数据库端口 --> <property name="port">3301</property> <!-- 真实mysql数据库IP --> <property name="ipAddress">127.0.0.1</property> <!-- 用于登陆mysql的用户名 --> <property name="user">root</property> <property name="password">password</property> <property name="schema">test</property> </factoryConfig> <!-- ObjectPool实现类 --> <poolConfig class=”com.meidusa.amoeba.net.poolable.PoolableObjectPool”> <property name="maxActive">200</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="blogdb" > <!-- PoolableObjectFactory实现类 --> <factoryConfig class=”com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory”> <property name="manager">defaultManager</property> <property name="port">3302</property> <property name="ipAddress">127.0.0.1</property> <property name="user">blog</property> <property name="password">blog</property> <property name="schema">test</property> </factoryConfig> <!-- ObjectPool实现类 --> <poolConfig class=”com.meidusa.amoeba.net.poolable.PoolableObjectPool”> <property name="maxActive">200</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="other" > <!-- PoolableObjectFactory实现类 --> <<factoryConfig class=”com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory”> <property name="manager">defaultManager</property> <property name="port">3303</property> <property name="ipAddress">127.0.0.1</property> <property name="user">root</property> <property name="password">password</property> <property name="schema">test</property> </factoryConfig> <!-- ObjectPool实现类 --> <poolConfig class=”com.meidusa.amoeba.net.poolable.PoolableObjectPool”> <property name="maxActive">200</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="virtualdb" virtual="true"> <poolConfig class=”com.meidusa.amoeba.server.MultipleServerPool”> <!-- 负载均衡参数 1=ROUNDROBIN , 2=WEIGHTBASED --> <property name="loadbalance">1</property> <!-- 参与该pool负载均衡的poolName列表以逗号分割,server1、server2、server3这几个dbserver配置 省略,他们几个是平等的数据库 --> <property name="poolNames">server1,server2,server3</property> </poolConfig> </dbServer> </dbServerList>
5. QueryRouter查询路由配置:
配置项 | 是否必选 | 默认值 | 说明 |
class | 是 | 空 | QueryRouter实现类,Amoeba for Mysql (com.meidusa.amoeba.mysql.parser.MysqlQueryRouter) |
functionConfig | 否 | 空 | 用于解析sql函数的配置文件,如果不配置则将不解析包含函数sql或者解析的不完整 |
ruleConfig | 否 | 空 | 数据切分规则配置文件,如果不配置则sql数据切分功能将不能用 |
needParse | 否 | true | 是否对sql进行parse,如果false则将不能使用数据切分、读写分离等功能 |
defaultPool | 是 | 空 |
needParse=false,无法解析query,不满足切分规则的,writePool | readPool = null情况。所有sql将在默认的dbServer上面执行。 |
writePool | 否 | 空 | 启用needParse功能,并且没有匹配到数据切分规则,则update、inster、delete语句将在这个pool中执行 |
readPool | 否 | 空 | 启用needParse功能,并且没有匹配到数据切分规则,则select语句将在这个pool中执行 |
LRUMapSize | 否 | 1000 | statment cache , 存放sql解析后得到的statment |
Master/Slave结构之下的读写分离:
Master:master(1个主数据库,可读写)
Slave:slave1,slave2(2个从数据库,只读/负载均衡)
Amoeba提供读写分离pool相关配置。并且提供负载均衡配置。可配置slave1、slave2形成一个虚拟的virtualSlave,该配置提供负载均衡、failOver、故障恢复。
<dbServer name="virtualSlave" virtual="true"> <poolConfig class=”com.meidusa.amoeba.server.MultipleServerPool”> <!-- 负载均衡参数 1=ROUNDROBIN , 2=WEIGHTBASED --> <property name="loadbalance">1</property> <!-- 参与该pool负载均衡的poolName列表以逗号分割 --> <property name="poolNames">slave1,slave2</property> </poolConfig> </dbServer>
如果不启用数据切分,那么只需要配置QueryRouter属性writePool = master readPool = virtualSlave
<queryRouter class=”com.meidusa.amoeba.mysql.parser.MysqlQueryRouter”> <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>
那么遇到update / insert / delete 将query 语句发送到 writePool ,将 select 发送到 readPool 机器中执行。