关键词:MHA,mysql mha

【1】需求

  采用mysql技术,实现MHA高可用主从环境,预计未来数据量几百G

  MHA概念参考:MYSQL高可用技术概述

【2】环境技术架构

【2.1】MHA简介

该软件由两部分组成:

  • MHA Manager(管理节点)
  • MHA Node(数据节点)

MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。

MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。

整个故障转移过程对应用程序完全透明。

可以将MHA工作原理总结为如下

  1. 从宕机崩溃的master保存二进制日志事件(binlog events)
  2. 识别含有最新更新的slave
  3. 应用差异的中继日志(relay log)到其他的slave;
  4. 应用从master保存的二进制日志事件(binlog events);
  5. 提升一个slave为新的master;
  6. 使其他的slave连接新的master进行复制;

【2.2】MHA工具包

Manager工具包

组件名称 组件说明
masterha_check_ssh 检查MHA的SSH配置状况
masterha_check_repl 检查MySQL复制状况
masterha_manger 启动MHA
masterha_check_status 检测当前MHA运行状态
masterha_master_monitor 检测master是否宕机
masterha_master_switch 控制故障转移(自动或者手动)
masterha_conf_host 添加或删除配置的server信息

Node工具包

这些工具通常由MHA Manager的脚本触发,无需人为操作

组件名称 组件说明
save_binary_logs 保存和复制master的二进制日志
apply_diff_relay_logs 识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog 去除不必要的ROLLBACK事件(MHA已不再使用这个工具)
purge_relay_logs 清除中继日志(不会阻塞SQL线程)

【2.3】基本操作环境与架构

  操作系统:5台 centos7.5

  数据库版本:mysql5.7.24

  MHA 软件  :MHA 0.58

  数据库架构:基于MHA 软件实现主从复制,采用GTID+无损同步复制技术,双主多从。

项目具体部署信息
角色 ip地址 主机名 server_id 类型
Monitor host 192.168.1.201 db1   监控复制组
master 192.168.1.202 db2 2023306 写入
slave1 192.168.1.203 db3 2033306 读(备用master)
slave2 192.168.1.204 db4 2043306
slave3 192.168.1.205 db5 2053306

【3】实践环境准备(搭建GTID+半同步的1主3从)

【3.0】注意事项

(1)不要将read_only=1写进从库的配置文件,因为主库宕机时,从库要提升为主库接受写请求  mysql -e"set global read_only=1"
(2)主从节点复制的过滤规则要相同,即binlog_do_db 与 binlog_ignore_db 参数主从配置需要相同
(3)从节点需要修改配置参数 relay_log_purge=0 ,即关闭中继日志的清除

(4)serverid不能一样

#采用命令方式将从库设为只读,不要将该参数写进配置文件中
mysql -e"set global read_only=1"
#关闭中继日志的清除
mysql -e"set global relay_log_purge=0"

【3.1】host

echo "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4">> /etc/hosts
echo "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6" >>/etc/hosts echo "192.168.1.201 db1" >>/etc/hosts
echo "192.168.1.202 db2" >>/etc/hosts
echo "192.168.1.203 db3" >>/etc/hosts
echo "192.168.1.204 db4" >>/etc/hosts
echo "192.168.1.205 db5" >>/etc/hosts

【3.2】my.cnf

[client]
port =
socket = /mysql/data//mysql.sock
default-character-set=utf8 [mysql]
disable-auto-rehash #允许通过TAB键提示
default-character-set = utf8
connect-timeout = [mysqld]
server-id =
port =
user = mysql
socket = /mysql/data//mysql.sock
pid-file = /mysql/data//mysql.pid
basedir = /mysql/app/mysql/
datadir = /mysql/data//data
#bind_address = 10.10.10.11
autocommit = character-set-server=utf8
explicit_defaults_for_timestamp=true
lower_case_table_names=
back_log=
max_connections=
max_connect_errors=
table_open_cache=
external-locking=FALSE
max_allowed_packet=32M
sort_buffer_size=2M
join_buffer_size=2M
thread_cache_size=
query_cache_size=32M
#query_cache_limit=4M
transaction_isolation=READ-COMMITTED
tmp_table_size=96M
max_heap_table_size=96M ###***logs
long_query_time =
slow_query_log =
slow_query_log_file=/mysql/log//slow.log
log-error_verbosity=
log-error = /mysql/log//mysql.err
log_output = FILE #参数log_output指定了慢查询输出的格式,默认为FILE,你可以将它设为TABLE,然后就可以查询mysql架构下的slow_log表了 #log-queries-not-using-indexes
#log-slow-slave-statements
#general_log =
#general_log_file = /mysql/log//mysql.log
#max_binlog_size = 1G
#max_relay_log_size = 1G #replication_new
log_bin=/mysql/log//mysql-bin #开启binlog
log_bin_index=/mysql/log//mysql-bin.index
binlog_format=row
binlog_rows_query_log_events=on
max_binlog_size= bind-address=0.0.0.0
server_id= #从库务必记得修改
expire_logs_days= #超过7天的binlog清理
innodb_support_xa=
binlog_cache_size=1M
log_bin_trust_function_creators= #同步存储过程、函数、触发器
innodb_flush_log_at_trx_commit=
sync_binlog=
transaction-isolation=read-committed #slave parameter 如果是从库,务必放开
#relay_log=/mysql/log//relaylog/mysql-relay.log
#relay_log_purge=
#read_only=  
#slave-parallel-type=LOGICAL_CLOCK
#slave-parallel-workers=
#master_info_repository=table #master_info 会记录到 mysql.slave_master_info
#relay_log_info_repository=table #relay_log 会记录到,mysql.slave_relay_log_info
#relay_log_recovery=
#slave_skip_errors=ddl_exist_errors
#slave_preserve_commit_order= #.7的增强半同步
#如果是5.,参数前面加上loose_,如下列,如果是5. 则直接使用 rpl_semi_sync_master_enabled= 之类的就好了。
#我这里是5.7就直接做增强半同步了(loseless Semisynchronous ) plugin_dir=/mysql/app/mysql/lib/plugin/
plugin_load=rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so
loose_rpl_semi_sync_master_enabled= #MySQL开启主的半同步复制(rpl_semi_sync_master_enabled)
loose_rpl_semi_sync_slave_enabled= #MySQL5.6开启从的半同步复制
loose_rpl_semi_sync_master_timeout= #超时5秒,切回异步
rpl_semi_sync_master_wait_for_slave_count= #至少收到1个slave发会的ack
rpl_semi_sync_master_wait_point=AFTER_SYNC #MySQL .7的方法,AFTER_SYNC(default value,增强半同步) & AFTER_COMMIT(传统半同步) #GTID mode
gtid_mode=on
enforce_gtid_consistency=
log-slave-updates=
binlog_gtid_simple_recovery=

