Mysql MHA搭建

2 篇文章 0 订阅

机器配置

192.168.146.107

mysql主

node1

虚拟IP为192.168.146.106

192.168.146.108

mysql从

node2

192.168.146.109

mysql从

node3 + manager

系统信息:

为107设置VIP :

安装Docker

安装需要的软件包:yum-utils、device-mapper-persistent-data和lvm2。

yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

设置仓库

使用国内镜像,比如阿里云源镜像

yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

安装docker engine,包括docker-ce、docker-ce-cli和containerd.io

yum install docker-ce docker-ce-cli containerd.io

启动docker

systemctl start docker

验证安装是否ok

docker run hello-world

以上操作在三台机器上都执行

Docker安装和启动Mysql8.0.26

拉取镜像

docker pull mysql:8.0.26

创建文件夹用于挂载,放置mysql配置文件和数据

cd /home; mkdir -p mysql && cd $_ && mkdir {conf,data,mysql-files,mysqld,log}
chmod 777 /home/mysql/mysqld

进入conf文件夹创建mysql的配置文件my.cnf ,内容如下
[mysqld]
server_id=306
port=3306
default_authentication_plugin=mysql_native_password
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
symbolic-links=0
explicit_defaults_for_timestamp=true
binlog-ignore-db=mysql
binlog-ignore-db=information_schema

binlog_cache_size=1M
binlog_format=mixed
binlog_expire_logs_seconds=259200
max_binlog_size=500M
slave_skip_errors=1062
log_slave_updates=1
lower_case_table_names=1
log-bin=mysql-bin
replicate-ignore-db=mysql,information_schema
sync_binlog=0
bind-address=0.0.0.0
skip-name-resolve
skip_ssl

auto_increment_offset=1
auto_increment_increment=1

character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake=true

max_connections=1000
innodb-force-recovery=0

gtid-mode=on
enforce-gtid-consistency=1
master-info-repository=TABLE
relay_log_purge=0
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=2
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
innodb_flush_log_at_trx_commit=0
relay_log_recovery=1

[client]
port=3306
socket=/var/run/mysqld/mysqld.sock
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4
上述操作在三台机器都执行, 但要注意,三个my.cnf的server_id需要不同

三台服务器启动mysql

docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=ws-123456 \
-v /home/mysql/data:/var/lib/mysql:rw \
-v /home/mysql/mysql-files:/var/lib/mysql-files:rw \
-v /home/mysql/mysqld:/var/run/mysqld:rw \
-v /home/mysql/log:/var/log/mysql:rw \
-v /home/mysql/conf:/etc/mysql:rw \
--name mysql --privileged=true \
-d mysql:8.0.26

进入容器,创建用户

docker exec -it 6f94e362fe6d sh

 执行如下sql

CREATE USER IF NOT EXISTS 'repl'@'%' IDENTIFIED BY 'ws-123456';
ALTER USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'ws-123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON *.* TO 'repl'@'%';
flush privileges;

CREATE USER IF NOT EXISTS 'mha'@'%' IDENTIFIED BY 'ws-123456';
ALTER USER 'mha'@'%' IDENTIFIED WITH mysql_native_password BY 'ws-123456';
GRANT all  ON *.* TO 'mha'@'%';
flush privileges;

CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY 'ws-123456';
grant all on *.* to 'root'@'%';
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'ws-123456';
flush privileges;

搭建Mysql一主二从

连接108和109两台从机,执行如下命令,表示107的mysql作为主,启动主从复制

change master to 
master_host='192.168.146.107',
master_port=3306, 
master_user='repl',
master_password='ws-123456',
MASTER_AUTO_POSITION=1;   

start slave;
show slave status;

 测试主从复制是否成功

连接107节点,执行如下sql

CREATE DATABASE IF NOT EXISTS `test` default character set utf8 collate utf8_general_ci;

查看108和109是否已经同步

设置三台机器免密访问

在107节点依次执行如下命令

