前言:mysql
在企业中,数据库高可用一直是企业的重中之重,中小企业不少都是使用mysql主从方案,一主多从,读写分离等,可是单主存在单点故障,从库切换成主库须要做改动。所以,若是是双主或者多主,就会增长mysql入口,增长高可用。不过多主须要考虑自增加ID问题,这个须要特别设置配置文件,好比双主,可使用奇偶,总之,主之间设置自增加ID相互不冲突就能完美解决自增加ID冲突问题。ios
复制分红三步:web
\1. master将改变记录到二进制日志(binary log)中(这些记录叫作二进制日志事件,binary log events);sql
\2. slave将master的binary log events拷贝到它的中继日志(relay log);数据库
\3. slave重作中继日志中的事件,将改变反映它本身的数据。vim
下图描述了这一过程:centos
1.两台mysql均可读写,互为主备,默认只使用一台(masterA)负责数据的写入,另外一台(masterB)备用;bash
2.masterA是masterB的主库,masterB又是masterA的主库,它们互为主从;服务器
3.两台主库之间作高可用,能够采用keepalived等方案(使用VIP对外提供服务);网络
4.全部提供服务的从服务器与masterB进行主从同步(双主多从);
5.建议采用高可用策略的时候,masterA或masterB均不因宕机恢复后而抢占VIP(非抢占模式);
这样作能够在必定程度上保证主库的高可用,在一台主库down掉以后,能够在极短的时间内切换到另外一台主库上(尽量减小主库宕机对业务形成的影响),减小了主从同步给线上主库带来的压力;
可是也有几个不足的地方:
1.masterB可能会一直处于空闲状态(能够用它当从库,负责部分查询);
2.主库后面提供服务的从库要等masterB先同步完了数据后才能去masterB上去同步数据,这样可能会形成必定程度的同步延时;
架构的简易图以下:
1.1.三、MySQL双主和主从模式的区别
主从是对主操做数据,从会实时同步数据。反之对从操做,主不会同步数据,还有可能形成数据紊乱,致使主从失效。 主主则是不管对那一台操做,另外一个都会同步数据。通常用做高容灾方案
Keepalived是一个基于VRRP协议来实现的WEB 服务高可用方案,能够利用其来避免单点故障。一个WEB服务至少会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),可是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。
keepalived可提供vrrp以及health-check功能,能够只用它提供双机浮动的vip(vrrp虚拟路由功能),这样能够简单实现一个双机热备高可用功能。
keepalived是一个相似于layer3, 4 & 5交换机制的软件,也就是咱们平时说的第3层、第4层和第5层交换。Keepalived的做用是检测web 服务器的状态。 Layer3,4&5工做在IP/TCP协议栈的IP层,TCP层,及应用层,原理分别以下:
Layer3:Keepalived使用Layer3的方式工做式时,Keepalived会按期向服务器群中的服务器
发送一个ICMP的数据包(既咱们平时用的Ping程序),若是发现某台服务的IP地址没有激活,Keepalived便报告这台服务器失效,并将它从服务器群中剔除,这种状况的典型例子是某台服务器被非法关机。Layer3的方式是以服务器的IP地址是否有效做为服务器工做正常与否的标准。在本文中将采用这种方式。
Layer4:若是您理解了Layer3的方式,Layer4就容易了。Layer4主要以TCP端口的状态来决定服务器工做正常与否。如web server的服务端口通常是80,若是Keepalived检测到80端口没有启动,则Keepalived将把这台服务器从服务器群中剔除。
Layer5:Layer5就是工做在具体的应用层了,比Layer3,Layer4要复杂一点,在网络上占用的带宽也要大一些。Keepalived将根据用户的设定检查服务器程序的运行是否正常,若是与用户的设定不相符,则Keepalived将把服务器从服务器群中剔除。
vip即虚拟ip,是附在主机网卡上的,即对主机网卡进行虚拟,此IP仍然是占用了此网段的某个IP。
Keepalived高可用服务对之间的故障切换转移,是经过 VRRP (Virtual Router Redundancy Protocol ,虚拟路由器冗余协议)来实现的。
核心:
在 Keepalived服务正常工做时,主 Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点本身还活看,当主 Master节点发生故障时,就没法发送心跳消息,备节点也就所以没法继续检测到来自主 Master节点的心跳了,因而调用自身的接管程序,接管主Master节点的 IP资源及服务。而当主 Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。
VRRP ,全 称 Virtual Router Redundancy Protocol ,中文名为虚拟路由冗余协议 ,VRRP的出现就是为了解决静态踣甶的单点故障问题,VRRP是经过一种竞选机制来将路由的任务交给某台VRRP路由器的。
解决mysql数据库Master-Slave 单点故障问题。
\1. Master-Master Replication 实现数据同步。
2.经过keepalived虚拟IP 从网络层实现单点故障时IP自动切换,从而实现高可用。
3.经过keepalived配置实现read读指向Slave节点,实现读写分离。
缺点:根据线上实际应用状况,只考虑单点网络故障及机器设备故障时虚拟ip自动切换(只切换一次)。不考虑mysql服务异常等状况,数据库异常可经过nagios等监控,防止屡次来回切换,形成数据混乱!且故障节点恢复时,要人工操做及注意步骤。
一、使用两个MySQL数据库db01,db02,互为Master和Slave,即:
一边db01做为db02的master,一旦有数据写向db01时,db02定时从db01更新
另外一边db02也做为db01的master,一旦有数据写向db02时,db01也定时从db02得到更新
(这不会致使循环,MySQL Slave默认不会记录Master同步过来的变化)
二、但从AppServer的角度来讲,同时只有一个结点db01扮演Master,另一个结点db02扮演Slave,不能同时两个结点扮演Master。即AppSever老是把write操做分配某个数据库(db01),除非db01 failed,被切换。
三、若是扮演Slave的数据库结点db02 Failed了:
a)此时appServer要可以把全部的read,write分配给db01,read操做再也不指向db02
b)一旦db02恢复过来后,继续充当Slave角色,并告诉AppServer能够将read分配给它了.
四、若是扮演Master的数据库结点db01 Failed了
a)此时appServer要可以把全部的写操做从db01切换分配给db02,也就是切换Master由db02充当
b)db01恢复过来后,充当Slave的角色,Master由db02继续扮演。
服务器:
DB1:192.168.25.3一、centos7.六、mysql5.七、keepalived、hostname:DB1
DB2:192.168.25.3二、centos7.六、mysql5.七、keepalived、hostname:DB2
Slave1:192.168.25.3四、cenots7.六、mysql5.七、hostname:slave
VIP:192.168.25.200(虚拟)
远程客户端:192.168.25.35(用来调用vip测试)
步骤
DB一、DB2两台服务器分别安装MySQL,这两台均已安装过程省略
分别修改配置文件,在/etc/my.cnf文件中得[mysqld]段加配置信息
DB1:
[root@DB1 ~]# vim /etc/my.cnf
server-id=1
log-bin=mysql-bin
relay-log=mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
auto-increment-increment = 2
auto-increment-offset = 1
slave-skip-errors = all
解释:
server-id=1(节点标识,每台的server-id不能养,必须全局惟一)
log-bin=mysql-bin(开启binlog日志,用于主从数据复制)
relay-log=mysql-relay-bin(开启relay-log日志,relay-log日志记录的是从服务器I/O 线程将主服务器的二进制日志读取过来记录到从服务器本地文件,而后SQL线程会读取relay-log日志的内容并应用到从服务器)
replicate-wild-ignore-table=mysql.%(复制过滤选项)
auto-increment-increment = 2(字段一次递增多少)
auto-increment-offset = 1(自增字段的起始值:一、三、五、七、等奇数)
保存重启,使其配置生效
[root@DB1 ~]# service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
DB2:
[root@DB2 ~]# vim /etc/my.cnf
server-id=2
log-bin=mysql-bin
relay-log=mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
auto-increment-increment = 2
auto-increment-offset = 2
slave-skip-errors = all
保存重启,使其配置生效
[root@DB2 ~]# service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
Slave1:
[root@slave1 ~]# vim /etc/my.cnf
[mysqld]
server-id=3
log-bin=mysql-bin
log-slave-updates
relay-log=mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
auto-increment-increment = 2
auto-increment-offset = 3
slave-skip-errors = all
#注:在执行主主互备以前要保证两台服务器上MySQL数据一致
DB1:
[root@DB1 ~]# mysql -uroot -pwww.123
mysql> show master status;
DB2:
[root@DB2 ~]# mysql -uroot -pwww.123
mysql> show master status;