【3.3】准备测试数据

  (主库上跑,即202那台机器)

-- 【3.3.1】创建复制用户
create user 'rpl'@'192.168.1.%' identified by '';
grant replication slave on *.* to 'rpl'@'192.168.1.%';
flush privileges;
select user,host from mysql.user; -- 【3.3.2】构造测试数据
-- 构造test库和test库下的test1,test2,test3表。test4表用于模拟业务一直在运行
create database test;
use test;
create table test1(id int);
insert into test1 values(1);
create table test2(id int);
insert into test2 values(2);
create table test3(id int);
insert into test3 values(3);
commit;
create table test4(id int);
insert into test4 values(4);
commit; -- 构造存储过程sp_test4来循环插入test4表,模拟业务运行
use test;
drop procedure if exists sp_test4;
delimiter $$
create procedure sp_test4()
begin
declare n int;
set n=11;
while(n<=20)
do
insert into test.test4 values(n);
commit;
set n=n+1;
end while;
end $$
delimiter ; -- 构造事件,来调度sp_test4过程
use test;
set global event_scheduler=1; delimiter $$
create event if not exists event_test4
on schedule every 5 second
on completion preserve
enable
do
begin
call sp_test4();
end $$
delimiter ; -- 为了防止测试数据量累计导致卡顿,我这里5小时做一次truncate
delimiter $$
create event if not exists event_truncate_test4
on schedule every 5 hour
on completion preserve
enable
do
begin
truncate table test.test4;
end $$
delimiter ;

【3.4】基于xtrabackup的备份恢复初始化

-- 在202 主库上备份
innobackupex --defaults-file=/etc/my.cnf -uroot -p123456 --no-timestamp /mysql/backup/full.bak -- 传输到从库
scp -r /mysql/backup/full.bak root@192.168.1.203:/mysql/backup/
scp -r /mysql/backup/full.bak root@192.168.1.204:/mysql/backup/
scp -r /mysql/backup/full.bak root@192.168.1.205:/mysql/backup/ #在从服务器还原
innobackupex --apply-log /mysql/backup/full.bak
service mysql stop
cd /mysql/data/
mkdir data
innobackupex --defaults-file=/etc/my.cnf --copy-back /mysql/backup/full.bak
chown -R mysql:mysql /mysql
chmod -R /mysql

【3.5】主从配置

#在从服务器上执行
stop slave;
reset slave;
reset master;
SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= ;
set global gtid_purged='2c8b1813-e26f-11e9-adce-000c29658c19:1-417'; -- 这个从/mysql/backup/full.bak/xtrabackup_info 中获得
SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;
show master status; change master to
master_host='192.168.1.202',
master_user='rpl',
master_password='',
master_port=,
master_auto_position=; start slave;

【3.6】核验主从同步

(1)show slave status\G

(2)show processlist;

(3)select count(1) from test.test4;

【4】MHA

  安装参考:https://www.cnblogs.com/winstom/p/11022014.html

  概念:高可用架构方案  中的【3】MHA

【4.1】软件下载与依赖参考

【4.2】准备perl环境,安装 mha node 与 manager节点

需要在5台机器上都安装mha node,在monitor节点上安装 manager节点

#【4.2.1】安装依赖包: 监控节点manager(201)必须配置好网络yum源与epel源。其他的节点只需要本地yum源即可。 参考:yum源配置#monitor节点 一定要先安装epel源
yum install epel-release 
yum install -y perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
#【4.2.2】开始在所有节点安装node节点(这个可以只有操作系统的yum源)
cd mha4mysql-node-0.58
perl Makefile.PL
make && make install
#【4.2.2】/usr/local/bin/ 目录下会出现4个工具(node)
-r-xr-xr-x.  root root  Oct  : apply_diff_relay_logs
-r-xr-xr-x. root root Oct : filter_mysqlbinlog
-r-xr-xr-x. root root Oct : purge_relay_logs
-r-xr-xr-x. root root Oct : save_binary_logs
Node脚本说明:(这些工具通常由MHA Manager的脚本触发,无需人为操作) save_binary_logs //保存和复制master的二进制日志
apply_diff_relay_logs //识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog //去除不必要的ROLLBACK事件(MHA已不再使用这个工具)
purge_relay_logs //清除中继日志(不会阻塞SQL线程)

#【4.2.3】开始在201安装manager(【注意查看【4.2】的yum依赖包安装,否则该步骤会部分操作失败】)

cd mha4mysql-manager-0.58
perl Makefile.PL
make && make install

#【4.2.4】把上面生成的工具命令所在目录添加到环境变量

 echo "export PATH=${PATH}:/usr/local/bin">>/etc/profile source /etc/profile

#201机器,安装完node和manager节点之后,/usr/local/bin 目录如下

  

【4.3】秘钥互信及复制mysql共享库到系统库

  (要MHA故障自动转移必须要这个)

(1)秘钥互信
配置所有机器相互之间root用户秘钥互信
在所有机器上执行: 生成密钥对
  ssh-keygen -t dsa -f ~/.ssh/id_rsa -P "" #推送公钥
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.201
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.202
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.203
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.204
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.205
#此时所有的机器之间以完成互信,无需密码等即可ssh登陆 (2)复制mysql客户端共享库到Linux系统库下
cp /mysql/app/mysql/lib/libmysqlclient.so.20 /lib64/

【4.4】MHA配置及relay_log清理脚本(4.4.3)

在monitor,即201机器上配置