ssh-keygen -t rsa
ssh-copy-id 192.168.146.108
ssh-copy-id 192.168.146.109

同样在108和109节点依次执行如下命令

108
ssh-keygen -t rsa
ssh-copy-id 192.168.146.107
ssh-copy-id 192.168.146.109

109
ssh-keygen -t rsa
ssh-copy-id 192.168.146.107
ssh-copy-id 192.168.146.108

如下图所示

108:

109:

测试免密登录

在107执行如下

ssh 192.168.146.108

安装MHA

安装依赖

所有服务器都需要安装依赖包

yum -y install epel-release
yum -y install perl-DBD-MySQL perl-DBI

#安装epel-release执行报错Error: Unable to find a match epel,百度之后说是少源,执行下边命令后正常
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
yum -y install ncftp

#执行如果报错Error: Unable to find a match ncftp,执行一下yum -y update,然后再次安装,如果还报错再手动编译安装ncftp
cd /home
wget https://www.ncftp.com/downloads/ncftp/ncftp-3.2.6-src.tar.gz
tar xvf ncftp-3.2.6-src.tar.gz
cd ncftp-3.2.6
./configure && make && make install

安装mha

所有服务器都需要安装

cd /home
wget https://qiniu.wsfnk.com/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm

创建mha工作目录

所有服务器执行

mkdir /home/mysql_mha

安装mha监控manager

正常来说应该安装在一个单独的节点,此处为了节约一个节点,就安装在192.168.146.109上

yum -y install epel-release
yum -y install perl-Config-Tiny perl-Time-HiRes perl-Parallel-ForkManager perl-Log-Dispatch perl-DBD-MySQL

#执行如果报错Error: Unable to find a match ,执行一下yum -y update,然后再次安装
wget https://qiniu.wsfnk.com/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm

在manager管理机器上配置管理节点

mkdir /etc/mha

vim /etc/mha/mysql_mha.cnf
#内容如下
[server default]
#mha访问数据库的账号与密码
user=mha
password=ws-123456
#指定mha的工作目录
manager_workdir=/home/mysql_mha
#指定管理日志路径
manager_log=/home/mysql_mha/manager.log
#指定mha在远程节点上的工作目录
remote_workdir=/home/mysql_mha
#可以使用ssh登入的用户
ssh_user=root
ssh_port=22
#指定主从复制的mysq用户和密码
repl_user=repl
repl_password=ws-123456
#指定检测间隔时间
ping_interval=1
#指定master节点存放binlog的日志文件的目录
master_binlog_dir=/home/mysql/data
#指定一个脚本,该脚本实现了在主从切换之后,将虚拟ip漂移到新的master上
master_ip_failover_script=/usr/bin/master_ip_failover
#指定用于二次检查节点状态的节点
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.146.107 -s 192.168.146.108 -s 192.168.146.109
#配置集群中的节点
[server1]
hostname=192.168.146.107
#指定该节点可以参与master选举
candidate_master=1

[server2]
hostname=192.168.146.108
candidate_master=1

[server3]
hostname=192.168.146.109
##指定该节点不参与master选举 该节点也是监控节点,所以关闭master候选
no_master=1

编写配置文件中的/usr/bin/master_ip_failover脚本

vim /usr/bin/master_ip_failover

#内容如下
#!/usr/bin/env perl

use strict;
use warnings FATAL => 'all';

use Getopt::Long;

my (
    $command, $orig_master_host, $orig_master_ip,$ssh_user,
    $orig_master_port, $new_master_host, $new_master_ip,$new_master_port,
    $orig_master_ssh_port,$new_master_ssh_port,$new_master_user,$new_master_password
);

# 这里定义的虚拟IP可以根据实际情况进行修改
my $vip = '192.168.146.106/24';
my $key = '1';

