mysql-故障转移+负载均衡
环境:centOS6.5-64bit,mysql-server版本或5.x以上版本;
keepalived-1.2.12下载:http://download.csdn.net/detail/u011648187/7076813,
haproxy-1.4.24下载:http://download.csdn.net/detail/u011648187/7076801
mysql企业版本文件太大,资源里就不上传了。可自行去官网下载,不一定非要企业版,只要是5.x以上版本就可以了
也可到官方网站下载最新版本。
说明:
keepalived 实现通过 vrrp协议,通过使一个虚拟IP地址(或称浮动IP)在主备设备间的切换来达到主机冗余;
而客户机通过访问这个虚拟IP 来获取服务;
haproxy 是一款负载均衡软件,用于将请求按策略转发给不同主机,达到负载均衡的效果;
可以实现网络层或应用层上的判断分配;
mysql 开启二进制日志,做到数据库之间的双向复制,保持数据一致性;
#提醒一下,实际生产环境没人会这样搭建的,仅通过这个实验来理解这些概念,希望阅者能有所获;
server1_ip=222.31.102.19
server2_ip=222.31.102.20
server_vip=222.31.102.30
================================================
#此处关闭了防火墙,开启则另配置相应规则
service iptables stop
chkconfig iptables off
ls /opt/soft/ #提取准备软件到此处
haproxy-1.4.20.tar.gz keepalived-1.2.7.tar.gz
mkdir /opt/keepalived
mkdir /opt/scripts/ #此实验用到脚本目录
mkdir /opt/log/ #此实验日志文件夹
=================================================
[install_mysql]
#在两台主机上安装 mysql ,此处使用 rpm 包安装,yum环境可以搭本地源;
yum install -y mysql-server
service mysqld start
2.3.1 Mysql安装步骤
1. 查看系统中是否已经安装了MySql
rpm -qa | grep -i mysql
2. 如已经有mysql相关安装,将其卸载
rpm –e –nodeps xxx(1中显示的mysql相关安装)
3. 查看mysql服务
chkconfig --list | grep -i mysql
4. 删除mysql服务
如有mysql服务,将其删除
chkconfig --del mysql
5. 清除mysql文件夹
whereis mysql
将显示的文件夹删除
rm –rf xxxx
6. 安装mysql
1. 解压MySql安装包
unzip xxxx
2. 安装MySql
rpm –ivh MySQL- server*.rpm
rpm –ivh MySQL- client*.rpm
7. 启动mysql服务
1. servicemysql start
8. 首次进入mysql,修改密码
1. 查看初始密码
cat ~/.mysql_secret
2. 登陆mysql
mysql –uroot –pxxxx
3. 修改密码
set password for'root'@'localhost'=password('newpasswd');
4. 刷新权限
flush privileges;
9. 创建数据库,用户、授权…
1. 如果有数据要导入到数据库发现导入的数据有遗漏现象请修改mysql配置文件max_allowed_packet的值,windows系统下配置文件为my.ini,linux系统下为my.cnf,在配置文件找到[mysqld] 节点并在其下面插入一条max_allowed_packet=20M(可以适当修改)
=======================================================
[create_mysql_test_table]
#分别创建一张相同名称和字段的表,插入不同的值,方便中途测试 ha 和轮询是否成功;
#还有分别创建一个相同的用户
#server1
mysql
>use test;
>create table mywait(name char(9),phonechar(14));
>insert into mywait(name,phone)values('wait',15000000000);
#server2
>use test;
>create table mywait(name char(9),phonechar(14));
>insert into mywait(name,phone)values('chen',15611111111);
[new_mysql_test_user]
>mysql
>grant all on test.* to test@'%'identified by '123456';
>flush privileges;
=======================================================
#从客户机上测试一下;
mysql -utest -p123456 -h 222.31.102.19 -e"select * from test.mywait;"
mysql -utest -p123456 -h 222.31.102.20 -e"select * from test.mywait;"
#至此,mysql 基础环境搭建完成;
=======================================================
[install_keepalived]
yum install -y libnl-devel #解决依赖关系
yum install -y openssl-devel
tar xf /opt/soft/keepalived-1.2.7.tar.gz -C/opt/soft
cd /opt/soft/keepalived-1.2.7/
#with-kernel 指定内核版本时,根据本机情况使用TAB键补全
./configure --prefix=/opt/keepalived--with-kernel-dir=/usr/src/kernels/2.6.18-308.el5-i686/
make && make install
[keepalived_config]
#因为没有安装在 / 目录下,所以这些启动和配置文件都需要再 copy 一下;
cp /opt/keepalived/sbin/keepalived/usr/sbin/
cp/opt/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
cp /opt/keepalived/etc/sysconfig/keepalived/etc/sysconfig/
mkdir /etc/keepalived
cp /opt/keepalived/etc/keepalived/keepalived.conf/etc/keepalived/
#设置开机启动
[root@stb keepalived-1.2.12]# chkconfig--add keepalived
[root@stb keepalived-1.2.12]# chkconfigkeepalived --list
keepalived 0:关闭 1:关闭 2:关闭 3:关闭 4:关闭 5:关闭 6:关闭
[root@stb keepalived-1.2.12]# chkconfig keepalivedon
[root@stb keepalived-1.2.12]# chkconfigkeepalived --list
keepalived 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭
[root@stb keepalived-1.2.12]#
=======================================================
vim /etc/keepalived/keepalived.conf#keepalived 主配文件
! Configuration File for keepalived
#简单的头部,这里主要可以做邮件通知报警等的设置,此处就暂不配置了;
global_defs {
notificationd LVS_DEVEL
}
#预先定义一个脚本,方便后面调用,也可以定义多个,方便选择;
vrrp_script mysql_chk {
script "/opt/scripts/mysql_chke.sh"
interval 2 #脚本循环运行间隔
weight 2 #脚本的结果导致优先级变更,成功+2
}
#VRRP虚拟路由冗余协议配置
vrrp_instance VI_1 { #VI_1 是自定义的名称;
state MASTER #表明这是一台主设备,备用设备为 BACKUP
interface eth1 #指定VIP需要绑定的物理网卡
virtual_router_id 11 #VRID虚拟路由标识,也叫做分组名称,该组内的设备需要相同
priority 150 #定义这台设备的优先级1-254;
advert_int 1 #生存检测时的组播信息发送间隔,组内一致
authentication { #设置验证信息,组内一致
auth_type PASS #有PASS 和 AH 两种,常用 PASS
auth_pass 111 #密码
}
virtual_ipaddress { #指定VIP地址,组内一致,可以设置多个IP
222.31.102.30/24
}
track_script { #使用在这个域中使用预先定义的脚本
mysql_chk
}
#此部分所载入的脚本为外部脚本,不需要预先定义;
#也可不添加,此实验在后半部分安装haproxy后,才有添加;
notify_master /opt/scripts/start_haproxy.sh #表示当切换到master状态时,要执行的脚本
notify_fault /opt/scripts/stop_keepalived.sh #故障时执行的脚本
notify_stop /opt/scripts/stop_haproxy.sh #keepalived停止运行前运行的脚本
}
#keepalived 主和备的配置文件基本相同;只需要修改:
state BACKUP #修改为备份设备
priority 100 #优先级要比主低
#其它地方根据实际情况也可以做调整;
=======================================================
#新建刚才配置keepalived 时所定义的脚本,用于在mysql死亡后结束 keepalived
[root@stb scripts]#
[root@stb scripts]# vim mysql_chke.sh
[root@stb scripts]# cat/opt/scripts/mysql_chke.sh
#!/bin/bash
#mysql_chke.sh
#
a=`ps -C mysqld --no-header | wc -l`
if [ $a -eq 0 ];then
sleep 3
/sbin/service keepalived stop
echo "`date +%c` stop keepalived" >>/opt/log/stop_keepalived.log
fi
service keepalived start
[root@stb scripts]# service keepalivedstart #在两台设备上面启动
#开始测试
ip address
#查看主设备 11 上是否有生成 vip 地址;
#注意事项,keepalived 生成的 VIP 对 ifconfig 命令不可见,所以需要使用ip addr命令;
[root@stb ~]# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth1:
link/ether 00:0c:29:b8:94:34 brd ff:ff:ff:ff:ff:ff
inet 222.31.102.19/24 brd 222.31.102.255 scope global eth1
inet 222.31.102.30/24 scope global secondary eth1
inet6 2002:de1f:667a:b:20c:29ff:feb8:9434/64 scope global dynamic
valid_lft 2591775sec preferred_lft 604575sec
inet6 fec0::b:20c:29ff:feb8:9434/64 scope site dynamic
valid_lft 2591775sec preferred_lft 604575sec
inet6 fe80::20c:29ff:feb8:9434/64 scope link
valid_lft forever preferred_lft forever
[root@stb ~]#
mysql -utest -p123456 -h 222.31.102.30 -e"select * from test.mywait;"
#正常情况是只能查询到 MASTER 的数据库的数据;
1、尝试将 MASTER 的keepalived 停掉
2、down 掉 MASTER 的网卡
3、让mysql 启动不了,比如先注释掉mysql这个用户,后killallmysqld ,
查看mysql_chke 脚本是否会把 keepalived 结束掉;
#这个时后 vip 地址会移动到 Slave 主机上; HA 搭建的是否成功体现于查询所获取值的变化;
#当将 MASTER 恢复后,VIP 又会回到 11 的设备上;
#至此 keepalived 为 mysql 做HA 模式成功;
========================================================================
二、
[install_haproxy]
#用于将请求分别轮询到222.31.102.19 222.31.102.20
tar xf /opt/soft/haproxy-1.4.20.tar.gz -C/opt/soft/
cd /opt/soft/haproxy-1.4.20/
make TARGET=linux26 PREFIX=/opt/haproxyinstall
mkdir /opt/haproxy/conf
mkdir /opt/haproxy/logs
touch /opt/haproxy/conf/haproxy.cfg
========================================================================
[mysql_config]
#修改 mysql 监听,使 mysql 避开222.31.102.30,因为 haproxy 也要监听 30:3306 这个IP地址和端口;
vim /etc/my.cnf
#server1
[mysqld]
bind-address=222.31.102.19 #mysql 的监听,添加这一句就好了
#server2
[mysqld]
bind-address=222.31.102.20
#重启mysql
service mysqld restart
#到现在已经不能通过222.31.102.30 访问数据库了,接下来配置 haproxy
========================================================================
[config_haproxy]
#主备服务器的主配文件一致;
[root@stb scripts]# cat/opt/haproxy/conf/haproxy.cfg
global #全局系统配置
log 127.0.0.1 local0 info #定义日志级别[errwarning info debug]
#local0 是日志设备,必须为24种标准syslog设备之一;
maxconn 4096 #最大链接数
uid 0 #运行该程序的用户,此处没有其它用户了,就用的root
gid 0
daemon #以后台形式运行
nbproc 1 #进程数量
defaults #默认配置
mode tcp #所处理的类别 http |tcp | health
option redispatch #serverId对应的服务器挂掉后,强制定向到其他健康的服务器
retries 3 #三次连接失败则服务器不用
timeout connect 5000 #连接超时
timeout client 50000 #客户端超时
timeout server 50000 #服务器超时
timeout check 2000 #心跳检测超时
listen proxy
bind 222.31.102.30:3306 #监听地址
mode tcp
balance roundrobin #定义负载方式,此处为轮询
log 127.0.0.1 local0 info #定义日志类型
#rise 3三次正确表示服务器可用,fall 3表示3次失败表示服务器不可用
server db1 222.31.102.19:3306 check inter 1200 rise 2 fall 3 weight 1
server db2 222.31.102.20:3306 check inter 1200 rise 2 fall 3 weight 1
#服务器状态监控配置,可以通过定义的地址查看集群状态;
listen haproxy_stats
log 127.0.0.1 local0 info
mode http
bind 222.31.102.30:8888
option httplog
stats uri /status
stats realm Haproxy Manager
stats auth admin:admin #设置监控地址的帐号与密码
#在keepalived 主配文件中添加刚才在其末端说明的外部定义脚本
[root@stb scripts]#
#启动服务
/opt/haproxy/sbin/haproxy -f/opt/haproxy/conf/haproxy.cfg
#说明事项,keepalived 的服务主备设备上都可以同时运行,实则只有获得VIP的服务器才有效;
#但是 haproxy 启动的时候需要监听 VIP地址,所以第一次备用设备是手动起不了服务的;
#需要在 keepalived 的notify_master配置项中设定脚本,当此设备获得VIP地址后才启动 haproxy;
#有个问题在这里,我们只设定了当keepalived停止服务时,才结束 haproxy ,没有设定移交VIP时是否结束;
#其实这也不用担心,因为主机上已经没有VIP地址了,即便是监听也无效果,并无干扰;
========================================================================
##开始测试
#检测监听
netstat -tunlp | grep ha
netstat -tunlp | grep 3306
# master 设备上才会有两个程序监听不同地址的3306;
#暂未配置 mysql 互为主备就是为了方便这一阶段的排错,这样能更准确的测试;
mysql -utest -p123456 -h 222.31.102.30 -e"select * from test.mywait;"
#返回值应该是在 server1server2 之间徘徊;
sed -i 's/^mysql.*$/#&/'/etc/passwd #注释掉mysql的用户
service mysqld stop
#这个时候 mysql 服务已经启动不起了,mysql_chke.sh脚本会把 keepalived 停止掉;
keepalived 停止前,又会把 haproxy 杀死;当备份的设备获得vip 后,则会通过start_haproxy.sh 脚本将 haproxy 启动起来;
于是并不会因为服务器当机或mysql故障,影响我们客户端对 30 的查询操作,实验完成一半了;
#但是测试时,在VIP地址切换过程中,客户端会有那么2-3秒不能访问到数据库,这个暂时忽略不计;
sed 's/^#//' /etc/passwd #测试完后,记得恢复mysql用户哦;
#恢复mysql 后,启动主设备的mysqld keepalived ,然后使用 ip a 查看VIP 地址是否有返回来;
#在其中一台设备上 killallhaproxy ,之后查看集群状态;
http://222.31.102.30:8888/status
#查看后再将 haproxy 启动
#至此,已经完成 负载均衡 + 高可用 两部分,负载方式为轮询
========================================================================
##三个脚本,很简单,就不再介绍了哈;主要是做日志和结束服务;
[root@stb scripts]# cat start_haproxy.sh
#!/bin/bash
#start_haproxy.sh
sleep 5
get=`ip addr |grep 222.31.102.30 |wc -l`
echo $get >>/opt/log/start_haproxy.log
if [ $get -eq 1 ]
then
echo "`date +%c` success to get vip" >>/opt/log/start_haproxy.log
/opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg
else
echo "`date +%c` can not get vip" >>/opt/log/start_haproxy.log
fi
[root@stb scripts]#
[root@stb scripts]# cat stop_haproxy.sh
#!/bin/bash
#stop_haproxy.sh
pid=`pidof haproxy`
echo "`date +%c` stop haproxy">> /opt/log/stop_haproxy.log
kill -9 $pid
[root@stb scripts]#
[root@stb scripts]# cat stop_keepalived.sh
#!/bin/bash
#stop_keepalived.sh
pid=`pidof keepalived`
if [ $pid == "" ]
then
echo "`date +%c` no keepalived process id" >> /opt/log/stop_keepalived.log
else
echo "`date +%c` will stop keepalived " >> /opt/log/stop_keepalived.log
/etc/init.d/keepalived stop
fi
[root@stb scripts]#
=======================================================
[mysql Manager Slave]
#mysql 主备配置;两台设备上添加用户哦;
root#mysql
create database db1;
GRANT REPLICATION SLAVE ON *.* TO'test1'@'%' IDENTIFIED BY '123456';
#此处注意哦,Slave 权限必须的,我最初使用 all 权限,结果主备始终不同步,改成 Slave 就OK了;
flush privileges;
show grants for test1@'%';
==================================================================
#server1 的 mysql 配置 #server_id=1 #服务器标识,唯一 #log_bin=mysqlbinlog #启用二进制日志 #log_bin_index=mysqlbinlog-index #日志索引文件 #log_slave_updates=1 #让从服务器把自身复制的事件和记录都写到自己的二进制日志里 #relay_log=relay-log #中继日志位置;存放slave端获取到master端的二进制文件信息 #replicate_do_db=db1 ##指定需要同步的数据库
[root@stb scripts]# cat /usr/my.cnf # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html
[mysqld]
# Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M bind-address=222.31.102.19
#fyy-cust server_id=1 #服务器标识,唯一 log_bin=mysqlbinlog #启用二进制日志 log_bin_index=mysqlbinlog-index #日志索引文件 log_slave_updates=1 #让从服务器把自身复制的事件和记录都写到自己的二进制日志里 relay_log=relay-log #中继日志位置;存放slave端获取到master端的二进制文件信息 #replicate_do_db=db1 ##指定需要同步的数据库 master-host=222.31.102.20 master-user=test1 master-password=123456 master-port=3306 master-connect-retry=60 replicate-do-db=test binlog-ignore-db=mysql
# Remove leading # to turn on a very important data integrity option: logging # changes to the binary log between backups. # log_bin
# These are commonly set, remove the # and set as required. # basedir = ..... # datadir = ..... # port = ..... # server_id = ..... # socket = .....
# Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [root@stb scripts]#
|
#server2 的 mysql 配置
server_id=2 log_bin=mysqlbinlog log_bin_index=mysqlbinlog-index log_slave_updates=1 relay_log=relay-log replicate_do_db=db1 |
#分别重启两服务
service mysqld restart
mysql> show master status; #查看mysql 的当前二进制日志文件
+--------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB |Binlog_Ignore_DB |
+--------------------+----------+--------------+------------------+
| mysqlbinlog.000001 | 98 | | |
+--------------------+----------+--------------+------------------+
1 row in set (0.28 sec)
#分别连接对方 mysql 日志,开始备份;记得替换Master_Host 和日志名及MASTER_LOG_POS;
>CHANGE MASTER TOMASTER_HOST='222.31.102.20',master_port=3306,MASTER_USER='test1',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysqlbinlog.000001',MASTER_LOG_POS=98;
>START SLAVE; #开始同步
mysql> SHOW SLAVE STATUS\G #查看mysql同步状态
*************************** 1. row***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 222.31.102.19
Master_User: mywait
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysqlbinlog.000001
Read_Master_Log_Pos: 98
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 237
Relay_Master_Log_File: mysqlbinlog.000001
Slave_IO_Running: Yes #表明获取对方日志文件的连接成功;
Slave_SQL_Running: Yes #将获取到的日志转成sql语句回写本地数据库成功;
Replicate_Do_DB: db1
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 237
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
#主要就是看Slave_IO_Running,Slave_SQL_Running
#这里错误的话,多数情况是Slave_IO_Running 的问题,防火墙,用户权限,日志是否有启用等都需要判断;
=====================================================================
=====================================================================
#至此 mysql 双主互备搭建完成,我们的全部实验规划也全部完成;
#进入全面测试阶段;
#在 server1 的DB1里新建一张表,并赋值
>use db1;
>create table mywait(name char(9),phonechar(14));
>insert into mywait(name,phone)values('wait',15888888888);
#新建一个具有 db1 权限的用户
grant all on db1.* to test2@'%' identifiedby '123456';
>flush privileges;
#切换到 test 库,在mywait 表中插入一条数据;
use test;
insert into mywait(name,phone) values('test',15002839961);
#在 server2做验证;
>use db1;
>show tables;
>select * from mywait;
#此时数据与 server1 的会数据一致,表示mysql同步成功;
select user,host,password from mysql.user;
#在 server1 创建的用户也会被server2 所同步;
#select * from test.mywait
#可以看到 server1上的 test 库并没有被同步;
#客户机上测试
mysql -utest2 -p123456 -h 222.31.102.30 -e"select * from db1.mywait;"
#完毕;
=======================================================
#存在的问题;
在做mysql_chke 脚本时,本打算使用检查进程的形式判断服务是否启动;
`ps -C mysqld --no-header | wc -l`
当检查mysql 进程不存在的时候,先试着启动一次mysqld ,然后再检测,如果还是启动不了服务,再结束 keepalived ;
但是在使用 /etc/rc.d/init.d/mysqld start 启动后,出现一些问题;
比如mysql 配置文件错误或是注销用户等,mysql服务已然起不来了,虽然手动起不来服务;
但使用 ps -C mysqld 还是可以检查出一条mysqld 的进程来,这是什么情况没弄明白,希望能得到指点;
可优化项,haproxy 的功能很多,可以做成基于权重的分配方式,或是根据访问地址的,甚至可以使用 cookie 做判断;
大家都可以多测试一下;
有些地方是需要在两台服务器上同时配置的,大家看的时候多留意一下,测试过程中多看日志是最好的排错方式;