#【4.4.1】复制监控节点配置文件
mkdir -p /etc/masterha
cp /soft/mha4mysql-manager-0.58/samples/conf/app1.cnf  /etc/masterha/ #默认引用配置文件位置为:/etc/masterha_default.cnf #【4.4.2】修改监控节点配置文件
mkdir -p /var/log/masterha/app1
touch /var/log/masterha/app1/manager.log
chmod -R 777 /var/log/masterha/
vim /etc/masterha/app1.cnf
[server default]
manager_workdir=/var/log/masterha/app1 #管理节点工作目录
manager_log=/var/log/masterha/app1/manager.log #管理节点日志
master_binlog_dir=/mysql/log/3306 #数据库Binlog所在日志
master_ip_failover_script=/usr/local/bin/master_ip_failover #自动故障转移的脚本
master_ip_online_change_script=/usr/local/bin/master_ip_online_change #手动在线切换主节点的脚本
password= #mysql数据库监控密码
user=root #mysql数据库监控用户
ping_interval= #发送ping间隔包的时间,默认3S,这里1是1S,如果3次没有响应则故障切换
remote_workdir=/tmp #mysql切换的时候binlog保存路径
repl_password= #mysql复制的mysql用户密码
repl_user=rpl #mysql复制的Mysql用户账户
report_script=/usr/local/bin/send_report #发生切换之后的报警报告脚本
secondary_check_script=/usr/local/bin/masterha_secondary_check -s db2 -s db3 -s db4 -s db5 #检测哪个库是最新的,以便故障转移时为新主库
shutdown_script="" #关闭的脚本
ssh_user=root #SSH通信的用户 [server1]
hostname=192.168.1.202
port= [server2]
hostname=192.168.1.203
port=
candidate_master= #设置为备用主库,当多个SERVER都有设置它,用最新的做主库
check_repl_delay= #切换的时候忽略复制延迟,

#默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

[server3]
port=
hostname=192.168.1.204 [server4]
hostname=192.168.1.205
port=
no_master= #不会成为主库 直接可用配置参数代码:
[server default]
manager_workdir=/var/log/masterha/app1
manager_log=/var/log/masterha/app1/manager.log master_binlog_dir=/mysql/log/
master_ip_failover_script=/usr/local/bin/master_ip_failover
master_ip_online_change_script=/usr/local/bin/master_ip_online_change
password=
user=root
ping_interval=
remote_workdir=/tmp
repl_password=
repl_user=rpl
report_script=/usr/local/bin/send_report
secondary_check_script=/usr/local/bin/masterha_secondary_check -s db2 -s db3 -s db4 -s db5
shutdown_script=""
ssh_user=root [server1]
hostname=192.168.1.202
port=
candidate_master= [server2]
hostname=192.168.1.203
port=
candidate_master=
check_repl_delay= [server3]
port=
hostname=192.168.1.204 [server4]
hostname=192.168.1.205
port=
no_master=

#配置文件说明
MHA主要配置文件说明

manager_workdir=/var/log/masterha/app1.log:设置manager的工作目录
manager_log=/var/log/masterha/app1/manager.log:设置manager的日志文件
master_binlog_dir=/data/mysql:设置master 保存binlog的位置,以便MHA可以找到master的日志
master_ip_failover_script= /usr/local/bin/master_ip_failover:设置自动failover时候的切换脚本
master_ip_online_change_script= /usr/local/bin/master_ip_online_change:设置手动切换时候的切换脚本
user=root:设置监控mysql的用户
password=dayi123:设置监控mysql的用户,需要授权能够在manager节点远程登录
ping_interval=:设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover
remote_workdir=/tmp:设置远端mysql在发生切换时binlog的保存位置
repl_user=repl :设置mysql中用于复制的用户密码
repl_password=replication:设置mysql中用于复制的用户
report_script=/usr/local/send_report:设置发生切换后发送的报警的脚本
shutdown_script="":设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)
ssh_user=root //设置ssh的登录用户名
candidate_master=:在节点下设置,设置当前节点为候选的master
slave check_repl_delay= :在节点配置下设置,默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master;这个选项对于对于设置了candidate_master=1的主机非常有用
secondary_check_script=/usr/local/bin/masterha_secondary_check -s db2 -s db3 -s db4 -s db5 #检测哪个库是最新的,以便故障转移的时候确认信主库
 

【4.4.3】设置定期清理relay脚本(node节点服务器,即202~205)

#在202机器上执行
弄之前,先给主库,再加个IP网卡 :/sbin/ifconfig ens34:1 192.168.1.210/24,然后作为VIP使用
mysql -uroot -p123456 -e"set global relay_log_purge=0;" #所有202~205都执行
vim /usr/local/bin/purge_relay_log.sh #新建/修改如下
#!/bin/bash
user=root #mysql的账户密码
password=
port=
socket=/mysql/data//mysql.sock
log_dir='/var/log/masterha/log'
work_dir='/mysql/log/3306/relaylog'
purge='/usr/local/bin/purge_relay_logs'
if [ ! -d $log_dir ]
then
mkdir -p $log_dir
fi
$purge --user=${user} --password=${password} -S ${socket} --host=localhost --disable_relay_log_purge --port=${port}

#复制到202~205上的每一台机器上去

  scp root@192.168.1.202:/usr/local/bin/purge_relay_log.sh /usr/local/bin

#添加到crontab,每4小时执行一次

  chmod +x /usr/local/bin/purge_relay_log.sh

  crontab -e

  0 4 * * * /bin/bash /usr/local/bin/purge_relay_log.sh

  #4个小时清理一次

#手工执行以下查看该脚本是否报错

【4.5】VIP配置

  这些官方有脚本,但是这是比较新的脚本,我们还是用我们自己的老脚本

    

  (1)手工用脚本实现  

    【4.5.1】自动故障转移VIP脚本(master_ip_failover)    
    【4.5.2】手动故障转移VIP配置脚本(master_ip_online_change)

  (2)keepalived

手动配置VIP

#在主库上,手动添加vip地址
nohup ping -c 192.168.1.210
if [ $? != ];then
/sbin/ifconfig ens34: 192.168.1.210/
fi #在主、备主上,根据情况脚本设置开机自启
cat << eof >>/etc/rc.d/rc.local
nohup ping -c 192.168.1.210
if [ $? != ];then
/sbin/ifconfig ens34: 192.168.1.210/
fi
eof

如何删掉这个手动添加的VIP地址?

ifconfig ens34:1 down
#ip addr del 192.168.1.210 dev ens34 #开启
ifconfig ens34:1 up
ifup ifcfg-ens34:1

