mysql 高可用方案
数据库位于现代企业应用的核心,它储存了组织机构中最有价值的资产,包括客户信息、产品信息、订单信息和历史数据。另外,组织机构依赖于数据库来运行他们关键业务应用。几小时甚至是几分钟的宕机,往往会造成收入的大量流失和客户的不满。因此,保证数据库高可用是所有组织机构优先考虑的事情。对于希望在当今瞬息万变的经济环境立于不败之地并取得成功的企业来说,构建一个具有高可用性的 IT 基础架构至关重要。II 实现目标通过技术手段实现mysql数据库的高可用性,从而减少停工时间保证服务的正常稳定运行。
III 方案建设概要
III.1 现有高可用方案分析Mysql作为一款开源软件经过多年的发展,已经形成很多套实现高可用方案,并且均都投入生产使用,主要为这几种:mysql + replication 、mysql + heartbeat + 共享存储、mysql + drbd + heartbeat 、 mysql cluster。以下将依次对各个方案进行分析。III.2 Mysql+replicationIII.2.1 概述Mysql的复制(Replication)是一个异步的复制,从一个Mysql instace(称之为Master)复制到另一个Mysql instance(称之Slave)。实现整个复制操作主要由三个进程完成的,其中两个进程在Slave(Sql进程和IO进程),另外一个进程在Master(IO进程)上。
III.2.2 Mysql replication方案拓扑图
Mysql+replication主从复制拓扑图方案具体解释:要实施复制,首先必须打开Master端的binarylog(bin-log)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。III.2.3 Mysql+replication优缺点优点:易实施、成本低、经济实惠、后期维护方便,且由于整套系统架构简单,不涉及到存储及双机软件,因此系统出现故障率很低。方便做到读写分离。缺点:在主机出现问题后不能自动切换到备份机,需要人工干涉更改IP地址。III.3 mysql + heartbeat + 共享存储
III.3.1概述HA双机热备软件将操作环境推广到一种群集操作系统。群集是一种松散耦合的计算节点集合,提供网络服务或应用程序(包括数据库、web 服务和文件服务)的单一客户视图。HA双机热备软件的目标是:1:减少或消灭由软件或硬件故障引起的系统停机时间2:提供增强的系统可用性,能够不必关掉整个群集就可执行维护III.3.2 Mysql+heartbeat+共享存储方案拓扑图 方案具体解释:本方案采用高可靠性的HA双机热备软件来保证服务的高稳定性及连续性。默认情况下两台mysql机器只有一台机器在工作,当工作机mysql主机出现问题后,系统将自动切换到mysql备机上继续提供服务,而整个过程只需要30秒的时间,当mysql主机故障维修完毕后,服务将自动切换回mysql主机上继续提供服务。III.3.3 Mysql+heartbeat+共享存储优缺点优点:安全性、稳定性高,出现故障系统将自动切换,从而保证服务的连续性。缺点:相对mysql replication成本提高,需要有共享存储设备。III.4 Mysql+drbd+heartbeat
III.4.1概述此方案除了刚刚介绍完的heartbeat外,主要用了DRBD这个工具,DRBD是一种块设备,可以被用于高可用(HA)之中.它类似于一个网络RAID-1功能.当你将数据写入本地文件系统时,数据还将会被发送到网络中另一台主机上.以相同的形式记录在一个文件系统中.本地(主节点)与远程主机(备节点)的数据可以保证实时同步.当本地系统出现故障时,远程主机上还会保留有一份相同的数据,可以继续使用.III.4.2 Mysql+drbd+heartbeat方案拓扑图 III.4.3 Mysql+drbd+heartbeat优缺点优点:安全性、稳定性高,出现故障系统将自动切换,从而保证服务的连续性,相对mysql+heartbeat+存储来说对大优点是节约了存储这个硬件设备。缺点:mysql主机宕机,切换到备机,备机接管服务,待主机修复完配置failback机制的话会发生脑裂情况,需要手工执行命令进行主机接管。
III.5Mysql clusterIII.5.1 概述MySQL集群是一种分布式设计,目标是要达到没有任何单点故障点。因此,任何组成部分都应该拥有自己的内存和磁盘。任何共享存储方案如网络共享,网络文件系统和SAN设备是不推荐或不支持的。通过这种冗余设计,MySQL声称数据的可用度可以达到99。999%。III.5.2 Mysql cluster方案拓扑图 III.5.3 Mysql cluster优缺点优点:安全性、稳定性高,可以在线增加节点,官方声称可用度可达到99.999%。缺点:至少三个节点,对主机的数量有要求,无形增加方案成本、对于数据节点要求内存一致、对于引擎只能使用ndb、不支持外键功能、管理复杂
IV 可行性方案选择在上面列出的四种方案,我们都根据公司的对数据库的生产要求,做了一些筛选。mysql cluster 这个方案管理复杂ndb引擎的硬性要求凸显出来的一些大的限制,我们将此先做了排除。Mysql replication 这个方案公司目前正在使用,但是对mysql的同步的主机的高可用没有保障,固先保留。Mysql + drbd + heartbeat这个方案虽然能方便的做到主机到备机的切换,也能节约硬件的成本,但是备机向主机回切的过程中drbd的限制容易产生脑裂情况,须手工执行命令,此方案也先保留。最后就剩下了myslq + heartbeat + 共享存储方案,此方案对硬件有要求需要一个共享存储设备,在出现问题后的故障切换以及主机恢复资源的回切都表现的相当良好,固此方案将被优先考虑。
V Mysql+heartbeat+共享存储方案具体实施步骤
环境:
nfs:192.168.184.103 as4u7
主机-cm5.3:192.168.184.124 10.0.0.1
备机-as5u3:192.168.184.102 10.0.0.2
注意:关闭防火墙,selinux
第一块:nfs的搭建(在192.168.184.103上面)
[root@oracle ~]# vi /etc/exports
/data 192.168.184.*(rw,sync,no_root_squash)
[root@oracle ~]# service nfs start
[root@oracle ~]# exportfs -rv
#####################################################################
第二块:mysql的安装(主备机一样)
# tar -zxvf mysql-5.0.67.tar.gz
# cd mysql-5.0.67
# groupadd mysql
# useradd -g mysql -s /sbin/nologin -M mysql
# ./configure –prefix=/usr/local/mysql
# make && make install
# cp support-files/my-large.cnf /etc/my.cnf
# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
# chmod 755 /etc/rc.d/init.d/mysqld
加入服务队列:
# chkconfig –add mysqld
# chown -R mysql.mysql /usr/local/mysql/
# /usr/local/mysql/bin/mysql_install_db –user=mysql
# chown -R mysql.mysql /usr/local/mysql/var
# /usr/local/mysql/bin/mysqld_safe –user=mysql &
*************************************************************************
配置库文件搜索路径
# echo “/usr/local/mysql/lib/mysql” >> /etc/ld.so.conf
# ldconfig
添加/usr/local/mysql/bin到环境变量PATH中
#echo “exportPATH=$PATH:/usr/local/mysql/bin” >> /etc/profile
#source /etc/profile
**************************************************************************
在执行第三步之前,为了确保mysql+nfs的能否成功执行,可以先测试一下,我这里是这么做的,①停掉原
先的mysql。②先在主机上面把nfs挂上来挂到/data目录,③然后mv /usr/local/mysql/var /data/里面去
,④然后起mysql服务,看能不能起来,然后往里面建库建表,再用备机挂nfs看主机建的库和表是否存在,
这么来回测试。测试完就可以确定mysql+nfs是ok的了。底下出错专心找heartbeat的问题。
#######################################################################
第三块:heartbeat的安装
tar -zxvf libnet.tar.gz
cd libnet
./configure
make && make install
tar -zxvf heartbeat-2.1.3.tar.gz
cd heartbeat-2.1.3
groupadd haclient
useradd -g haclient hacluster
./ConfigureMe configure
make && make install
配置双机文件,一共需要三个文件–ha.cf、haresources、authkeys
# cd /etc/ha.d
[root@cm5 ha.d]# vi ha.cf
debugfile /var/log/ha-debug
logfile /var/log/ha-log
logfacility local0
keepalive 2
deadtime 30
warntime 10
initdead 120
auto_failback on
node as5u3
node cm5.3
udpport 694
ucast eth0 10.0.0.2
ping_group group1 192.168.184.102 192.168.184.124
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster
hopfudge
[root@cm5 ha.d]# vi haresources
cm5.3 IPaddr::192.168.184.200/24/eth0Filesystem::192.168.184.103:/data::/data::nfs mysqld
[root@cm5 ha.d]# vi authkeys
auth 1
1 crc
[root@cm5 ha.d]# chmod 600 authkeys
##########################################################
第四步:测试
1、先停掉主备机的上面的mysql,卸掉nfs的挂载。
2、/etc/init.d/heartbeat start (主备机双执行)
3、可以看到主机的虚ip已经起来了、nfs也挂上来了、mysql服务也已经起来了
4、主机上写表,断掉主机的网卡,主机释放资源,备机起来,所有的都在
5、主机网卡起来,资源从备机释放。
********************************************************************************************************************************************************************
第五步:对于innodb表的操作
上面用myisam是可以成功的。但是用innodb,主机把网卡断了,备机mysql起不来。
/var/log/mysql.log
InnoDB: Unable to lock ./ibdata1, error: 11
InnoDB: Check that you do not already have another mysqld process
InnoDB: using the same InnoDB data or log files.
/var/log/ha-log
ResourceManager[25602]: 2010/07/16_18:13:10 info: Running/etc/init.d/mysqld start
ResourceManager[25602]: 2010/07/16_18:13:41 ERROR: Return code 1 from /etc/init.d/mysqld
ResourceManager[25602]: 2010/07/16_18:13:41 CRIT: Giving up resources due tofailure of mysqld
解决思路:
1.修改了mysql.sock文件存放的路径不能全部放在共享的分区里面。(修改my.cnf)
2.既然修改mysql.sock路径就得修改启动脚本的里面的配置,详情见最后。
3.修改/etc/ha.d/haresource-------test1 IPaddr::192.168.122.13/24/eth0nfs mysqld
4.在/etc/ha.d/resource.d/里面添加了一文件 nfs ,主要作用就是设置nfs的mount
[root@test2 resource.d]# more nfs
#!/bin/sh
unset LC_ALL; export LC_ALL
unset LANGUAGE; export LANGUAGE
case "$1" in
'start')
/bin/mount -onolock 192.168.122.12:/data /var/lib/mysql
;;
'pre-start')
;;
'post-start')
;;
'stop')
/bin/umount /var/lib/mysql
;;
'pre-stop')
;;
'post-stop')
;;
*)
echo "Usage: $0 { start | pre-start | post-start | stop | pre-stop |post-stop }"
;;
esac
exit 0
5.测试
我写了一个测试脚本,脚本意思通过建立log表,不断往里面的插数据,数据的顺序依次是0、1、2……10000。
[root@test1 ~]# more test.sh
#!/bin/bash
i=0
while [ $i -lt 10000 ]
do
mysql --socket=/tmp/mysql.sock -e "insert into cm.log values("$i")";
let i=i+1
echo "add $i to table log"
done
此时在主机上面执行这个脚本,如下所示开始往数据库的log表里面插入数据了
[root@test1 ~]# ./test.sh
add 1 to table log
add 2 to table log
add 3 to table log
add 4 to table log
add 5 to table log
add 6 to table log
……
add 2026 to table log
到了插入到第2026的时候,断开主机的网卡。
查看备机mysql的log日志,看到备机的mysql的会有一个inndb检查修复的操作。很快备机的mysql服务就起来了。
[root@test2 ~]#tail –f /var/log/mysql.log
100716 22:12:23 mysqld started
100716 22:12:23 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files...
InnoDB: Restoring possible half-written data pages from the doublewrite
InnoDB: buffer...
100716 22:12:24 InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 17445609.
InnoDB: Doing recovery: scanned up to log sequence number 0 17451961
100716 22:12:25 InnoDB: Starting an apply batch of log records tothe database...
InnoDB: Progress in percents: 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 4445 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 7071 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 9697 98 99
InnoDB: Apply batch completed
100716 22:12:25 InnoDB: Started; log sequence number 0 17451961
100716 22:12:25 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.0.45' socket: '/tmp/mysql.sock' port:3306 Source distribution
在进入到备机的mysql,查看log表里面的数据一共有2027条,正截止到我们在断开主机执行到的数字2026。
[root@test2 resource.d]# mysql --socket=/tmp/mysql.sock -e "select count(*) from cm.log";
+----------+
| count(*) |
+----------+
| 2027 |