在实际的应用中,数据库是非常重要和关键的一个环节。在保障数据库安全的同时,提高应用性和缩短出故障后的恢复时间,也同等重要。特别是在一些持续性和实时性要求高的应用中,故障一小时,可能会让你损失几千到几万甚至更高。
本方案致力于数据库实时备份,并且在故障发生后以最短的时间恢复和修复。
在mysql数据库的备份应用中,主从复制结构是应用的比较广泛,数据同步和实时性都很高,基本上能满足大部分的需求。
本方案基于主从复制结构的基础上,当主库出现故障时,从库能自动接管主库的功能,向外提供服务,且将自身设置为主库,将这个故障时间和影响缩短至最小,5秒内可切换完成。待原主库修复后,会自动进入从库的备份角色,如此循环。
在本方案的实现中,有两种方法且均基于mysql的主从结构中:
1、 高可用(High Availability)HA集群,用heartbeat实现及增加了故障后的恢复功能。
2 、同样是高可用,只是是自己编写脚本程序来监控,切换,恢复。
在方法1中,使用稳定的heartbeat开源软件实现,但此方法,需要多一个IP对外访问,同时在监控上,是监控机器的状态而不是mysql,有些情况下,机器是好的但mysql服务挂了,这种情况下就不准确了。不过可以修改监控方式或增加对mysql服务的监控。
方法2中,可以不用增加一个对外IP,同时在监控上,可以直接监控mysql的服务,至于稳定性,有待测试。此方法中还有一个问题,就是提供给 客户端的数据库连接IP,因为切换后,IP也就变了。如果说更改程序,那不现实。所以,这里可以用域名,不过仍然需要修改域名的IP指向或是修改客户机的 hosts文件。本文使用的是修改DNS的方法,因为DNS是自己配置的,可以灵活操作。
本文分两部分进行说明
第一部分 用 heartbeat 实现的高可用
1环境条件
两个虚拟机(IP:192.168.1.91/92/93),
CentOS5.4,mysql-5.1.37,heartbeat-2.1.3-3
2 安装前的准备
Heartbeat 的工作原理:heartbeat最核心的包括两个部分,心跳监测部分和资源接管部分,心跳监测可以通过网络链路和串口进行,而且支持冗余链路,它们之间相 互发送报文来告诉对方自己当前的状态,如果在指定的时间内未受到对方发送的报文,那么就认为对方失效,这时需启动资源接管模块来接管运行在对方主机上的资 源或者服务。更多请看官网 http://linux-ha.org/HomePage。
基础系统的安装,mysql的安装(略)
软件下载
http://linux-ha.org/DownloadSoftware
Http://www.packetfactory.net/libnet
http://dev.mysql.com/downloads/mysql/5.1.html
3 安装过程(heartbeat)
一般的软件源码安装是./configure –prefix=path;make;make install,本文使用yum安装。
yum install heartbeat
yum install heartbeat-ldirectord
有一点要注意:heartbeat的监测,可以是网络或串口,本文使用网络也就是网卡。
4 配置文档及脚本
1) Heartbeat的三个配置文件ha.cf,authkeys,haresources
Cat Ha.cf
debugfile
/
var
/
log
/
ha
-
debug
logfile
/
var
/
log
/
ha
-
log
logfacility local0
keepalive
2
deadtime
5
warntime
10
initdead
10
udpport
694
bcast eth0
auto_failback off
node mysqlm
node mysqls
respawn hacluster
/
usr
/
lib
/
heartbeat
/
ipfail
apiauth ipfail gid
=
haclient uid
=
hacluster
Cat authkeys
auth
1
1
crc
Cat haresources
mysqlm mysql_start1.sh IPaddr::
192.168
.
1.93
/
32
/
eth0
2) mysql_start1.sh脚本 3) 同保证和记录当主机由slave到master转变时记录当前master的文件和位置,需要建一个数据库和表来记录
#!
/
bin
/
sh
# author:www.osedu.net
# url:http:
/www.osedu.net
# description: mysql start
local_ip
=
192.168
.
1.91
mip
=
192.168
.
1.92
vip
=
192.168
.
1.93
mysql_in
=/
usr
/
local
/
mysqlm
mysql_bin
=
${mysql_in}
/
bin
/
mysql
mysql_user
=
root
mysql_port
=
3306
mysql_pass
=
12345
mysqld_start
=/
etc
/
rc.d
/
init.d
/
mysqldm
.
/
etc
/
rc.d
/
init.d
/
functions
function
slave_to_master() {
echo "mysql
to
master
from
slave..."
$mysql_bin
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
e "slave stop;"
log_file
=
$(${mysql_bin}
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e"show master status\G"
|
grep "
File
:"
|
a
wk
-
F
'
:
'
'
{printf $2}
'
)
log_id
=
$(${mysql_bin}
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e"show master status\G"
|
grep "Position:"
|
awk
-
F
'
:
'
'
{printf $2}
'
)
$mysql_bin
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e "
use
ms_state;
update
ms_log
set
mlf
=
'
${log_file}
'
,mlp
=
'
${log_id}
'
"
echo "mysql server
is
master"
}
function
master_to_slave {
echo "mysql
to
slave
from
master..."
if
(${mysql_bin}
-
h"${vip}"
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e"show slave status"
>
/
dev
/
null
2
>&
1
)
then
log_file
=
$(${mysql_bin}
-
h"${vip}"
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e"
use
ms_state;
select
m
lf
from
ms_log\G"
|
grep "mlf:"
|
awk
-
F
'
:
'
'
{printf $2}
'
)
log_id
=
$(${mysql_bin}
-
h"${vip}"
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e"
use
ms_state;
select
mlp
from
ms_log\G"
|
grep "mlp:"
|
awk
-
F
'
:
'
'
{printf $2}
'
)
$mysql_bin
-
u"${mysql_user}"
-
p"${mysql_pass}"
-
P"${mysql_port}"
-
e "slave stop;CHANGE MASTER
TO
MASTER_LOG_FILE
=
'
${log_file}
'
,MASTER_LOG_POS
=
${log_id};slave start";
echo "mysql server
is
slave"
fi
}
case
"$
1
"
in
start)
slave_to_master
;;
stop)
master_to_slave
;;
*
)
echo "Usage: mysql_start.sh {start
|
stop}"
echo "start
is
slave
to
master"
echo "stop
is
master
to
slave"
exit
1
esac
3) 同保证和记录当主机由slave到master转变时记录当前master的文件和位置,需要建一个数据库和表来记录
create
database
ms_state;
use
ms_state;
create
table
ms_log(
id
tinyint
(
1
) unsigned
not
null
auto_increment,
mlf
varchar
(
20
)
not
null
default
''
,
mlp
varchar
(
20
)
not
null
default
''
,
primary
key
(id)
);
insert
into
ms_log
values
(
NULL
,"test","
123
");
4) mysql的配置
log
-
bin
=
mysql
-
bin
binlog_format
=
mixed
server
-
id
=
1
master
-
host
=
192.168
.
1.92
master
-
user
=
msdata
master
-
password
=
pass
slave
-
skip
-
errors
=all
replicate
-
do
-
db
=
test
replicate
-
ignore
-
db
=
mysql
replicate
-
ignore
-
db
=
ms_state
其它配置略
经测试,91,92重起关机都能自动切换,接管93的IP,且故障机恢复后都能自动进入备份状态,且数据同步及时和一致。
第二部分 自己编写脚本实现的高可用
一 监控实现原理
自己编写脚本,实现的功能和heartbeat差不多,都是监控,切换等。
对于监控,可以监控系统的状态如ping,也可以监控mysql服务状态(本文使用的方法)。
二 实现脚本
除了用此脚本替换heartbeat外,其它的实现和配置同上。
1 监控脚本 mysql_monitor.sh
#
!/
bin
/
bash
# author:wdlinux
# http:
//
www.osedu.net
# description:monitor shell of mysql
local_ip
=
192.168
.
1.92
rip
=
192.168
.
1.91
mysql_in
=/
usr
/
local
/
mysqlm
mysql_bin
=
${mysql_in}
/
bin
/
mysql
mysql_user
=
root
mysql_pass
=
12345
mysql_port
=
3306
st
=
0
while
true
;
do
if
(${mysql_bin}
-
h
"
${rip}
"
-
u
"
${mysql_user}
"
-
p
"
${mysql_pass}
"
-
P
"
${mysql_port}
"
-
e
"
show master status
"
--
connect_timeout
=
1
>
/
dev
/
null
2
>&
1
)
then
if
(($st
==
0
));then
/
etc
/
rc.d
/
init.d
/
mysql_start1.sh stop
let st
=
$st
+
1
fi
else
for
((i
=
0
;i
<=
3
;i
++
));
do
sleep
3
if
(${mysql_bin}
-
h
"
${rip}
"
-
u
"
${mysql_user}
"
-
p
"
${mysql_pass}
"
-
P
"
${mysql_port}
"
-
e
"
show master status
"
--
conne
ct_timeout
=
1
>
/
dev
/
null
2
>&
1
)
then
break
else
if
(($i
==
3
));then
echo
"
slave to master
"
/
etc
/
rc.d
/
init.d
/
mysql_start1.sh start
###modify dns prg
exit
fi
fi
done
fi
sleep
3
done
将local_ip,rip作相应的修改,local_ip代表本机IP,rip为另一台机的IP
2 将监控脚本加入自启动,随系统启动,如
Echo “
/
etc
/
rc.d
/
init.d
/
mysql_monitor.sh
&
”
>>
/
etc
/
rc.d
/
rc.local
此方法也可以增加一个对外服务IP,如ha实现的一样,这样就省去了修改域名IP等问题。
但在脚本里,需要增加监控,添加,删除IP的实现和功能。