也可以通过构建一个新的网口网卡:http://www.lwops.cn/forum.php?mod=viewthread&tid=311&fromuid=1&tdsourcetag=s_pctim_aiomsg

大致步骤:

  (1)在主、备主上,复制 cp /etc/sysconfig/network-script/ifcfg-ens34   /etc/sysconfig/network-script/ifcfg-ens34:1 ,配置好IP地址为VIP

  (2)先在主库上启动这个网卡 ifup ifcfg-ens34:1  ,(注意不同主和备注 两个同事开启,会IP地址冲突的)

  (3)在两台机器上都添加下面脚本,并添加到开机启动,以防有机器宕机重启后 脚本不执行了。  避免配置问题不要使用 systemctl restart network 以防有问题直接远程都连不上,单独开启这个网卡用这个 ifup ifcfg-ens34:1

#在主、备主上,根据情况脚本设置开机自启
cat << eof >>/etc/rc.d/rc.local
nohup ping -c 2 192.168.1.210
if [ $? != 0 ];then
/sbin/ifconfig ens34:1 192.168.1.210/24
fi
eof

 手动故障转移等脚本配置


【4.5.1】MHA自动故障转移VIP脚本(master_ip_failover)
弄之前,先给主库,再加个IP网卡 :/sbin/ifconfig ens34:1 192.168.1.210/24,然后作为VIP使用
#修改 master_ip_failover脚本,使用脚本管理VIP
vim /usr/local/bin/master_ip_failover
#!/usr/bin/env perl