# 这里的网卡名称 “ens160” 需要根据你机器的网卡名称进行修改
my $ssh_start_vip = "/sbin/ifconfig ens160:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens160:$key down";
my $ssh_Bcast_arp= "/sbin/arping -I ens160 -c 3 -A 192.168.146.106";

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_ssh_port=i' => \$orig_master_ssh_port,
    'new_master_host=s'  => \$new_master_host,
    'new_master_ip=s'    => \$new_master_ip,
    'new_master_port=i'  => \$new_master_port,
    'new_master_ssh_port' => \$new_master_ssh_port,
    'new_master_user' => \$new_master_user,
    'new_master_password' => \$new_master_password

);

exit &main();

sub main {
    $ssh_user = defined $ssh_user ? $ssh_user : 'root';
    print "\n\nIN SCRIPT TEST====$ssh_user|$ssh_stop_vip==$ssh_user|$ssh_start_vip===\n\n";

    if ( $command eq "stop" || $command eq "stopssh" ) {

        my $exit_code = 1;
        eval {
            print "Disabling the VIP on old master: $orig_master_host \n";
            &stop_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn "Got Error: $@\n";
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "start" ) {

        my $exit_code = 10;
        eval {
            print "Enabling the VIP - $vip on the new master - $new_master_host \n";
            &start_vip();
	    &start_arp();
            $exit_code = 0;
        };
        if ($@) {
            warn $@;
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "status" ) {
        print "Checking the Status of the script.. OK \n";
        exit 0;
    }
    else {
        &usage();
        exit 1;
    }
}

sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}

sub start_arp() {
    `ssh $ssh_user\@$new_master_host \" $ssh_Bcast_arp \"`;
}
sub usage {
    print
    "Usage: master_ip_failover --command=start|stop|stopssh|status --ssh_user=user --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";
}

赋予脚本可执行权限

chmod a+x /usr/bin/master_ip_failover

验证ssh互信配置

masterha_check_ssh --conf=/etc/mha/mysql_mha.cnf

验证mysql主从同步

masterha_check_repl --conf=/etc/mha/mysql_mha.cnf

报错如下

Redundantt /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm line 201.

解决方法见问题记录2,解决之后重新验证成功

07e25f806dfb5e278d4e13829f0c321d.png

启动MHA manager

nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf >/dev/null 2>/dev/null &
ps -ef|grep mha
#检测状态
masterha_check_status --conf=/etc/mha/mysql_mha.cnf 

#关闭mha
masterha_stop --conf=/etc/mha/mysql_mha.cnf 

查看mha监控日志

tail -f /home/mysql_mha/manager.log

测试主从切换

停止master

mha管理节点日志如下

1)判断master下线,准备启动故障转移

2)校验slave配置,移除VIP设置

3)从slave中选择一个master

4)获取新master节点的binlog位点,重新设置VIP

ea0c6a6dd69583a82f7beefaed50c0db.png

 5)将剩余从节点关联到新的master,开始复制,将新master节点slave info 清除

6)本次故障转移的总结报告

注:

1、宕机的原master重新上线后需要手动执行change master to建立主从关系

2、MHA进行一次故障切换之后,进程会退出

搭建问题记录

问题1 MHA验证主从复制报错Access denied; you need (at least one of) the SUPER, REPLICATION CLIENT privilege(s) for this operation

原因是配置的mha用户需要有root权限(grant all)

问题2 MHA验证主从复制报错Error happened on checking configurations. Redundantt /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm line 201.

百度说是代码里解析mysql版本有问题,修改代码

vi /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm

#找到如下两个方法parse_mysql_version和parse_mysql_major_version,修改代码

#修改前:
#sub parse_mysql_version($) {
#  my $str = shift;
#  my $result = sprintf( '%03d%03d%03d', $str =~ m/(\d+)/g );
#  return $result;
#}
#sub parse_mysql_major_version($) {
#  my $str = shift;
#  my $result = sprintf( '%03d%03d', $str =~ m/(\d+)/g );
#  return $result;
#}

#修改后:
sub parse_mysql_version($) {
  my $str = shift;
 ($str) =  $str =~ m/^[^-]*/g;
  my $result = sprintf( '%03d%03d%03d', $str =~ m/(\d+)/g );
  return $result;
}

