赞
踩
目录
3、配置MySQL+Keepalived故障转移的高可用环境
我们通常说的双机热备是指两台机器都在运行,但并不是两台机器都同时在提供服务。当提供服务的一台出现故障的时候,另外一台会马上自动接管并且提供服务,而且切换的时间非常短。MySQL双主复制,即互为Master-Slave(只有一个Master提供写操作),可以实现数据库服务器的热备,但是一个Master宕机后不能实现动态切换。使用Keepalived,可以通过虚拟IP,实现双主对外的统一接口以及自动检查、失败切换机制,从而实现MySQL数据库的高可用方案。之前梳理了MySQL主从同步,下面说下MySQL+Keepalived双主热备高可用方案的实施。
实现双机热备的逻辑:
- 1)先实施Master->Slave的主主同步。主主是数据双向同步,主从是数据单向同步。一般情况下,主库宕机后,需要手动将连接切换到从库上。(但是用keepalived就可以自动切换)
- 2)再结合Keepalived的使用,通过VIP实现MySQL双主对外连接的统一接口。即客户端通过Vip连接数据库;当其中一台宕机后,VIP会漂移到另一台上,这个过程对于客户端的数据连接来说几乎无感觉,从而实现高可用。
Master1:192.168.223.128 安装mysql和keepalived Master2: 192.168.223.129 安装mysql和keepalived VIP:192.168.223.136 (虚拟漂移IP,不需要另外起一台服务) 要实现主主同步,可以先实现主从同步,即master1->master2的主从同步,然后master2->master1的主从同步. 这样,双方就完成了主主同步。 注意下面几点: 1)要保证同步服务期间之间的网络联通。即能相互ping通,能使用对方授权信息连接到对方数据库(防火墙开放3306端口)。 2)同步前,双方数据库中需要同步的数据要保持一致。这样,同步环境实现后,再次更新的数据就会如期同步了。 可能出现的问题: 1、报错: Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it). 解决办法: 删除mysql数据目录下的auto.cnf文件,重启mysql服务即可! 2、另:Keepalived必须使用root账号启动!
配置文件my.cnf
#1: 主库1修改配置 vim /etc/my.cnf server-id = 1 log-bin = master-bin sync_binlog = 1 binlog_checksum = none binlog_format = ROW auto-increment-increment = 2 auto-increment-offset = 1 slave-skip-errors = all log_slave_updates=1 #2: 主库2修改配置 vim /etc/my.cnf server-id = 2 log-bin = master-bin sync_binlog = 1 #表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置 binlog_checksum = none #不做日志统计检查,提升性能 binlog_format = ROW auto-increment-increment = 2 #表示自增长字段每次递增的量,其默认值是1,取值范围是1 .. 65535 auto-increment-offset = 1 #表示自增长字段从那个数开始,他的取值范围是1 .. 65535 slave-skip-errors = all #从节点跳过所有错误 log_slave_updates=1 # 从节点也要保存binlog日志,三级同步使用 #PS:其实就server-id不一样而已 #分别重启服务 ------------------------------------------------------------------------------------ #3:分别进入128,129两台mysql服务器: mysql -uroot -proot #都创建主从连接账户repl CREATE USER repl; #从库repl密码123456 跟主库连接,有slave的权限 GRANT replication slave ON *.* TO 'repl'@'192.168.223.128或者129' identified by '123456'; #刷新生效 flush privileges; #最好将库锁住,仅仅允许读,以保证数据一致性;待主主同步环境部署后再解锁; #锁住后,就不能往表里写数据,但是重启mysql服务后就会自动解锁! flush tables with read lock; #注意该参数设置后,如果自己同步对方数据,同步前一定要记得先解锁! --------------------------------------------------------------------------------- #4:#分别创建主库连接,master_log_file和master_log_position的值需要执行:show MASTER status;查询设置比当前文件早的文件名或者比当前position小的position值 #128机器做同步操作----》 unlock tables; #先解锁,将对方数据同步到自己的数据库中 stop slave;#停止同步,避免数据有更新 CHANGE MASTER TO master_host='192.168.223.129', master_port=3306, master_user='repl', master_password='123456', master_log_file='master-bin.000001', master_log_pos=501; start slave;#开启同步 show SLAVE status;#查看从节点状态,有问题解决问题 #129机器做同步操作----》 unlock tables; #先解锁,将对方数据同步到自己的数据库中 stop slave;#停止同步,避免数据有更新 CHANGE MASTER TO master_host='192.168.223.128', master_port=3306, master_user='repl', master_password='123456', master_log_file='master-bin.000005', master_log_pos=308; start slave;#开启同步 show SLAVE status;#查看从节点状态,有问题解决问题
测试:分别在128和129上面进行数据的增删改查,可以发现数据会相互同步!
与之前keeppalived搭建Nginx高可用类似,我们都是利用keepalived的虚拟IP漂移来达到单点故障转移的问题
- Keepalived看名字就知道,保持存活,在网络里面就是保持在线了,也就是所谓的高可用或热备,用来防止单点故障(单点故障是指一旦某一点出现故障就会导
- 整个系统架构的不可用)的发生,那说到keepalived不得不说的一个协议不是VRRP协议,可以说这个协议就是keepalived实现的基础。
- 1)Keepalived的工作原理是VRRP(Virtual Router Redundancy Protocol)虚拟路由冗余协议。在VRRP中有两组重要的概念:VRRP路由器和虚拟路由器,主控路由器和备份路由器。
- 2)VRRP路由器是指运行VRRP的路由器,是物理实体,虚拟路由器是指VRRP协议创建的,是逻辑概念。一组VRRP路由器协同工作,共同构成一台虚拟路由器。
- Vrrp中存在着一种选举机制,用以选出提供服务的路由即主控路由,其他的则成了备份路由。当主控路由失效后,备份路由中会重新选举出一个主控路由,来继续工作,来保障不间断服务。
之前已经安装过Keepalived,这里不再赘述!
分别进入128,129两台服务器的keepalived.conf配置
vim /etc/keepalived/keepalived.conf -------------------------------------------------------128------------------------------------------------------ global_defs { #不与其他节点重名即可 router_id mysql_master } vrrp_script chk_mysql { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等 script "/etc/keepalived/chk_mysql.sh" #这里通过脚本监测 interval 6 #脚本执行间隔,每6s检测一次 weight -5 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance mysql { state BACKUP interface eth0 #指定虚拟ip的网卡接口 #mcast_src_ip 192.168.223.129 #如果是漂移本地IP,可以不写 virtual_router_id 51 #路由器标识,MASTER和BACKUP必须是一致的 priority 100 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.223.136 } track_script { chk_mysql } } vim /etc/keepalived/keepalived.conf -------------------------------------------------------129------------------------------------------------------ global_defs { #不与其他节点重名即可 router_id mysql_master } vrrp_script chk_mysql { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等 script "/etc/keepalived/chk_mysql.sh" #这里通过脚本监测 interval 6 #脚本执行间隔,每6s检测一次 weight -5 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance mysql { state BACKUP interface eth0 #指定虚拟ip的网卡接口 #mcast_src_ip 192.168.223.129 #如果是漂移本地IP,可以不写 virtual_router_id 51 #路由器标识,MASTER和BACKUP必须是一致的 priority 99 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.223.136 } track_script { chk_mysql } }
编辑监测脚本:vim /etc/keepalived/chk_mysql.sh
#如果mysql服务挂掉了,就会关闭keepalived的服务,让VIP漂移到其他服务节点 ------------------------------------------------------------------------------------------- #!/bin/bash counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l) if [ "${counter}" -eq 0 ]; then killall keepalived fi #当然,你也可以抢救1次再关闭.... ------------------------------------------------------------------------------------------- #!/bin/bash counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l) if [ "${counter}" -eq 0 ]; then service mysql restart sleep 5; counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l) if [ "${counter}" -eq 0 ]; then killall keepalived fi fi
分别关停其中一个服务节点服务看看效果!
192.168.223.128 :MySQL Master1;MyCAT1,Keepalived1
192.168.223.129 :MySQL Master2;MyCAT2,Keepalived2
192.168.223.130 :MySQL Slave1;
192.168.223.131 :MySQL Slave2;
192.168.223.132 :VIP
5.3.1 MySQL双主同步配置
略,参考本课件第二步
5.3.2 MySQL主从同步配置
略,参考上节课课件《分库分表之Mycat进阶》
5.3.3 MyCAT配置
核心配置:schema.xml 两个MyCAT只需要配置不同的MySQL读写服务器
- <!-- 设置表的存储方式.schema name="TESTDB" 与 server.xml中的 TESTDB 设置一致 -->
- <schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
- <table name="users" primaryKey="id" dataNode="dn1" />
- <table name="item" primaryKey="id" dataNode="dn$2-3" rule="role1"/>
- </schema>
-
- <!-- 设置表的存储方式.schema name="TESTDB" 与 server.xml中的 TESTDB 设置一致 -->
- <dataNode name="dn1" dataHost="localhost1" database="db01" />
- <dataNode name="dn2" dataHost="localhost1" database="db02" />
- <dataNode name="dn3" dataHost="localhost1" database="db03" />
-
- ---------------------------------128--------------------------------------------------------
- <!-- mycat 逻辑主机dataHost对应的物理主机.其中也设置对应的mysql登陆信息 -->
- <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
- writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
- <heartbeat>select user()</heartbeat>
- <!-- can have multi write hosts -->
- <writeHost host="hostM1" url="jdbc:mysql://192.168.223.128:3306" user="root" password="root">
- <readHost host="hostS1" url="jdbc:mysql://192.168.223.130:3306" user="root" password="root"/>
- </writeHost>
- <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
- </dataHost>
-
- ---------------------------------129--------------------------------------------------------
- <!-- mycat 逻辑主机dataHost对应的物理主机.其中也设置对应的mysql登陆信息 -->
- <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
- writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
- <heartbeat>select user()</heartbeat>
- <!-- can have multi write hosts -->
- <writeHost host="hostM1" url="jdbc:mysql://192.168.223.129:3306" user="root" password="root">
- <readHost host="hostS1" url="jdbc:mysql://192.168.223.131:3306" user="root" password="root"/>
- </writeHost>
- <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
- </dataHost>
-
5.3.4 Keepalived配置
keepalived.conf
-------------------------------------128--------------------------------------------- ! Configuration File for keepalived global_defs { #不与其他节点重名即可 router_id mycat } vrrp_script chk_mycat { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等 script "/etc/keepalived/chk_mycat.sh" #这里通过脚本监测 interval 6 #脚本执行间隔,每6s检测一次 weight -5 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance mycat { state BACKUP interface eth0 #指定虚拟ip的网卡接口 virtual_router_id 51 #路由器标识,MASTER和BACKUP必须是一致的 priority 90 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优 先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.223.132 } track_script { chk_mycat } } -------------------------------------129--------------------------------------------- ! Configuration File for keepalived global_defs { #不与其他节点重名即可 router_id mycat } vrrp_script chk_mycat { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等 script "/etc/keepalived/chk_mycat.sh" #这里通过脚本监测 interval 6 #脚本执行间隔,每6s检测一次 weight -5 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance mycat { state BACKUP interface eth0 #指定虚拟ip的网卡接口 virtual_router_id 51 #路由器标识,MASTER和BACKUP必须是一致的 priority 100 #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优 #先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.223.132 } track_script { chk_mycat } }
存活脚本 chk_mycat:
- #!/bin/bash
- counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
- if [ "${counter}" -eq 0 ]; then
- service mysqld restart
- sleep 5;
- counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
- if [ "${counter}" -eq 0 ]; then
- /usr/local/mycat/bin/mycat stop
- killall keepalived
- fi
- fi
-
PS:由于节点过多,镜像文件是复制的,一定要注意mysql的server_id和server_uuid不要相同,否则会报错
一定一定注意请检查每个数据库节点是否存在相同的server_id/server_uuid:
show variables like '%server%id%';
检测脚本执行一定要小于检测脚本执行间隔时间,否则当前检测进程还没执行完,会被下一个进程挂起,永远也不会成功!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。