use strict;
use warnings FATAL => 'all'; use Getopt::Long; my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
); my $vip = '192.168.1.210/24';
my $key = '';
my $ssh_start_vip = "/sbin/ifconfig ens34:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens34:$key down"; GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
); exit &main(); sub main { print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n"; if ( $command eq "stop" || $command eq "stopssh" ) { my $exit_code = ;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = ;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) { my $exit_code = ;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = ;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
exit ;
}
else {
&usage();
exit ;
}
} sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
return unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
} sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
【4.5.2】手动故障转移VIP配置脚本(master_ip_online_change)
弄之前,先给主库,再加个IP网卡 :/sbin/ifconfig ens34:1 192.168.1.210/24,然后作为VIP使用
vim /usr/local/bin/master_ip_online_change
(1)官方版
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
use MHA::DBHelper;
use MHA::NodeUtil;
use Time::HiRes qw( sleep gettimeofday tv_interval );
use Data::Dumper; my $_tstart;
my $_running_interval = 0.1;
my (
  $command,          $orig_master_host, $orig_master_ip,
  $orig_master_port, $orig_master_user, 
  $new_master_host,  $new_master_ip,    $new_master_port,
  $new_master_user,  
); my $vip = '192.168.1.210/24';  # Virtual IP 
my $key = "1"; 
my $ssh_start_vip = "/sbin/ifconfig ens34:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens34:$key down";
my $ssh_user = "root";
my $new_master_password='123456';
my $orig_master_password='123456';
GetOptions(
  'command=s'              => \$command,
  #'ssh_user=s'             => \$ssh_user,  
  'orig_master_host=s'     => \$orig_master_host,
  'orig_master_ip=s'       => \$orig_master_ip,
  'orig_master_port=i'     => \$orig_master_port,
  'orig_master_user=s'     => \$orig_master_user,
  #'orig_master_password=s' => \$orig_master_password,
  'new_master_host=s'      => \$new_master_host,
  'new_master_ip=s'        => \$new_master_ip,
  'new_master_port=i'      => \$new_master_port,
  'new_master_user=s'      => \$new_master_user,
  #'new_master_password=s'  => \$new_master_password,
); exit &main(); sub current_time_us {
  my ( $sec, $microsec ) = gettimeofday();
  my $curdate = localtime($sec);
  return $curdate . " " . sprintf( "%06d", $microsec );
} sub sleep_until {
  my $elapsed = tv_interval($_tstart);
  if ( $_running_interval > $elapsed ) {
    sleep( $_running_interval - $elapsed );
  }
} sub get_threads_util {
  my $dbh                    = shift;
  my $my_connection_id       = shift;
  my $running_time_threshold = shift;
  my $type                   = shift;
  $running_time_threshold = unless ($running_time_threshold);
  $type                   = unless ($type);
  my @threads;   my $sth = $dbh->prepare("SHOW PROCESSLIST");
  $sth->execute();   while ( my $ref = $sth->fetchrow_hashref() ) {
    my $id         = $ref->{Id};
    my $user       = $ref->{User};
    my $host       = $ref->{Host};
    my $command    = $ref->{Command};
    my $state      = $ref->{State};
    my $query_time = $ref->{Time};
    my $info       = $ref->{Info};
    $info =~ s/^\s*(.*?)\s*$/$/ if defined($info);
    next if ( $my_connection_id == $id );
    next if ( defined($query_time) && $query_time < $running_time_threshold );
    next if ( defined($command)    && $command eq "Binlog Dump" );
    next if ( defined($user)       && $user eq "system user" );
    next
      if ( defined($command)
      && $command eq "Sleep"
      && defined($query_time)
      && $query_time >= );     if ( $type >= ) {
      next if ( defined($command) && $command eq "Sleep" );
      next if ( defined($command) && $command eq "Connect" );
    }     if ( $type >= ) {
      next if ( defined($info) && $info =~ m/^select/i );
      next if ( defined($info) && $info =~ m/^show/i );
    }     push @threads, $ref;
  }
  return @threads;
} sub main {
  if ( $command eq "stop" ) {
    ## Gracefully killing connections on the current master
    # . Set read_only= on the new master
    # . DROP USER so that no app user can establish new connections
    # . Set read_only= on the current master
    # . Kill current queries
    # * Any database access failure will result in script die.
    my $exit_code = ;
    eval {
      ## Setting read_only= on the new master (to avoid accident)
      my $new_master_handler = new MHA::DBHelper();       # args: hostname, port, user, password, raise_error(die_on_error)_or_not
      $new_master_handler->connect( $new_master_ip, $new_master_port,
        $new_master_user, $new_master_password, );
      print current_time_us() . " Set read_only on the new master.. ";
      $new_master_handler->enable_read_only();
      if ( $new_master_handler->is_read_only() ) {
        print "ok.\n";
      }
      else {
        die "Failed!\n";
      }
      $new_master_handler->disconnect();       # Connecting to the orig master, die if any database error happens
      my $orig_master_handler = new MHA::DBHelper();
      $orig_master_handler->connect( $orig_master_ip, $orig_master_port,
        $orig_master_user, $orig_master_password, );       ## Drop application user so that nobody can connect. Disabling per-session binlog beforehand
      #$orig_master_handler->disable_log_bin_local();
      #print current_time_us() . " Drpping app user on the orig master..\n";
      #FIXME_xxx_drop_app_user($orig_master_handler);       ## Waiting for N * milliseconds so that current connections can exit
      my $time_until_read_only = ;
      $_tstart = [gettimeofday];
      my @threads = get_threads_util( $orig_master_handler->{dbh},
        $orig_master_handler->{connection_id} );
      while ( $time_until_read_only > && $#threads >= ) {
        if ( $time_until_read_only % == ) {
          printf
"%s Waiting all running %d threads are disconnected.. (max %d milliseconds)\n",
            current_time_us(), $#threads + , $time_until_read_only * ;
          if ( $#threads < ) {
            print Data::Dumper->new( [$_] )->Indent()->Terse()->Dump . "\n"
              foreach (@threads);
          }
        }
        sleep_until();
        $_tstart = [gettimeofday];
        $time_until_read_only--;
        @threads = get_threads_util( $orig_master_handler->{dbh},
          $orig_master_handler->{connection_id} );
      }       ## Setting read_only= on the current master so that nobody(except SUPER) can write
      print current_time_us() . " Set read_only=1 on the orig master.. ";
      $orig_master_handler->enable_read_only();
      if ( $orig_master_handler->is_read_only() ) {
        print "ok.\n";
      }
      else {
        die "Failed!\n";
      }       ## Waiting for M * milliseconds so that current update queries can complete
      my $time_until_kill_threads = ;
      @threads = get_threads_util( $orig_master_handler->{dbh},
        $orig_master_handler->{connection_id} );
      while ( $time_until_kill_threads > && $#threads >= ) {
        if ( $time_until_kill_threads % == ) {
          printf
"%s Waiting all running %d queries are disconnected.. (max %d milliseconds)\n",
            current_time_us(), $#threads + , $time_until_kill_threads * ;
          if ( $#threads < ) {
            print Data::Dumper->new( [$_] )->Indent()->Terse()->Dump . "\n"
              foreach (@threads);
          }
        }
        sleep_until();
        $_tstart = [gettimeofday];
        $time_until_kill_threads--;
        @threads = get_threads_util( $orig_master_handler->{dbh},
          $orig_master_handler->{connection_id} );
      }                 print "Disabling the VIP on old master: $orig_master_host \n";
                &stop_vip();            ## Terminating all threads
      print current_time_us() . " Killing all application threads..\n";
      $orig_master_handler->kill_threads(@threads) if ( $#threads >= );
      print current_time_us() . " done.\n";
      #$orig_master_handler->enable_log_bin_local();
      $orig_master_handler->disconnect();       ## After finishing the script, MHA executes FLUSH TABLES WITH READ LOCK
      $exit_code = ;
    };
    if ($@) {
      warn "Got Error: $@\n";
      exit $exit_code;
    }
    exit $exit_code;
  }
  elsif ( $command eq "start" ) {
    ## Activating master ip on the new master
    # . Create app user with write privileges
    # . Moving backup script if needed
    # . Register new master's ip to the catalog database # We don't return error even though activating updatable accounts/ip failed so that we don't interrupt slaves' recovery.
# If exit code is or , MHA does not abort
    my $exit_code = ;
    eval {
      my $new_master_handler = new MHA::DBHelper();       # args: hostname, port, user, password, raise_error_or_not
      $new_master_handler->connect( $new_master_ip, $new_master_port,
        $new_master_user, $new_master_password, );       ## Set read_only= on the new master
      #$new_master_handler->disable_log_bin_local();
      print current_time_us() . " Set read_only=0 on the new master.\n";
      $new_master_handler->disable_read_only();       ## Creating an app user on the new master
      #print current_time_us() . " Creating app user on the new master..\n";
      #FIXME_xxx_create_app_user($new_master_handler);
      #$new_master_handler->enable_log_bin_local();
      $new_master_handler->disconnect();       ## Update master ip on the catalog database, etc
                print "Enabling the VIP - $vip on the new master - $new_master_host \n";
                &start_vip();
                $exit_code = ;
    };
    if ($@) {
      warn "Got Error: $@\n";
      exit $exit_code;
    }
    exit $exit_code;
  }
  elsif ( $command eq "status" ) {     # do nothing
    exit ;
  }
  else {
    &usage();
    exit ;
  }
} # A simple system call that enable the VIP on the new master 
sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
} sub usage {
  print
"Usage: master_ip_online_change --command=start|stop|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
  die;
}
(2)简单版
#!/bin/bash
source /root/.bash_profile vip=`echo '192.168.1.210/24'` #设置VIP
key=`echo ''` command=`echo "$1" | awk -F = '{print $2}'`
orig_master_host=`echo "$2" | awk -F = '{print $2}'`
new_master_host=`echo "$7" | awk -F = '{print $2}'`
orig_master_ssh_user=`echo "${12}" | awk -F = '{print $2}'`
new_master_ssh_user=`echo "${13}" | awk -F = '{print $2}'` #要求服务的网卡识别名一样
stop_vip=`echo "ssh root@$orig_master_host /usr/sbin/ifconfig bond0:$key down"`
start_vip=`echo "ssh root@$new_master_host /usr/sbin/ifconfig bond0:$key $vip"` if [ $command = 'stop' ]
then
echo -e "\n\n\n****************************\n"
echo -e "Disabled thi VIP - $vip on old master: $orig_master_host \n"
$stop_vip
if [ $? -eq ]
then
echo "Disabled the VIP successfully"
else
echo "Disabled the VIP failed"
fi
echo -e "***************************\n\n\n"
fi if [ $command = 'start' -o $command = 'status' ]
then
echo -e "\n\n\n*************************\n"
echo -e "Enabling the VIP - $vip on new master: $new_master_host \n"
$start_vip
if [ $? -eq ]
then
echo "Enabled the VIP successfully"
else
echo "Enabled the VIP failed"
fi
echo -e "***************************\n\n\n"
fi
【4.5.3】授权
chmod +x /usr/local/bin/master_ip_failover
chmod +x /usr/local/bin/master_ip_online_change

