首页 > 数据库 > MySQL > 正文

MySQL高可用之MHA布局

2024-07-24 12:34:52
字体:
来源:转载
供稿:网友
  MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。 MHA里有两个角色一个是MHA Node(数据节点)另一个是MHA Manager(管理节点)。 MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。
 
  大概流程如下:
  1、从宕机的master保存二进制日志事件;
  2、识别含有最新更新的slave;
  3、应用差异的中继日志(relay log)到其他slave;
  4、应用从master保存的二进制日志事件;
  5、提升一个slave为新master;
  6、使其他的slave连接到新的master进行复制。
 
  目前MHA主要支持一主多从的架构,要搭建MHA,一般MySQL集群中最少有三台数据库节点,一主二从,即:一台充当master,一台充当备用master,另外一台充当slave。
 
  MHA主要特性如下:
  1、MHA切换不依赖实例使用存储引擎和BINLOG格式;
  2、MHA不会增加MySQL服务器性能开销,除MHA管理节点外无需增加额外服务器;
  3、在MySQL服务器上部署MHA数据节点不会影响当前实例运行;
  4、MHA实现自动故障切换,也可以手动触发在线切换;
  5、MHA可以实现秒级的故障切换;
  6、MHA可以将任意slave提升master,也可以在切换时指定master候选节点;
  7、MHA提供扩展接口,允许在MHA切换过程中的特定时间点执行用户自定义脚本。
 
  MHA支持与限制:
  1、只支持BINLOG V4版本,要求MySQL 5.0或更高版本。
  2、候选master节点必须开启log-bin参数,如果所有从节点都为开启,则不进行故障转移。
  3、在MHA 0.52版本前不支持多master模式
  4、MHA默认不支持多级主从复制,通过修改配置文件和设置multi_tier_slave参数
 
  一、环境准备
  OS IP地址 主机名&角色 类型
  Centos 7.5 192.168.20.2 master 主master(写操作)
  Centos 7.5 192.168.20.3 slave1 从(备主)mysql(读操作)
  Centos 7.5 192.168.20.4 slave2 从mysql(读操作)
  Centos 7.5 192.168.20.5 manager 管理节点
  在上述环境中,master对外提供写服务,slave提供读操作,一旦master宕机,将会把其中一台slave(我这里将指定的是备主)提升为新的master,slave同时也指向新的master,manager作为管理服务器。
 
  1、 配置hosts文件,主机之间可互相解析
  以下操作在其中一个节点执行即可。
 
  #编写host文件
  [root@master ~]# cat >> /etc/hosts << EOF
  > 192.168.20.2    master
  > 192.168.20.3    slave1
  > 192.168.20.4    slave2
  > 192.168.20.5    manager
  > EOF
  > #将编写好的hosts文件分发到其他节点
  [root@master ~]# for i in master slave1 slave2 manager;do scp /etc/hosts $i:/etc/;done
  2、配置ssh免密登录
  注:集群中的所有主机都需要保证互相可以免密登录。
 
  #如果每台主机上执行以下指令不用输入密码就可以获取所有主机的主机名,说明免密登录配置无误
  [root@master ~]# for i in master slave1 slave2 manager;do ssh $i hostname;done
  master
  slave1
  slave2
  manager
  3、配置epel并安装MHA所需依赖
  注:以下命令需要在所有节点执行。
 
  #配置阿里的epel源(为加快安装速度),若非国内环境,执行yum -y install epel-release进行配置即可
  [root@master ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
  [root@master ~]# yum makecache           #建立元数据缓存
  # 安装所需依赖
  [root@master ~]# yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-ParallelForkManager perl-Config-IniFiles ncftp perl-Params-Validate perl-CPAN perl-TestMock-LWP.noarch perl-LWP-Authen-Negotiate.noarch perl-devel perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
  二、基于半同步进行主从复制
  注:接下来所有操作,如果没有特别说明,是需要在所有数据库服务器上进行执行的。
 
  1、查找半同步所需插件
  mysql> show variables like '%plugin_dir%';    #查找插件所在目录(每台DB服务器可能不一样)
 
  [root@master ~]# ls /usr/local/mysql/lib/plugin/ | egrep 'master|slave'
  #确定插件的目录下有以下两个文件(默认安装数据库后就有这些的)
  semisync_master.so
  semisync_slave.so
  2、安装插件
  # semisync_master.so和semisync_slave.so为上面查询到的插件名字
  mysql> install plugin rpl_semi_sync_master SONAME 'semisync_master.so';
  mysql> install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so';
 
  注:
 
  rpl_semi_sync_master_enabled=1:1表是启用,0表示关闭
  rpl_semi_sync_master_timeout=1000:毫秒单位 ,该参数主服务器等待确认消息10秒后,不再等待,变为异步方式。
  slave1主机完整配置文件如下:
 
  [root@slave1 ~]# cat /etc/my.cnf
  [mysqld]
  basedir=/usr/local/mysql
  datadir=/usr/local/mysql/data
  port=3306
  server_id=2
  socket=/usr/local/mysql/mysql.sock
  log-error=/usr/local/mysql/data/mysqld.err
  log-bin=mysql-bin
  binlog_format=mixed
  rpl_semi_sync_master_enabled=1
  rpl_semi_sync_master_timeout=1000
  rpl_semi_sync_slave_enabled=1
  relay_log_purge=0
  relay-log = relay-bin
  relay-log-index = slave-relay-bin.index
  slave2主机的完整配置文件如下:
 
  [root@slave2 ~]# cat /etc/my.cnf
  [mysqld]
  basedir=/usr/local/mysql
  datadir=/usr/local/mysql/data
  port=3306
  server_id=3
  socket=/usr/local/mysql/mysql.sock
  log-error=/usr/local/mysql/data/mysqld.err
  log-bin = mysql-bin
  relay-log = relay-bin
  relay-log-index = slave-relay-bin.index
  read_only = 1
  rpl_semi_sync_slave_enabled=1
  #由于slave2只是用来做一个slave主机,所以无需开启master的半同步
  在配置主从复制中,由于主和备主这两台主机上设置了参数relay_log_purge=0(表示不自动清除中继日志),所以slave节点需要定期删除中继日志,建议每个slave节点删除中继日志的时间错开。
 
  crontab -e
  0 5 * * * /usr/local/bin/purge_relay_logs - -user=root --password=pwd123 --port=3306 --disable_relay_log_purge >> /var/log/purge_relay.log 2>&1
  更改配置文件后,需要执行以下命令进行重启MySQL。
 
  [root@master ~]# systemctl restart mysqld
  查看半同步状态,确认已开启:
 
  mysql> show variables like '%rpl_semi_sync%';       #查看半同步是否开启
  +-------------------------------------------+------------+
  | Variable_name                             | Value      |
  +-------------------------------------------+------------+
  | rpl_semi_sync_master_enabled              | ON         |    #这个值要为ON
  | rpl_semi_sync_master_timeout              | 1000       |
  | rpl_semi_sync_master_trace_level          | 32         |
  | rpl_semi_sync_master_wait_for_slave_count | 1          |
  | rpl_semi_sync_master_wait_no_slave        | ON         |
  | rpl_semi_sync_master_wait_point           | AFTER_SYNC |
  | rpl_semi_sync_slave_enabled               | ON         |    #这个值也要为ON。
  | rpl_semi_sync_slave_trace_level           | 32         |
  +-------------------------------------------+------------+
  8 rows in set (0.00 sec)
 
  mysql> show status like '%rpl_semi_sync%';
  +--------------------------------------------+-------+
  | Variable_name                              | Value |
  +--------------------------------------------+-------+
  | Rpl_semi_sync_master_clients               | 0     |  
  | Rpl_semi_sync_master_net_avg_wait_time     | 0     |
  | Rpl_semi_sync_master_net_wait_time         | 0     |
  | Rpl_semi_sync_master_net_waits             | 0     |
  | Rpl_semi_sync_master_no_times              | 0     |
  | Rpl_semi_sync_master_no_tx                 | 0     |
  | Rpl_semi_sync_master_status                | ON    |
  | Rpl_semi_sync_master_timefunc_failures     | 0     |
  | Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
  | Rpl_semi_sync_master_tx_wait_time          | 0     |
  | Rpl_semi_sync_master_tx_waits              | 0     |
  | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
  | Rpl_semi_sync_master_wait_sessions         | 0     |
  | Rpl_semi_sync_master_yes_tx                | 0     |
  | Rpl_semi_sync_slave_status                 | OFF   |
  +--------------------------------------------+-------+
  15 rows in set (0.00 sec)
  #关于上个命令查看到的信息,有几个状态值得关注,将在下面写下来。
  rpl_semi_sync_master_status :显示主服务是异步复制模式还是半同步复制模式,ON为半同步;
  rpl_semi_sync_master_clients :显示有多少个从服务器配置为半同步复制模式;
  rpl_semi_sync_master_yes_tx :显示从服务器确认成功提交的数量
  rpl_semi_sync_master_no_tx :显示从服务器确认不成功提交的数量
  rpl_semi_sync_master_tx_avg_wait_time :事务因开启 semi_sync ,平均需要额外等待的时间
  rpl_semi_sync_master_net_avg_wait_time :事务进入等待队列后,到网络平均等待时间
  5、创建相关用户
  1)master主机操作如下:
 
  # 创建用于同步的用户
  mysql> grant replication slave on *.* to mharep@'192.168.20.%' identified by '123.com';
  Query OK, 0 rows affected, 1 warning (1.00 sec)
  # 创建用户mha的manager监控的用户
  mysql> grant all on *.* to manager@'192.168.20.%' identified by '123.com';
  Query OK, 0 rows affected, 1 warning (0.00 sec)
  # 查看master二进制相关的信息
  mysql> show master statusG
  *************************** 1. row ***************************
               File: mysql-bin.000001
           Position: 744
       Binlog_Do_DB:
   Binlog_Ignore_DB:
  Executed_Gtid_Set:
  1 row in set (0.00 sec)
  2)slave1主机操作如下:
 
  # 创建用于同步的用户
  mysql> grant replication slave on *.* to mharep@'192.168.20.%' identified by '123.com';
  Query OK, 0 rows affected, 1 warning (1.00 sec)
  # 创建用户mha的manager监控的用户
  mysql> grant all on *.* to manager@'192.168.20.%' identified by '123.com';
  Query OK, 0 rows affected, 1 warning (0.00 sec)
  3)slave2主机操作如下:
 
  由于slave2无需做备主,所以不用创建用于同步数据的账户
 
  #创建manager监控账号
  mysql> grant all on *.* to manager@'192.168.20.%' identified by '123.com';
  Query OK, 0 rows affected, 1 warning (0.00 sec)
  6、配置主从复制
  以下操作需要在slave1和slave2主机上分别执行一次,以便同步master主机的数据。
 
  #指定master主机的相关信息
  mysql> change master to
      -> master_host='192.168.20.2',
      -> master_port=3306,
      -> master_user='mharep',
      -> master_password='123.com',
      -> master_log_file = 'mysql-bin.000001',     #这是在master主机上查看到的二进制日志名
      -> master_log_pos=744;     #同上,这是查看到的二进制日志的position
  Query OK, 0 rows affected, 2 warnings (0.01 sec)
 
  mysql> start slave;      #启动slave
  Query OK, 0 rows affected (0.00 sec)
 
  7、安装MHA-node
  注:需要MHA-node需要在所有节点安装(包括manager主机节点)
 
  #下载包
  [root@master src]# wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58.tar.gz
  #安装
  [root@master src]# tar zxf mha4mysql-node-0.58.tar.gz
  [root@master src]# cd mha4mysql-node-0.58/
  [root@master mha4mysql-node-0.58]# perl Makefile.PL
  [root@master mha4mysql-node-0.58]# make && make install
  注:接下来的所有操作,如果没有特别标注,则只需要在manager主机节点上执行即可。
 
  8、安装MHA-manager
  #下载包
  [root@manager src]# wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58.tar.gz
  #安装
  [root@manager src]# tar zxf mha4mysql-manager-0.58.tar.gz
  [root@manager src]# cd mha4mysql-manager-0.58/
  [root@manager mha4mysql-manager-0.58]# perl Makefile.PL
  [root@manager mha4mysql-manager-0.58]# make && make install
  9、创建相应目录及复制所需文件
  [root@manager mha4mysql-manager-0.58]# mkdir /etc/masterha
  [root@manager mha4mysql-manager-0.58]# mkdir -p /masterha/app1
  [root@manager mha4mysql-manager-0.58]# mkdir /scripts
  [root@manager mha4mysql-manager-0.58]# pwd
  /usr/src/mha4mysql-manager-0.58     #确定当前所在目录
  [root@manager mha4mysql-manager-0.58]# cp samples/conf/* /etc/masterha/
  [root@manager mha4mysql-manager-0.58]# cp samples/scripts/* /scripts/
  10、修改mha-manager配置文件
  注:manager共有两个主要的配置文件,一个是通用默认的,一个是单独的。需要将默认通用的配置文件的内容清空,如下:
 
  #清空默认的配置文件
  [root@manager masterha]# > /etc/masterha/masterha_default.cnf
  然后修改单独的配置文件:
 
  [root@manager ~]# cat /etc/masterha/app1.cnf   #修改如下:
  [server default]
  manager_workdir=/masterha/app1    #指定工作目录
  manager_log=/masterha/app1/manager.log     #指定日志文件
  user=manager           #指定manager管理数据库节点所使用的用户名
  password=123.com       #对应的是上面用户的密码
  ssh_user=root        #指定配置了ssh免密登录的系统用户
  repl_user=mharep    #指定用于同步数据的用户名
  repl_password=123.com    #对应的是上面同步用户的 密码
  ping_interval=1        #设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应时自动进行切换
 
  [server1]
  hostname=192.168.20.2
  port=3306
  master_binlog_dir=/usr/local/mysql/data     #指定master保存二进制日志的路径,以便MHA可以找到master的日志
  candidate_master=1     #设置为候选master,设置该参数后,发生主从切换以后将会将此库提升为主库
 
  [server2]
  hostname=192.168.20.3
  port=3306
  master_binlog_dir=/usr/local/mysql/data
  candidate_master=1      #设置为候选master
 
  [server3]
  hostname=192.168.20.4
  port=3306
  master_binlog_dir=/usr/local/mysql/data
  no_master=1      #设置的不为备选主库
  完整无注释的配置文件如下:
 
  [root@manager ~]# cat /etc/masterha/app1.cnf
  [server default]
  manager_workdir=/masterha/app1   
  manager_log=/masterha/app1/manager.log    
  user=manager
  password=123.com
  ssh_user=root
  repl_user=mharep
  repl_password=123.com
  ping_interval=1
 
  [server1]
  hostname=192.168.20.2
  port=3306
  master_binlog_dir=/usr/local/mysql/data
  candidate_master=1
 
  [server2]
  hostname=192.168.20.3
  port=3306
  master_binlog_dir=/usr/local/mysql/data
  candidate_master=1
 
  [server3]
  hostname=192.168.20.4
  port=3306
  master_binlog_dir=/usr/local/mysql/data
  no_master=1
  11、启动前测试
 
  验证集群复制的有效性(MySQL必须都启动),如下:
 
  [root@manager masterha]# masterha_check_repl --global_conf=/etc/masterha/masterha_default.cnf --conf=/etc/masterha/app1.cnf
 
  这是因为没有在mysql节点上找到mysqlbinlog这个命令,只需要在所有MySQL主机节点上执行以下命令创建软连接即可,如下:
 
  #注:以下命令是在所有数据库服务节点执行
  [root@master ~]# ln -s /usr/local/mysql/bin/* /usr/local/bin/
 
  解决办法:
 
  [root@master ~]# rpm -qa |grep -i dbd       #查找下面的软件包
  perl-DBD-MySQL-4.023-6.el7.x86_64
  perl-DBD-SQLite-1.39-3.el7.x86_64
  #卸载下面的软件包
  [root@master ~]# rpm -e --nodeps perl-DBD-MySQL-4.023-6.el7.x86_64
  [root@master ~]# yum -y install perl-DBD-MySQL    #再次yum安装即可解决报错
  最后检查命令执行成功,如下:
 
  [root@manager ~]# masterha_check_repl --global_conf=/etc/masterha/masterha_default.cnf --conf=/etc/masterha/app1.cnf
  返回以下信息,表示无误:
 
  12、启动manager
  [root@manager ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf &> /var/log/mha_manager.log &
  注:可以多次执行上述命令,指定不同的app.cnf配置文件,以便监控多个MySQL集群,我这里就一个MySQL集群,所以只需要执行上述一条命令即可。
 
  13、验证故障转移
  可以自行查看当前MySQL集群中目前的主是哪台服务器,我这里MySQL集群中的主是master主机,如下:
 
  现在模拟master主机故障,然后再查看集群中的master是哪台,如下:
 
  # 在master主机停止MySQL服务
  [root@master ~]# systemctl stop mysqld
  # 再次在slave2主机上查看当前的主是哪台?
  mysql> show slave statusG
  *************************** 1. row ***************************
                 Slave_IO_State: Waiting for master to send event
                    Master_Host: 192.168.20.3    # 可以看到当前的主是slave1这台备主
                    Master_User: mharep
                    Master_Port: 3306
                  Connect_Retry: 60
                Master_Log_File: mysql-bin.000001
            Read_Master_Log_Pos: 744
                 Relay_Log_File: relay-bin.000002
                  Relay_Log_Pos: 320
  三、MHA Manager端日常维护
  1)检查是否有以下文件,有则删除
  MHA Manager服务发生主从切换后,MHA manager服务会自动停止,且在manager_workdir(/masterha/app1/)目录下面生成app1.failover.complete文件,若要再次启动MHA,必须先确保没有这个文件,如果有app1.failover.complete或者app1.failover.error这个文件,则会报错如下:
 
  只需要删除这个文件在将master主机指向新的master(也就是slave1)即可成功启动manager服务,如下:
 
  # 删除
  [root@manager app1]# rm -rf /masterha/app1/app1.failover.complete
  # 在manager服务的日志中查看指定master的信息,如下:
  [root@manager app1]# cat /masterha/app1/manager.log | grep MASTER
  #如果服务已运行很久,那么肯定是看最后一条信息,日志里已经把指向新的master需要执行的指令记录了下来
  #但是需要自己手动写密码
  Fri Feb 21 17:57:37 2020 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='192.168.20.3', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=744, MASTER_USER='mharep', MASTER_PASSWORD='xxx';
  Fri Feb 21 17:57:38 2020 - [info]  Executed CHANGE MASTER.
  # 在master主机上执行下面命令,以便指定slave2为主:
  mysql> CHANGE MASTER TO MASTER_HOST='192.168.20.3', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=744, MASTER_USER='mharep', MASTER_PASSWORD='123.com';
  #启动slave功能
  mysql> start slave;
 
  #再次启动manager服务
  [root@manager app1]#  nohup masterha_manager --conf=/etc/masterha/app1.cnf &> /var/log/mha_manager.log &
  [1] 16130
  # 通过jobs -l查看到状态为“运行中”,即说明manager重新运行成功
  [root@manager app1]# jobs -l
  [1]+ 16130 运行中               nohup masterha_manager --conf=/etc/masterha/app1.cnf &>/var/log/mha_manager.log &
  2)检查MHA复制
  [root@manager ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf
  3)停止MHA
  [root@manager ~]# masterha_stop --conf=/etc/masterha/app1.cnf
  4)启动MHA
  [root@manager ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf &>/tmp/mha_manager.log &
  当有slave节点宕机时,manager服务是无法启动的,建议在配置文件中暂时注释掉宕机节点的信息,待修复后再取消注释。
 
  5)检查状态
  [root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf   #manager没有启动时的状态如下
  app1 is stopped(2:NOT_RUNNING).
  #启动manager服务再进行检查如下
  [root@manager ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf &>/tmp/mha_manager.log &
  [1] 19651
  [root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
  app1 (pid:19651) is running(0:PING_OK), master:192.168.20.3

(编辑:武林网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表