
注:未在生成环境实施过
本方案主要针对amoeba和keepalived的配置与实施,有关mysql的部分,请自行参考其他文档!
优点
1:读写分离,支持水平分区,对开发透明
2:amoeba实现对从库组灵活的负载均衡和故障自动转移,keepalived实现amoeba的主备切换、故障转移
缺点
不支持主库故障转移,依然存在主库的单点故障
AMOEBA
[安装篇]
1、什么是Amoba?
Amoeba(变形虫)项目,该开源框架于2008年开始发布一款Amoeba for Mysql软件。这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的 时候充当SQL路由功能,专注于分布式数据库代理层(Database Proxy)开发。座落与 Client、DB Server(s)之间,对客户端透明。具有负载均衡、高可用性、SQL过滤、读写分离、可路由相关的到目标数据库、可并发请求多台数据库合并结果。 通过Amoeba你能够完成多数据源的高可用、负载均衡、数据切片的功能,目前Amoeba已在很多企业的生产线上面使用。
2、Linux下安装Amoba
A.JAVA环境安装
Amoeba框架是基于Java SE1.5开发的,建议使用Java SE 1.5版本。1.6的版本也可以。
准备Java安装包 jdk-1_5_0_22-linux-i586-rpm.bin,上传二进制包至/usr/java(没有,请新建)。
cd /usr/java
给予执行权限,chmod u+x jdk-1_5_0_22-linux-i586-rpm.bin
sh jdk-1_5_0_22-linux-i586-rpm.bin或者./jdk-1_5_0_22-linux-i586-rpm.bin #执行
接下来是LICENSE,空格跳过,最后按提示输入yes.
设置java环境变量
在/etc/profile尾部加入下面的内容
export JAVA_HOME=/usr/java/jdk1.5.0_22
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
source /etc/profile 使环境变量生效
java –version 验证java
java version "1.5.0_22"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03)
Java HotSpot(TM) Client VM (build 1.5.0_22-b03, mixed mode, sharing
B 安装Amoeba
去http://sourceforge.net/projects/amoeba/files/下载最新版本的Amoaba2.0。
mkdir /usr/local/amoeba
将压缩包上传至/usr/local/amoeba
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz
将export PATH="$PATH:/usr/local/amoeba/bin" 加入/etc/profile尾部
source /etc/profile
$ amoeba #验证amoeba的安装
amoeba start|stop
后台运行amoeba amoeba start &
[配置篇]
各种配置文件介绍,配置的详细见官方文档。
本文档的末尾附上了一份参考配置。
[注意事项]
如果启动或者连接amoeba出错,首先注意检查配置文件。数据库的用户名,密码等。
其中一个数据库实例连不上,涉及到该实例的操作将不会成功!但不会影响到对其他实例的操作。
实际使用过程中,数据库连接尽可能只连接amoea这个虚拟实例,主要是使用到水平分区的功能的时候。
1 Amoeba暂不支持事务
如果必须使用事务,而且事务内的处理操作都可以路由到同一台MySQL上的话,可以考虑在存储过程中使用事务进行处理。
2 Amoeba不支持跨库join和排序
跨库的join和排序非常消耗资源,会导致性能严重下降,Amoeba没有进行支持。我们在进行数据库设计的时候,也应该尽可能避免跨库join。
3 Insert语句必须指定表的列名
Amoeba是根据SQL语句进行解析的,如果SQL语句中没有切分规则中的关键字,那么Amoeba就不会按照规则进行水平切分。比如,按照城市ID进行数据水平切分时,如下语句不会被正确切分:
INSERT INTO tb_Shop VALUES (1,5,'店铺的名称','店铺的地址',1,'2011-07-30');
而如下语句则可以正确切分:
INSERT INTO tb_Shop(Shop_ID,City_ID,ShopName,Address,ShopStatus,CreateTime) VALUES (1,5,'店铺的名称','店铺的地址',1,'2011-07-30');
也就是说,切分规则中的关键字City_ID必须要在SQL语句中出现。
4 Amoeba不支持分库分表
Amoeba不支持分库分表,只能分MySQL实例。
5 Amoeba不支持大数据量的查询
大数据量的查询非常消耗内存,Amoeba在进行大数据量查询时性能会非常差。当然,实际业务中需要进行大数据量查询的情况会非常少或者根本没必要实现这种情况。这里所谓的大数据量查询指的是一次查询结果超过十万行。
6 Amoeba需要更严格的SQL语句规范
From 关键字后面如果不是子查询,一律不能带括号()
如果的表中字段名与关键字或者函数名一样需要带上字符(比如:mytable.`order`)
【压力测试】
Amoeba自带有测试工具Benchmark,测试的脚本是bin目录下benchmark,相应的测试配置放在benchmark目录下.官方手册上介绍说:采用NIO机制,确保客户端消耗极小的资源。使用Amoeba提供的benchmark会比其他工具更加轻量级,更加有利于性能测试。
测试环境,2台普通pc,分别部署amoeba和mysql,局域网。
机器配置:AMD Athlon(tm) II X2 250 Processor 内存4G Redhat 5.8
先建立好表benchmark,
CREATE TABLE `benchmark` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`content` text NOT NULL,
`title` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
修改测试配置文件 benchmark/query.xml
./benchmark -P 8066 -c 50 -f /usr/local/amoeba/benchmark/query.xml -h 127.0.0.1 -n 100000 -u amoeba -p 123456
清掉benchmark表,TRUNCATE TABLE benchmark,给title字段加上索引,再次测试
SELECT ID, FRIEND_ID FROM test.FRIEND WHERE ID=${@Math@abs(#random.nextInt(10000))} LIMIT ${@Math@abs(#random.nextInt(100))}, ${@Math@abs(#random.nextInt(100))}; 这是备用测试参考语句,供参考
【性能调优】
Amoeba作者给出的建议:
1、在可用性测试已经完成的情况下,建议将log4j.xml 中关于日志输出level为debug的全部设置成warn或者error 级别。 日志是非常消耗系统性能的,在没有必要的情况下可以不使用debug。
2、性能测试环境: amoeba 对 cpu的要求比较高,建议将amoeba配置在多核/多cpu的机器上面。
3、amoeba多线程配置,默认只有20~30个线程,在多核/多cpu 的情况下建议开大。
4、amoeba与数据库连接数配置:在性能测试并且客户端并发量不大的情况下,建议将amoeba与数据库的连接数跟客户端与mysql的并发连接数尽量相等,这样保证一个客户端连接可以获得一个数据库连接。
结合以上以及官方手册做以下修改:
A设置amoeba启动脚本来调整内存参数
vim /usr/local/amoeba/bin/amoeba
修改DEFAULT_OPTS="-server -Xms256m -Xmx256m -Xss128k"为 DEFAULT_OPTS="-server -Xms1024m -Xmx1024m -Xss256k"
B检查log4j.xml配置,将log4j.xml 中关于日志输出level为debug的全部设置成warn或者error 级别。
C修改amoeba.xml中的
connectionManagerList定义了一系列连接管理器,这些连接管理器可以在其他地方被引用,比如clientConnectioneManager在amoeba.xml中被引用作为MySQL Proxy Service的客户端连接管理器;defaultManager在dbServers.xml中被引用作为dbServer的数据库服务器端连接管理器。连接管理器主要配置了用于网络处理的CPU核数,默认其processor属性为Amoeba所在主机的CPU核数
【监控与故障处理】
准备一个备用的amoeba实例,使用keepalived转移amoeba故障。主amoeba故障了,会切到备用amoeba。此时修复好主amoeba,并重启keepalived,即可恢复正常。
KEEPALIVED
1 去官网最新版的keepalived,使用源码安装keepalived到主备两个节点上
cd /usr/local/src
wget http://www.keepalived.org/software/keepalived-1.2.7.tar.gz
tar zxf keepalived-1.2.7.tar.gz
cd keepalived-1.2.7
./configure --prefix=/usr/local/keepalived
make
make install
2 建立服务启动脚本,以便使用service命令控制之
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived
chmod +x /etc/init.d/keepalived
因为使用非默认路径(/usr/local)安装keepalived, 故需要修改几处路径,以保证keepalived能正常启动, 需要修改的文件如下:
A修改/etc/init.d/keepalived, 寻找大约15行左右的. /etc/sysconfig/keepalived, 修改为:
. /usr/local/keepalived/etc/sysconfig/keepalived, 即指向正确的文件位置
B同时在上述行下添加以下内容(将keepavlied主程序所在路径导入到环境变量PATH中):
PATH="$PATH:/usr/local/keepalived/sbin"
export PATH
C 修改/usr/local/keepalived/etc/sysconfig/keepalived文件,设置正确的服务启动参数
KEEPALIVED_OPTIONS="-D -f /usr/local/keepalived/etc/keepalived/keepalived.conf"
3 配置主-备模式
在这种模式下,虚拟IP在某时刻只能属于某一个节点,另一个节点作为备用节点存在。当主节点不可用时,备用节点接管虚拟IP,提供正常服务。
A 主节点的配置文件/usr/local/keepalived/etc/keepalived/keepalived.conf
global_defs {
notification_email {
root@localhost #默认的配置文件中,使用第三方smtp服务器,但这在现实中几乎没有意义(需要验证的原因),我们
#其指定为localhost, 将通知信息的发送交给本地sendmail服务处理。
}
notification_email_from root@local host
smtp_server localhost
smtp_connect_timeout 30
router_id NodeA #route_id配置是为了标识当前节点,两个节点的此项设置可相同,也可不相同
}
#vrrp_script check_local { #定义一个名称为check_local的检查脚本
#script "/usr/local/keepalived/bin/check_local.sh" #shell脚本的路径
#interval 5 #运行间隔,是情况调整
#}
vrrp_instance VI_1 {
state MASTER #指定A节点为主节点 备用节点上设置为BACKUP即可
interface eth0 #绑定虚拟IP的网络接口
virtual_router_id 51 #VRRP组名,两个节点的设置必须一样,以指明各个节点属于同一VRRP组
priority 100 #主节点的优先级(1-254之间),备用节点必须比主节点优先级低
advert_int 1 #组播信息发送间隔,两个节点设置必须一样
authentication { #设置验证信息,两个节点必须一致
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #指定虚拟IP, 两个节点设置必须一样
192.168.1.230/24 #也就是client请求的ip
}
#track_script {
#check_local
#}
}
B 备节点 将主节点的配置复制到备节点,并修改以下几项:
router_id NodeB
state BACKUP
priority 99
C 为保证服务的可靠性(避免“脑裂”发生),使用一个脚本check_server.sh,检测amoeba的服务状态。这个脚本本身不存在,需要我们根据业务的需求编写。以下是本方案用到的脚本(别忘了加执行权限,chmod u+x),请加入到计划任务中:
基本原理是:检查本机的amoeba服务状态,如果amoeba不正常,则启动amoeba;启动后,多次检查amoeba状态,如果amoeba不正常,则停止keepalived服务。
#!/bin/bash
#author liuyonglong@120.net
set -x
MYSQL=/usr/local/mysql/bin/mysql
MYSQL_HOST=127.0.0.1
MYSQL_USER=amoeba
MYSQL_PORT=8066
MYSQL_PASSWORD=123456
CHECK_TIME=3
MYSQL_OK=1
#AMOEBA_STATS=`ps -ef |grep amoeba |grep -v grep |wc -l`
AMOEBA_STATS=`ps -ef |grep‘/usr/local/amoeba/bin/amoeba.classworlds’|grep -v grep |wc -l`
pidfile=/var/lock/subsys/`basename $0`.pid
if [ -f $pidfile ] && [ -e /proc/`cat $pidfile` ]
then
exit 1
fi
trap "rm -fr $pidfile ; exit 0" 1 2 3 15
echo $$ > $pidfile
if [ $AMOEBA_STATS -eq 0 ]
then
amoeba start &
sleep 5
fi
while [ $CHECK_TIME -ne 0 ]
do
let "CHECK_TIME-=1"
$MYSQL -h $MYSQL_HOST -u $MYSQL_USER -p${MYSQL_PASSWORD} -P ${MYSQL_PORT} -e "show databases;" > /dev/null 2>&1
if [ $? -eq 0 ]
then
MYSQL_OK=1
CHECK_TIME=0
else
MYSQL_OK=0
fi
done
now=`date`
status='ok!'
if [ $MYSQL_OK -eq 0 ]
then
status='fail!'
service keepalived stop
fi
echo "$status:$now" >> /root/keepalive.log
exit 0
我们在check_server.sh定义的检测规则是:
1.自身服务故障(如web超时,http返回状态不是200)
2.无法ping通网关
3.产生以上任何一个问题,均应该移除本机的虚拟IP(停止keepalived实例即可)
3 经过以上修改与配置,keepalived基本安装即可完成,启动测试之:
service keepalived restart
切勿忘记将此服务设置为开机启动
chkconfig keepalived on
使用ip addr命令验证。
正常情况下,主节点会绑定虚拟ip192.168.1.230。
可以将主节点停掉(断网、停掉keepalived或者重启机器),检查虚拟ip是否能漂移到备节点。然后恢复主节点的服务,看虚拟ip能否漂移回来。
附AMOEBA参考配置:
Amoeba.xml
dbServer.xml