【4.5.4】keepalive(待写)

【4.6】配置检查(在201上,即manager节点上)

【4.6.1】检查SSH配置
#检查mha manager 到所有的 MHA Node 的SSH链接状态
masterha_check_ssh --conf=/etc/masterha/app1.cnf
【4.6.2】检查整个复制环境状态
#通过 masterha_check_repl 脚本查看整个集群的状态
masterha_check_repl --conf=/etc/masterha/app1.cnf
【4.6.3】检查 MHA Manager 的状态
masterha_check_status --conf=/etc/masterha/app1.cnf
【4.6.4】手动启动MHA监控
mkdir -p /var/log/masterha/app1
chmod -R 777 /var/log/masterha/app1 #启动MHA监控
nohup masterha_manager --conf=/etc/masterha/app1.cnf --ignore_laster_failover &
#--remove_dead_master_conf & (1)--remove_dead_master_conf #当发生故障切换后,老的主库配置会从配置文件中移除掉(比如发生故障切换了,202主库切换到了203,那么在app1.cnf配置文件中,[server1]描述的ip为192.168.1.202内容会被清除)
(2)--manger_log #管理节点的日志位置
(3)--ignore_last_failover
  #在默认情况下,如果mha检查到主库连续发现宕机,且两次宕机间隔不超过8小时,则不会发生继续切换。(会生成一个文件,判断文件存在就不允许继续故障转移切换)
  #加了这个参数的话,就是来避免上述情况的,以便可以无限制的故障切换。 # 停止MHA监控
masterha_stop --conf=/etc/masterha/app1.cnf
 

【4.7】自动故障转移切换测试

切换之后,注意修改my.cnf,比如read_only等等

【4.7.1】直接关闭主库202机器的mysql

systemctl stop mysql #service mysql stop

【4.7.2】查看日志了解故障转移切换原理

#查看日志 /var/log/masterha/app1/manager.log
#这里只筛选了一下步骤 ** Phase : Configuration Check Phase completed.
* Phase : Dead Master Shutdown Phase..
* Phase : Dead Master Shutdown Phase completed.
* Phase : Master Recovery Phase..
* Phase 3.1: Getting Latest Slaves Phase..
* Phase 3.3: Determining New Master Phase..
* Phase 3.3: New Master Recovery Phase..
* Phase : Master Recovery Phase completed.
* Phase : Slaves Recovery Phase..
* Phase 4.1: Starting Slaves in parallel..
* Phase : New master cleanup phase.. 由此可以看出,MHA故障转移详细步骤;
(1)配置文件检查阶段:通过检查MHA的配置文件,获取相关的MHA集群机器信息,故障转移脚本信息等等
(2)宕机主库关闭阶段:将VIP删除
(3)复制宕机master库的binlog与最新slave库的差异relay log,保存到monitor节点下。
(4)推选识别含有最新数据的slave库,提升为master库。
(5)新master库应用(3)中保存下来的二进制日志
(6)将其他的slave库连接到新的master库,进行复制

【4.7.3】核验数据

(1)打开 schedure_event,查看test.test4

(2)查看show slave status

(3)建立一个库、表、数据,查看是否同步

(4)如何查看vip是否切换成功?

  mysql -uroot -p123456 -h192.168.1.210 #通过VIP登录

  show variables like 'hostname';

    

  最终发现,VIP还是切换过来了。

【4.7.4】MHA 官方的 BUG

对于 201 机器 monitor ,发生故障转移后,manager进程直接死掉了,即MHA监控脚本已经自动停止。

这个时候如果再次发生故障,就无法自动故障转移切换了。详情如下图:

  

解决办法:

  官方的回复是,不想让这个进程死掉,就放到后台运行,但我们是后台启动的,并没有效果;

  我们可以写一个脚本,监控进程是否存在,如果进程不存在则启动它。感觉就如同mysqld_safe一样,守护着mysql,mysql挂了就自动拉起来。

vim /usr/local/bin/manager_status_check

#!/bin/bash
while true
do
mha_check=`ps -ef|grep masterha_manager|grep -v grep|wc -l`
if [ ${mha_check} -eq ];then
nohup masterha_manager --conf=/etc/masterha/app1.cnf --ignore_laster_failover &
#--remove_dead_master_conf &
else
echo "MHA manager start"
fi
sleep
done #授权及加入开机自启
#chmod u+x /usr/local/bin/manager_status_check
#echo "nohup /usr/local/bin/manager_status_check">>/etc/rc.d/rc.local

【4.7.5】原本宕机的主节点重新加入回