sub parse_mysql_major_version($) {
  my $str = shift;
  $str =~ /(\d+)\.(\d+)/;
  my $strmajor = "$1.$2";
  my $result = sprintf( '%03d%03d', $strmajor =~ m/(\d+)/g );
  return $result;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 这个错误的原因可能是因为你的 MySQL 安装在 Docker 容器内,而 MHA 试图在宿主机上执行 MySQL 命令,导致找不到 mysqlbinlog 命令。 解决方法是在 MHA 配置文件中指定 MySQL 的执行路径,将其指向 Docker 容器内的 MySQL 安装目录。具体来说,你需要在 MHA 配置文件中的 [mysql_variables] 部分加入如下内容: ``` mysql_basedir="/path/to/mysql/install/directory" mysql_bindir="/path/to/mysql/install/directory/bin" ``` 替换 "/path/to/mysql/install/directory" 为 Docker 容器内 MySQL 安装目录的路径即可。 希望这些信息对你有帮助! ### 回答2: 在使用MySQL MHA搭建时遇到mysqlbinlog命令找不到的问题,可能是因为MySQL未安装或者环境变量配置不正确。 首先,你需要确认MySQL是否在Docker容器内正确安装。可以通过以下命令查看容器内是否已经安装了MySQL: docker exec -it [容器名] bash mysql -V 如果没有安装,你需要在Docker容器内安装MySQL。可以使用以下命令安装MySQL: apt-get update apt-get install mysql-server 如果MySQL已正确安装,但仍然提示mysqlbinlog命令找不到,那可能是因为环境变量配置不正确。我们可以通过以下步骤来解决这个问题: 1.首先,使用docker exec命令进入到正在运行的MySQL容器内: docker exec -it [容器名] bash 2.然后,查找mysqlbinlog的路径: find / -name mysqlbinlog 3.找到mysqlbinlog的路径后,将路径添加到环境变量中: export PATH=$PATH:[mysqlbinlog的路径] 4.保存并退出容器内的bash界面。 5.重新进入MySQL容器,在bash界面中尝试运行mysqlbinlog命令,确保已经可以找到该命令: docker exec -it [容器名] bash mysqlbinlog 通过这些步骤,您应该能够解决mysqlbinlog命令找不到的问题,并正常使用MySQL MHA搭建。如果问题仍然存在,请检查MySQL容器内的环境变量配置是否正确,并确认所使用的MySQL版本是否支持mysqlbinlog命令。 ### 回答3: 在搭建MHAMySQL高可用性解决方案)时,如果在docker容器内报出mysqlbinlog命令找不到的错误,可能是由于相关的MySQL client程序未正确安装或未正确配置环境变量所致。 首先,我们需要确认是否在docker容器内正确安装了MySQL client程序。可以使用以下命令验证是否已安装: ``` docker exec -it <container_id> mysql --version ``` 如果返回了正确的版本号,则说明MySQL client已正确安装。如果未安装,需要先在docker容器内安装MySQL客户端程序。 另外,当我们在docker容器内执行命令时,需要确认`mysqlbinlog`命令在可执行路径中。可以使用以下命令搜索该命令: ``` docker exec -it <container_id> find / -name mysqlbinlog ``` 找到`mysqlbinlog`的路径后,可以尝试直接运行该命令,验证是否能正常执行。 如果无法找到`mysqlbinlog`命令,可能是由于环境变量配置不正确导致的。可以使用以下命令查看环境变量配置情况: ``` docker exec -it <container_id> env ``` 确保`PATH`环境变量中包含了`mysqlbinlog`命令所在的路径。 如果以上步骤都没有解决问题,还可以尝试重新安装MySQL client程序或在docker容器内重新构建MySQL镜像。 总之,通过正确安装并配置MySQL client程序,以及在环境变量中正确设置`mysqlbinlog`命令所在的路径,应该可以解决mysqlbinlog命令找不到的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值