DB1:
在DB1的数据库建立DB2的复制用户并受权
mysql> grant replication slave on *.* to 'cproot'@'192.168.25.32' identified by 'cpwww.123';
Query OK, 0 rows affected, 1 warning (0.02 sec)
刷新并查看log bin日志和pos位置
mysql> flush privileges;
Query OK, 0 rows affected (0.02 sec)
mysql> show master status;


DB2:
mysql> grant replication slave on *.* to 'cproot'@'192.168.25.31'identified by 'cpwww.123';
Query OK, 0 rows affected, 1 warning (0.02 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;

在DB2的数据库中将DB1设置为本身得主服务器
mysql> change master to master_host='192.168.25.31',master_user='cproot',master_password='cpwww.123',master_log_file='mysql-bin.000001',master_log_pos=613;
Query OK, 0 rows affected, 2 warnings (0.11 sec)
DB1:
在DB1的数据库中将DB2设置为本身的主服务器
mysql> change master to master_host='192.168.25.32',master_user='cproot',master_password='cpwww.123',master_log_file='mysql-bin.000001',master_log_pos=613;
Query OK, 0 rows affected, 2 warnings (0.11 sec)
分别查看DB一、DB2服务器状态
DB2:
mysql> start slave; Query OK, 0 rows affected (0.01 sec) mysql> show slave status\G;
若是slave_io不是yes是 这样得话那就有三种可能错误须要排查
1,网络不通
2,密码不正确
3,Pos不对
4,防火墙没关
我此次遇到的就是防火墙没关,而且用service iptables stop还很差使,我是这样解决的
先看提示得错误
提示用/bin/systemctl stop iptables.service这样得方式去关闭,这里须要先安装iptables.services而后在关闭防火墙
[root@DB2 data]# yum -y install iptables-services [root@DB2 ~]# systemctl stop iptables
DB1:
mysql> start slave; Query OK, 0 rows affected (0.01 sec) mysql> show slave status\G;
到此主主同步配置完成,查看状态slave_io和slave_sql都是yes说明主主同步成功
在DB1上建立一个数据库one,而后在DB2上查看是否同步成功
注意:在建立以前最好再次重启一下MySQL数据库否则可能会同步不成功
DB1: mysql> create database one; Query OK, 1 row affected (0.02 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | one | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec)
DB2:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | one | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) 在DB2把新建的数据库one删除掉,看看DB1上是否还存在 mysql> drop database one; Query OK, 0 rows affected (0.01 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec)
DB1:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec)
双向操做没问题,均可以同步成功,主主已经搭建成功
DB1
在DB1的数据库建立slave1的复制用户并受权
mysql> grant replication slave on *.* to 'cproot'@'192.168.25.34' identified by 'cpwww.123'; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec) mysql> show master status;
在slave里的数据库里把DB1设置为主服务器
Slave1:
mysql> change master to master_host='192.168.25.31',master_user='cproot',master_password='cpwww.123',master_log_file='mysql-bin.000003',master_log_pos=774; Query OK, 0 rows affected, 2 warnings (0.05 sec) mysql> start slave; Query OK, 0 rows affected (0.01 sec) mysql> show slave status\G
查看状态slave_io和slave_sql都是yes,这里主从就同步成功了
测试在DB1数据库新建two
DB1:
mysql> create database two; Query OK, 1 row affected (0.02 sec) mysql> show databases;
Slave1:
在slave1上查看是否同步
主从同步成功
同步错误问题总结:若是slave_io不是yes多看看防火墙是否关闭,还有就是受权是输入得帐号密码和pos是否输入正确了
DB一、DB2:
安装keepalived并将其配置成系统服务。DB1和DB2都要进行以下操做:
[root@DB1 ~]# yum install -y openssl-devel [root@DB1 ~]# cd /usr/local/src/ [root@DB1 src]# wget http://www.keepalived.org/software/keepalived-1.3.5.tar.gz [root@DB1 src]# tar -zxvf keepalived-1.3.5.tar.gz [root@DB1 src]# cd keepalived-1.3.5 [root@DB1 keepalived-1.3.5]# ./configure --prefix=/usr/local/keepalived
执行这个后会发如今最后会报错configure: error: libnfnetlink headers missing(没有的话忽略)
而后执行
[root@DB1 keepalived-1.3.5]# yum -y install libnfnetlink-devel 再从新执行./configure [root@DB1 keepalived-1.3.5]# ./configure --prefix=/usr/local/keepalived [root@DB1 keepalived-1.3.5]# make && make install
在执行这一条的时候若是遇到这样的错误多是没有依赖包
解决方法:
[root@DB2 keepalived-1.3.5]# yum -y install libnl libnl-devel libnfnetlink-devel openssl-devel
(最好是在安装以前所有执行这条语句以防发生错误)
[root@DB1 keepalived-1.3.5]# cp /usr/local/src/keepalived-1.3.5/keepalived/etc/init.d/keepalived /etc/rc.d/init.d/ [root@DB1 keepalived-1.3.5]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ [root@DB1 keepalived-1.3.5]# mkdir /etc/keepalived/ [root@DB1 keepalived-1.3.5]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ [root@DB1 keepalived-1.3.5]# cp /usr/local/keepalived/sbin/keepalived /usr/sbin/ [root@DB1 keepalived-1.3.5]# echo "/etc/init.d/keepalived start" >>/etc/rc.local
DB1:
[root@DB1 ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak [root@DB1 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { ops@wangshibo.cn tech@wangshibo.cn } notification_email_from ops@wangshibo.cn smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id MASTER-HA } vrrp_script chk_mysql_port { #检测mysql服务是否在运行。有不少方式,好比进程,用脚本检测等等 script "/opt/chk_mysql.sh" #这里经过脚本监测 interval 2 #脚本执行间隔,每2s检测一次 weight -5 #脚本结果致使的优先级变动,检测失败(脚本返回非0)则优先级 -5 fall 2 #检测连续2次失败才算肯定是真失败。会用weight减小优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance VI_1 { state BACKUP interface ens160 #指定虚拟ip的网卡接口 mcast_src_ip 192.168.25.31 virtual_router_id 79 #路由器标识,MASTER和BACKUP必须是一致的 priority 100 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就能够将VIP资源再次抢回来 \# nopreempt advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.25.200 } track_script { chk_mysql_port } }
编写切换脚本。KeepAlived作心跳检测,若是Master的MySQL服务挂了(3306端口挂了),那么它就会选择自杀。Slave的KeepAlived经过心跳检测发现这个状况,就会将VIP的请求接管
[root@DB1 ~]# vim /opt/chk_mysql.sh \#!/bin/bash counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l) if [ "${counter}" -eq 0 ]; then /etc/init.d/keepalived stop fi [root@DB1 ~]# chmod 755 /opt/chk_mysql.sh [root@DB1 ~]# /etc/init.d/keepalived start
3.二、DB2上配置keepalived,DB2服务器上的keepalived.conf文件只修改priority为9九、nopreempt不设置
DB2:
[root@DB2 ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak [root@DB2 ~]# >/etc/keepalived/keepalived.conf [root@DB2 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { ops@qq.com tech@qq.com } notification_email_from ops@wangshibo.cn smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id MASTER-HA } vrrp_script chk_mysql_port { script "/opt/chk_mysql.sh" interval 2 weight -5 fall 2 rise 1 } vrrp_instance VI_1 { state BACKUP interface ens160 mcast_src_ip 192.168.25.32 virtual_router_id 79 priority 99 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.25.200 } track_script { chk_mysql_port } } [root@DB2 ~]# cat /opt/chk_mysql.sh \#!/bin/bash counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l) if [ "${counter}" -eq 0 ]; then /etc/init.d/keepalived stop fi [root@DB2 ~]# chmod 755 /opt/chk_mysql.sh [root@DB2 ~]# /etc/init.d/keepalived start
####经常使用的指令说明
(1)notification_email:收件箱
(2)notification_email_from:发件箱
(3)vrrp_mcast_group4:VRRP多播地址,必须为D类地址,便可用IP范围为224.0.0.0~239.255.255.255
(4)script:自定义检查脚本路径
(5)interval:自定义检查脚本的执行时间间隔,单位为秒
(6)vrrp_instance:配置虚拟路由器实例
(7)state:MASTER或BACKUP,当前节点在此虚拟路由器上的初始状态,只能有一个为MASTER,其他的都应该为BACKUP,此处都须要配置为BACKUP
(8)nopreempt:定义工做模式为非抢占模式,默认为抢占模式
(9)preempt_delay:抢占模式下,节点上线后触发新选举操做的延迟时长,单位为秒
(10)interface:绑定当前虚拟路由器使用的物理接口
(11)virtual_router_id:当前虚拟路由器的惟一标识,取值范围为0~255,两个节点必须一致
(12)priority:当前主机在此虚拟路由器中的优先级,取值范围为0~255
(13)advert_int:VRRP通告心跳信息和优先级信息的时间间隔,单位为秒
(14)auth_type:认证类型
(15)auth_pass:认证密码,两个节点必须一致
(16)virtual_ipaddress:VIP地址
(17)可经过命令# man keepalived.conf查看keepalived.conf配置文件的详细帮助文档
如今查看一下vip在那一台机器,在DB1上是正确的
在DB1下是正确的
首先先测试vip能不能正常切换
在DB1上操做关闭MySQL,看看能不能飘移到DB2上,而后在启动能不能正常飘移到DB1上
DB1:
[root@DB1 ~]# /etc/init.d/mysqld stop [root@DB1 ~]# ip addr
查看得知,关闭msyql后vip已经没了
DB2:
[root@DB2 ~]# ip addr
此时VIP已经飘移到DB2上
启动DB1的MySQL和keepalived
注意:先启动MySQL在启动keepalived,由于脚本里MySQL没有启动的话keepalived启动后会再次关闭的
DB1:
[root@DB1 ~]# /etc/init.d/mysqld start Starting MySQL. SUCCESS! [root@DB1 ~]# /etc/init.d/keepalived start Starting keepalived (via systemctl): [ 肯定 ] [root@DB1 ~]# ip addr
此时VIP已经成功飘移回DB1上
首先在DB1和DB2上都要受权容许root用户远程登陆,用于在客户端登陆测试!
并在两台机器上设置IPtables防火墙规则
DB1:
受权: [root@DB1 ~]# mysql -uroot -pwww.123 mysql> grant all on *.* to root@'192.168.25.%' identified by "www.123"; Query OK, 0 rows affected, 1 warning (0.02 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec) 添加防火墙规则: [root@DB1 ~]# vim /etc/sysconfig/iptables -A INPUT -s 192.168.0.0/24 -d 224.0.0.18 -j ACCEPT #容许组播地址通讯 -A INPUT -s 192.168.0.0/24 -p vrrp -j ACCEPT #容许VRRP(虚拟路由器冗余协)通讯 -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT #开放mysql的3306端口 [root@DB1 ~]# systemctl start iptables
DB2:
[root@DB2 ~]# mysql -uroot -pwww.123 mysql> grant all on *.* to root@'192.168.25.%' identified by "www.123"; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec) [root@DB2 ~]# vim /etc/sysconfig/iptables -A INPUT -s 192.168.0.0/24 -d 224.0.0.18 -j ACCEPT #容许组播地址通讯 -A INPUT -s 192.168.0.0/24 -p vrrp -j ACCEPT #容许VRRP(虚拟路由器冗余协)通讯 -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT #开放mysql的3306端口 [root@DB2 ~]# systemctl start iptables 注意:若是在启动防火墙报错(没有文件或目录时在防火墙规则里加一条 “IPTABLES -P INPUT ACCEPT”而后保存退出会生成/etc/sysconfig/下的iptables配置文件:使用service iptables save以后再从新启动iptables就能够了)
Monitor:
经过MySQL客户端经过VIP链接,看是否能够链接成功。(链接是须要提早在服务器端受权的)
[root@monitor ~]# mysql -h 192.168.25.200 -uroot -pwww.123
建立一个数据库,而后在库中建立一个表,并插入数据。
mysql> show variables like "%hostname%"; (这条语句可查看当前VIP在那台服务器上)
mysql> show databases;
mysql> create database one; Query OK, 1 row affected (0.01 sec) mysql> use one; Database changed mysql> create table test_table(id int, name varchar(32)); Query OK, 0 rows affected (0.08 sec) mysql> show tables; +----------------+ | Tables_in_one | +----------------+ | one_table | +----------------+ 1 row in set (0.00 sec) mysql> insert into one_table(id,name) values(1,'glt'); Query OK, 1 row affected (0.02 sec)
验证数据:
分别查看DB1和DB2的数据同步状况
DB1:
[root@DB1 ~]# mysql -uroot -pwww.123 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | one | +--------------------+ 5 rows in set (0.00 sec) mysql> use one; Database changed mysql> show tables; +----------------+ | Tables_in_one | +----------------+ | one_table | +----------------+ 1 row in set (0.00 sec) mysql> select * from one_table; +------+------+ | id | name | +------+------+ | 1 | glt | +------+------+ 1 row in set (0.00 sec)
DB2:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | one | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use one Database changed mysql> show tables; +---------------+ | Tables_in_one | +---------------+ | one_table | +---------------+ 1 row in set (0.00 sec) mysql> select * from one_table -> ; +------+------+ | id | name | +------+------+ | 1 | glt | +------+------+ 1 row in set (0.00 sec)
中止DB1中的MySQL,经过VIP登陆查看当前的在那一台服务器上并继续在one库上插入数据,而后在重启DB1看是否能够同步数据。
DB1:
[root@DB1 ~]# service mysqld stop Shutting down MySQL............ SUCCESS!
Monitor:
[root@monitor ~]# mysql -h 192.168.25.200 -uroot -pwww.123 mysql> show variables like "%hostname%"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | hostname | DB2 | +---------------+-------+ 1 row in set (0.00 sec)
当前链接的是DB2,故障自动切换成功。
mysql> use one; Database changed mysql> insert into one_table(id,name)values(2,'hhh'); Query OK, 1 row affected (0.03 sec) mysql> select * from one_table; +------+------+ | id | name | +------+------+ | 1 | glt | | 2 | hhh | +------+------+ 2 rows in set (0.00 sec)
启动DB1查看同步状况
DB1:
[root@DB1 ~]# /etc/init.d/mysqld start Starting MySQL. SUCCESS! [root@DB1 ~]# mysql -uroot -pwww.123 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | one | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use one; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +---------------+ | Tables_in_one | +---------------+ | one_table | +---------------+ 1 row in set (0.00 sec) mysql> select * from one_table -> ; +------+------+ | id | name | +------+------+ | 1 | glt | | 2 | hhh | +------+------+ 2 rows in set (0.00 sec)
数据同步成功
到此,双机热备所有完成
在以前的基础上改动如下环境;以下:
192.168.25.31 MySQL+keepalived
192.168.25.32 MySQL+keepalived
写入VIP:192.168.25.200(31主,32从)
读取VIP:192.168.25.100(32主,31从)
[root@DB1 ~]# cp /etc/my.cnf /etc/my.cnf.bak [root@DB1 ~]# vim /etc/my.cnf binlog_format=mixed
[root@DB1 ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak2 [root@DB1 ~]# vim /etc/keepalived/keepalived.conf 修改以下 ! Configuration File for keepalived global_defs { notification_email { ops@wangshibo.cn tech@wangshibo.cn } notification_email_from ops@wangshibo.cn smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id MASTER-HA } vrrp_script chk_mysql_port { #检测mysql服务是否在运行。有不少方式,好比进程,用脚本检测等等 script "/opt/chk_mysql.sh" #这里经过脚本监测 interval 2 #脚本执行间隔,每2s检测一次 weight -5 #脚本结果致使的优先级变动,检测失败(脚本返回非0)则优先级 -5 fall 2 #检测连续2次失败才算肯定是真失败。会用weight减小优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance VI_1 { state BACKUP interface ens160 #指定虚拟ip的网卡接口 mcast_src_ip 192.168.25.31 virtual_router_id 79 #路由器标识,MASTER和BACKUP必须是一致的 priority 100 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就能够将VIP资源再次抢回来 nopreempt #不主动抢占资源,只有在优先级高的机器上设置便可,优先级低的机器不设置 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.25.200 #写入虚拟VIP } } track_script { chk_mysql_port vrrp_instance VI_2{ state BACKUP #另外一台配置为MASTER interface ens160 virtual_router_id 44 #注意id和上面的不一样(另外一台和这个ID同样) priority 90 #优先级,另外一台为100 advert_int 1 authentication { auth_type pass auth_pass 1111 } virtual_ipaddress { 192.168.25.100 #读取虚拟VIP } } }
##注意:在这次的环境中不知道为何DB2的keepalived必需要在/usr/local/keepalived/var/run/这个路径下把keepalived.pid文件放进去,否则启动不了,而且每启动一次这个文件就会消失一次,须要再次拷贝过去,原keepalived.pid文件在/run/keepalived.pid
[root@DB2 ~]# cp /run/keepalived.pid /usr/local/keepalived/var/run/** [root@DB2 ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak2 [root@DB2 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { ops@qq.com tech@qq.com } notification_email_from ops@wangshibo.cn smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id MASTER-HA } vrrp_script chk_mysql_port { script "/opt/chk_mysql.sh" interval 2 weight -5 fall 2 rise 1 } vrrp_instance VI_1 { state BACKUP #两台此处都是BACKUP interface ens160 #网卡接口 \#mcast_src_ip 192.168.25.32 virtual_router_id 79 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.25.200 #写入虚拟VIP } track_script { chk_mysql_port } } vrrp_instance VI_2{ state MASTER #用于MySQL读 interface ens160 #网卡接口 virtual_router_id 44 #注意id和上面的不一样(另外一台和这个ID同样) priority 100 #优先级,另外一台为90 advert_int 1 authentication { auth_type pass auth_pass 1111 } virtual_ipaddress { 192.168.25.100 #读取虚拟VIP } } }
DB1和DB2重启keepalived查看此时的虚拟ip
[root@DB1 ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:50:56:9d:45:0a brd ff:ff:ff:ff:ff:ff inet 192.168.25.31/24 brd 192.168.25.255 scope global noprefixroute ens160 valid_lft forever preferred_lft forever inet 192.168.25.200/32 scope global ens160 valid_lft forever preferred_lft forever inet6 fe80::779a:c241:de68:1ca8/64 scope link noprefixroute valid_lft forever preferred_lft forever DB1的虚拟ip是写入ip没问题
[root@DB2 ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:50:56:9d:54:61 brd ff:ff:ff:ff:ff:ff inet 192.168.25.32/24 brd 192.168.25.255 scope global noprefixroute ens160 valid_lft forever preferred_lft forever inet 192.168.25.100/32 scope global ens160 valid_lft forever preferred_lft forever inet6 fe80::5a60:abe2:4734:487e/64 scope link noprefixroute valid_lft forever preferred_lft forever
此时DB2的虚拟ip是读取ip没得问题
一、 31服务器恢复后,不要插上网线或者修改31的iP(防止数据自动同步,致使数据污染)
二、 暂时关闭keepalive(默认开机不启动)
三、 启动31的mysql并停掉slave,防止32数据同步到31,同时插上网线或者修改iP为31;
四、 检查32的slave状态是有主键冲突,若是有主键冲突,导出31上的数据,并作删除;
五、 重启32的slave,查看是否还有主键冲突,若是有继续上步操做,直到32的slave状态恢复正常;
六、 开启31的slave并查看slave状态,正常状况下应该不会出现主键冲突,若是有主键冲突,导出数据并分析缘由,(根据实际状况处理)
七、 检查31与32服务器数据是否一致,若是数据一致,切换VIP 100(读虚拟IP)到31,修改步骤以下:
a)修改32的keepalive配置vrrp_instance VI_2 中state状态为BACKUP、priority 修改成90
b)重启32 keepalive(确保31的keepalive是关闭状态)
c)修改31的keepalive配置vrrp_instance VI_2 中state状态为MASTER、priority 修改成180
d)重启31的keepalive
e)检查VIP 100(读虚拟IP)是否切到31上,而且VIP 200(写虚拟IP)应该保留在32上。
八、 线上应用测试(读与写)
故障修复后的状态应该是:
1.192.168.25.31 mysql+keepalive
2.192.168.25.32 mysql+keepalive
3.写入VIP:192.168.25.200(32主,31从)
4.读取VIP:192.168.25.100(31主,32从)
一、修复32服务器以前应断开网线或者修改ip(防止读VIP自动切回)
二、关闭keepalive 因此服务器上的keepalive 最好设计成开不会自动启动命令以下:chkconfig keepalived off
三、检查32数据库的slave状态是否正常,数据库数据同步是否正常
四、数据同步完成后启动keepalive,检查读取数据的虚拟IP 100应该切回本服务器,写数据的虚拟IP不变。
五、应用测试读写数据是否正常
一、 开启31和32数据库以前,先断网线
二、 分别检查31和32服务器的mysql更新的最新时间
三、 若是31数据比较新,先插上31的网线,使其对外提供服务。
3.1检查读和写的虚拟iP是否都在31上
3.2关闭32上的keepalive,而且开启32上msyql的salve,同步31上的数据
3.3若是同步正常启动keepalive
3.4测试读写数据是否正常
四、若是32的数据比较新,就先插上32的网线,使其对外提供服务
4.1 检查读和写的虚拟ip是否都在32上
4.2 关闭31上的keepalive,而且开启31上mysql的save,开始同步32上的数据
4.3若是同步正常,启动31的keepalive
4.4测试读写数据是否正常