(1)如果掉线时间长,宕机时间段内数据量大,建议操作如下(或者直接进行备份还原操作

增强半同步从库宕机如何重新连入主库?

. 此2个参数rpl_semi_sync_master_enabled  和rpl_semi_sync_slave_enabled  不要直接写入到my.cnf配置文件开启。
.在slave库上先 stop slave io_thread ;set global rpl_semi_sync_slave_enabled= 关闭此参数。
然后start slave io_thread 或者start slave 开启异步复制,让slave库追赶上master库。
.然后在slave库 set global rpl_semi_sync_slave_enabled= ;stop slave io_thread;start slave io_thread;

(2)否则直接运行下列脚本重新制定主从即可

现在主库是203啦。

change master to
master_host='192.168.1.203',
master_user='rpl',
master_password='',
master_port=,
master_auto_position=;

注意,如果monitor 启动的时候加了

--remove_dead_master_conf

那么配置文件会把之前宕机的机器信息(也就是202)清除掉,所以我们需要修改一下配置文件,把202加回来

左边修改前,右边修改后。

【4.8】手工切换主库(宕机切换与在线切换,masterha_master_switch 与 master_ip_online_change)

切换之后,注意修改my.cnf

做这块操作之前,必须要先关掉 masterha_manger.

ps -ef|grep manager*

【4.8.1】 masterha_master_switch
#在线切换(当前主库是203,想切换到202为主库)masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=192.168.1.202 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

#其实会调用到 master_ip_online_change 脚本
#master_ip_online_change 具体文件配置参考【4.5】VIP配置 【4.8.1】核验
参考:【4.7.3】核验数据 记得把监控启动起来

【4.8.2】MHA在线切换的考虑与基本原理

在许多情况下, 需要将现有的主服务器迁移到另外一台服务器上。 比如主服务器硬件故障,RAID 控制卡需要重建,将主服务器移到性能更好的服务器上等等。维护主服务器引起性能下降, 导致停机时间至少无法写入数据。 另外, 阻塞或杀掉当前运行的会话会导致主主之间数据不一致的问题发生。 MHA 提供快速切换和优雅的阻塞写入,这个切换过程只需要 0.5-2s 的时间,这段时间内数据是无法写入的。在很多情况下,0.5-2s 的阻塞写入是可以接受的。因此切换主服务器不需要计划分配维护时间窗口。

MHA在线切换的大概过程:

  1. 检测复制设置和确定当前主服务器
  2. 确定新的主服务器
  3. 阻塞写入到当前主服务器
  4. 等待所有从服务器赶上复制
  5. 授予写入到新的主服务器
  6. 重新设置从服务器

注意,在线切换的时候应用架构需要考虑以下两个问题:

  1. 自动识别master和slave的问题(master的机器可能会切换),如果采用了vip的方式,基本可以解决这个问题。
  2. 负载均衡的问题(可以定义大概的读写比例,每台机器可承担的负载比例,当有机器离开集群时,需要考虑这个问题)

为了保证数据完全一致性,在最快的时间内完成切换,MHA的在线切换必须满足以下条件才会切换成功,否则会切换失败。

  1. 所有slave的IO线程都在运行
  2. 所有slave的SQL线程都在运行
  3. 所有的show slave status的输出中Seconds_Behind_Master参数小于或者等于running_updates_limit秒,如果在切换过程中不指定running_updates_limit,那么默认情况下running_updates_limit为1秒。
  4. 在master端,通过show processlist输出,没有一个更新花费的时间大于running_updates_limit秒。

【5】增删节点

【5.1】增加节点

(1)新节点机器 安装agent节点环境,初始化mysql数据库

(2)新节点机器 异步复制跟上

(3)新节点机器 半同步复制跟上

(4)与manager 秘钥互信

(5)修改manager配置文件

(6)重启manager服务

(7)复制检查

【5.2】删除节点

(1)关闭删除节点复制
(2)停掉删除节点服务/清除slave 连接 master信息(reset slave)
(3)修改配置文件
(4)重启manager

(5)复制检查

附录:故障解决

(1)perl-Log-Dispatch no available packages

     perl-Parallel-ForkManager no available packages

  解决办法:

    yum -y install epel-release ,安装了之后, 再重新

      yum install -y perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes

(2)手动VIP如何在重启后正确的重新设置?

cat << eof >>/etc/rc.d/rc.local
nohup ping -c 192.168.1.210
if [ $? != ];then
/sbin/ifconfig ens34: 192.168.1.210/
fi
eof #判断主库 select * from information_schema.processlist where state like 'Master%';
#判断从库 select * from information_schema.processlist where state like 'Slave%';

(3)官方BUG,故障转移之后,monitor服务器下的manager程序死掉了

详情见本文【4.7.4】

(4) masterha_check_repl(1130,1045) :Access denied for user 'root'@'mha1'

故障原因:

此账号没有权限登录到对应的机器上

处理方法:

为对应的用户授权即可

(5)masterha_check_repl(Can't exec "mysqlbinlog"):从当前环境变量中找不到binlog

故障原因:

从当前的环境变量中找不到 mysqlbinlog 命令

解决方法:

将 mysqlbinlog 的路径添加到 环境变量中

(6) masterha_check_repl(rep no exist or does not have REPLICATIONSLAVE privilege)

故障原因

缺少 REPLICATION SLAVE 权限

解决方法:

为同步账号添加 REPLICATION SLAVE 权限即可, 注意,是所有节点都添加, 保证主从切换后都可以正常使用。

(7)event_scheduler导致常连接问题

  

故障原因:

这个是由于部属的 mha 版本没有跟上 数据库的版本. 在检测长连接时, 由于系统新增加了event_scheduler 功能,且属于打开的状态,那么此用户会一直存在, mha 检测时将其列为长连接,所以出现上面错误

解决方法:

临时解决方法: 禁用 event_scheduler, set global event_scheduler = 0;

长久之计,按下面方式修改源码:

(8) mha 管理 vip, 节点之间的网卡名不一样,切换会失败

解决方法:

  * 改网卡名

  * 改切换脚本

2.6、 mha 管理 vip, ssh 默认端口非22

  切换会失败

解决方法:

  * 改默认端口

  * 改切换脚本

注: 在线切换 和 故障切换脚本QQ群中提供 群号:748415432

(9) 使用 GTID 时切换的坑(gtid_mode=1; auto_position=0)

  gtid_mode=1; auto_position=0 模式, 配置 binlog server 选项

虽然打开了 GTID, 但同步依旧使用的是log_file + position 模式同步数据, 切换时依旧自动转成 auto_position=1 模式, 转换后很有可能出来 1236 同步错误. 下面两段代码解释了为什么会依旧使用 auto_position=1 模式 .

  
  

2.8、 gtid_mode=1; auto_position=0模式,

  配置 binlog server 选项, 同时配置了 use_gtid_auto_pos=0

  看似解决了上面的问题, 但引入了一个最大的问题, 不补尝原主实例的差异数据了, 这就是说, 原主库任何情况下出现异常都属于机器挂的情况‘

2.9、 gtid_mode=1; auto_position=1模式,

  没有配置 binlog server 选项, 依旧补不了日志。

2.7 ~ 2.9 解决方案:

  开启 gitd 后, 最好的方案就是 基于 gtid 同步, 且使用 auto_position=1, 同时配置 binlog server 选项。

(10)如果新实例,则需要执行一个事务,才可以被识别为开启 了 GTID 模式

[server default]

# 这边是 连接 MySQL 的账号与密码, 如果端口发生改变, 也要写上相应的端口, 默认为
port=
user=rootpassword=# 这边是连接机器的 ssh 用户,密码使用互信方式实现
ssh_user=root# 这边复制账号
repl_user=repl
repl_password=123456
master_binlog_dir= /data/mysql/mysqldata3306/binlog
master_ip_failover_script= /etc/mha/scripts/
master_ip_failover_new
master_ip_online_change_script= /etc/mha/scripts/master_online_change_new
manager_workdir=/etc/mha/app1manager_log=/etc/mha/log/mha/manager.log

[server1]
hostname=192.168.1.20
candidate_master=
master_binlog_dir= /data/mysql/mysqldata3306/binlog

[server2]
hostname=192.168.1.2
1candidate_master=
master_binlog_dir= /data/mysql/mysqldata3306/binlog

[server3]
hostname=192.168.1.22
candidate_master=
master_binlog_dir= /data/mysql/mysqldata3306/binlog

[server4]
hostname=192.168.1.23
candidate_master=
master_binlog_dir= /data/mysql/mysqldata3306/binlog

[binlog1]
hostname=192.168.1.20
[binlog2]
hostname=192.168.1.21
[binlog3]
hostname=192.168.1.22
[binlog4]
hostname=192.168.1.23

结尾

想要完美的避开上面的坑, 建议:

* 使用高版本的 MHA, 可以解决上面切换的坑.

* 如果打开了 GTID 模式,则使用 auto_position=1 同步模式,同时 MHA 的配置文件中 配置[binlog1] 选项, 地址写上原主库地址就好, 不需要真实配置一个 binlog server 服务器

本文分享自微信公众号 - 3306pai(pai3306)

参考文献

参考:mysql5.7.24 GTID+半同步 1主3从

参考:一步一个坑搭建MHA http://www.ttlsa.com/mysql/step-one-by-one-deploy-mysql-mha-cluster/

参考:MHA官网 https://code.google.com/p/mysql-master-ha/

参考:比较详细的MHA部署搭建:https://blog.csdn.net/qq_35209838/article/details/86497864

软件下载:https://cbs.centos.org/koji/buildinfo?buildID=1261

安装参考:https://www.cnblogs.com/winstom/p/11022014.html

概念:高可用架构方案  中的【3】MHA

mysql故障应用参考:https://cloud.tencent.com/developer/article/1339797

(5.15)mysql高可用系列——MHA实践的更多相关文章

  1. MySQL高可用方案MHA自动Failover与手动Failover的实践及原理

    集群信息 角色                             IP地址                 ServerID      类型 Master                     ...

  2. mysql高可用方案MHA介绍

    mysql高可用方案MHA介绍 概述 MHA是一位日本MySQL大牛用Perl写的一套MySQL故障切换方案,来保证数据库系统的高可用.在宕机的时间内(通常10-30秒内),完成故障切换,部署MHA, ...

  3. MySQL高可用方案--MHA部署及故障转移

    架构设计及必要配置 主机环境 IP                 主机名             担任角色 192.168.192.128  node_master    MySQL-Master| ...

  4. (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)

    一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...

  5. 【DB宝42】MySQL高可用架构MHA+ProxySQL实现读写分离和负载均衡

    目录 一.MHA+ProxySQL架构 二.快速搭建MHA环境 2.1 下载MHA镜像 2.2 编辑yml文件,创建MHA相关容器 2.3 安装docker-compose软件(若已安装,可忽略) 2 ...

  6. MySQL高可用之MHA (转)

    MySQL高可用之MHA MHA简介 MHA是由日本人yoshinorim(原就职于DeNA现就职于FaceBook)开发的比较成熟的MySQL高可用方案.MHA能够在30秒内实现故障切换,并能在故障 ...

  7. MySQL高可用方案MHA在线切换的步骤及原理

    在日常工作中,会碰到如下的场景,如mysql数据库升级,主服务器硬件升级等,这个时候就需要将写操作切换到另外一台服务器上,那么如何进行在线切换呢?同时,要求切换过程短,对业务的影响比较小. MHA就提 ...

  8. MySQL高可用系列之MHA(二)

    一.參数说明 MHA提供了一系列配置參数.深入理解每一个參数的详细含义,对优化配置.合理使用MHA非常重要.非常多高可用性也都是通过合理配置一些參数而实现的. MHA包含例如以下配置參数,分别说明例如 ...

  9. MySQL高可用方案MHA的部署和原理

    MHA(Master High Availability)是一套相对成熟的MySQL高可用方案,能做到在0~30s内自动完成数据库的故障切换操作,在master服务器不宕机的情况下,基本能保证数据的一 ...

随机推荐

  1. How to Set Up Chinese Characters on Windows 7

    How to Change the Display Language of non-Unicode Programs in Windows http://www.7tutorials.com/chan ...

  2. SQL Server Dead Lock Log

    1 . 模拟Dead Lock Session1: begintran insertintoT1(name)values('test1') UpdateT2setname='test1' commit ...

  3. Codevs 1137 计算系数 2011年NOIP全国联赛提高组

    1137 计算系数 2011年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给定一个多项式(ax + by ...

  4. 日期与时间(C/C++)

    C++继承了C语言用于日期和时间操作的结构和函数,使用之前程序要引用<ctime>头文件 有四个与时间相关的类型:clock_t.time_t.size_t.和tm.类型clock_t.s ...

  5. PySpider的安装

    使用 Pip 安装,命令如下 pip install pyspider 命令执行完毕即可安装成功. 常见错误: Windows 下可能会出现这样的错误提示:Command "python s ...

  6. 在iOS开发中使用icon font的方法

    http://iconfont.cn/help/iconuse.html 在开发阿里数据iOS版客户端的时候,由于项目进度很紧,项目里的所有图标都是用最平常的背景图片方案来实现.而为了要兼容普通屏与R ...

  7. 预处理、const、static、sizeof-为什么inline能很好地取代表达式形式的预定义

    1:有如下几种原因: (1)inline定义的类的内联函数,函数的代码被放在符号表中,在使用时直接进行替换(像宏一样展开),没有了调用的开销,效率也很高. (2)类的内联函数也是一个真正的函数.编译器 ...

  8. Spring AOP:Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException

    1 报错 Exception encountered during context initialization - cancelling refresh attempt: org.springfra ...

  9. DS博客作业04--树大作业

    1.树的存储结构 本组采用的树的存储结构为链式结构,选择如图所示的结构体 Name为结点的名称 LevelNum为孩子节点的个数 *Children[20]用来指向不同的孩子结点(类似于二叉树的结构体 ...

  10. [go]包管理

    vendor方式 //包管理发展 go get(无版本概念) -> vendor(godep)(无版本概念) -> go modules go get github.com/tools/g ...