基于mysql8.0.27部署1主2从的MHA集群
目录
一、mysql概述
1.1、关系型数据库
1.2、MySQL数据库
1.3、RDBMS术语
二、mysql的部署
2.1、拉取mysql
2.2、解压
2.3、 改名
2.4、 指定安装文件位置
2.5、 创建用户组
2.6、 修改mysql配置文件
2.7、创建data文件夹
2.8、更改mysql目录权限
2.9、初始化数据库
2.10、查看初始密码
2.11、 启动mysql服务
2.12、使用初始密码进入数据库,修改密码
2.13、设置远程连接
2.14、测试连接
三、mysql主主复制部署
3.1、克隆两台服务
3.2、 添加对应主机
3.3、 关闭防火墙以及修改selinux
3.4、 修改俩台服务器的配置文件
3.5、主服务器
3.6、查看主服务器的日志配置
3.7、从服务器
3.8、从服务器
3.9、主服务器
3.10、在主服务查看
四、MHA集群部署
添加主机名
4.1、 安装MHA
4.2、免密
4.3、创建mysql的软链接
4.4、创建用户
4.5、配置环境变量
4.6、 创建manager的配置文件
4.7、检查互信
4.8、 检查主从复制状态
4.9、开启MHA-manager
4.10、查看MHA状态
4.11、 测试HA高可用的自动切换
4.12、 回到主
五、MHA+VIP部署
5.1、修改mha.cnf配置文件
5.2、编写 master_ip_failover文件
5.3、添加 master_ip_failover的权限
5.4、添加虚拟ip
5.5、 测试状态检查
5.6、开启MHA-manager
5.7、测试
5.8、查看IP
5.9、进入host2,查看ip
5.10、手动转移
5.10、测试连接
5.11、查看日志
一、mysql概述
1.1、关系型数据库
关系型数据库天然就是二维表格,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。
1.2、MySQL数据库
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司。
MySQL可将数据保存在不同的表中,而不是将所有数据放在一个大的仓库内,从而加快了访问速度并提高了灵活性。
MySQL 使用了标准的 SQL 语言形式。支持大型的数据库,可以处理拥有上千万条记录的大型数据库。MySQL 还可用于多种系统中,且支持多种语言。
1.3、RDBMS术语
数据库:数据库是一些关联表的集合。
数据表:表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。
列:一列(数据元素)包含了相同的数据,例如邮政编码的数据。
行:一行(=元组,或者记录)是一组相关的数据,例如一条用户订阅的数据。
亢余:存储两倍数据,亢余降低了性能,但是提高了数据的安全性。
主键:主键是唯一的,一个数据表中只能够包含一个主键,你可以使用主键来查询数据。
外键:外键用于关联两个表。
复合键:复合键(组合键)将多个列作为一个索引键,一般用于复合索引。
索引:使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或者多列的值进行排序的一种结构。类似于书籍的目录。
二、mysql的部署
2.1、拉取mysql
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.27-el7-x86_64.tar.gz
2.2、解压
tar -xvf mysql-8.0.27-el7-x86_64.tar.gz
2.3、 改名
mv mysql-8.0.27-el7-x86_64 mysql
2.4、 指定安装文件位置
mv mysql /usr/local
2.5、 创建用户组
groupadd mysql
useradd -r -g mysql mysql
passwd mysql
2.6、 修改mysql配置文件
/etc/my.cnf[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
# server_id = .....
socket = /tmp/mysql.sock
character-set-server = utf8
skip-name-resolve
log-error = /usr/local/mysql/data/error.log
pid-file = /usr/local/mysql/data/mysql.pidsql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
2.7、创建data文件夹
cd /usr/local/mysql
mkdir data
2.8、更改mysql目录权限
chown -R mysql .
chgrp -R mysql .
2.9、初始化数据库
./bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
2.10、查看初始密码
vim /usr/local/mysql/data/error.log
2.11、 启动mysql服务
./support-files/mysql.server start
2.12、使用初始密码进入数据库,修改密码
./bin/mysql -uroot -palter user 'root'@'localhost' identified by 'Root123456';
2.13、设置远程连接
mysql> create user 'root'@'%' identified with mysql_native_password by 'Root123456';
Query OK, 0 rows affected (0.01 sec)mysql> grant all on *.* to 'root'@'%';
Query OK, 0 rows affected (0.00 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
2.14、测试连接
systemctl stop firewalld.service
firewall-cmd --state
三、mysql主主复制部署
3.1、克隆两台服务
删除每台服务器的server-uuid,并重新启动mysql,生成新的uuid
3.2、 添加对应主机
vim /etc/hosts192.168.157.80 host1
192.168.157.81 host2
192.168.157.82 host3
3.3、 关闭防火墙以及修改selinux
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld # 关闭自启动# 修改selinux
vim /etc/sysconfig/selinux
SELINUX=disabled # 设置为disabled
3.4、 修改俩台服务器的配置文件
主从服务器/etc/my.cnf添加以下三行server-id=200
log-bin=mysql-bin
binlog_checksum=nonelog-bin=mysql-bin //将mysql二进制日志取名为mysql-bin
binlog_checksum=none //不对二进制检查
server-id=200 //为服务器设置一个独一无二的id便于区分,建议使用ip地址的最后一位充当server-id
3.5、主服务器
use mysql;
CREATE USER 'slave'@'%' IDENTIFIED BY 'abc123';
grant REPLICATION SLAVE on *.* to 'slave'@'%';
alter user 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123';
flush privileges;
3.6、查看主服务器的日志配置
show master status;
3.7、从服务器
根据主服务器的日志配置配置从服务器
change master to master_host='192.168.157.80',master_user='slave',master_password='abc123', master_log_file='mysql-bin.000001',master_log_pos=1124;启动从服务器slave :start slave;
查看是否配置成功:show slave status;
3.8、从服务器
从服务器
use mysql;
CREATE USER 'slave1'@'%' IDENTIFIED BY 'abc123';
grant REPLICATION SLAVE on *.* to 'slave1'@'%';
alter user 'slave1'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123';
flush privileges;查看从服务器的日志配置:show master status;
3.9、主服务器
根据从服务器的日志配置主服务器
change master to master_host='192.168.157.81',master_user='slave1',master_password='abc123', master_log_file='mysql-bin.000001',master_log_pos=1130;start slave;
3.10、在主服务查看
show slave status \G;
四、MHA集群部署
192.168.157.80 | host1 | 主库 |
192.168.157.81 | host2 | 备选主库 |
192.168.157.82 | host3 | 从库 |
注:我这个的MHA-manager部署在主库上(但一般不部署在主库上,部署在从库上为最佳)
添加主机名
配置MHA集群不用搞主主复制
vim /etc/hosts192.168.157.80 host1
192.168.157.81 host2
192.168.157.82 host3
4.1、 安装MHA
- 所有节点安装node软件依赖包和node软件yum -y install perl-DBD-MySQL
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm- 在manager安装manager软件依赖包和manager软件
yum install -y perl-Config-Tiny
yum install -y epel-release
yum install -y perl-Log-Dispatch
yum install -y perl-Parallel-ForkManager
yum install -y perl-Time-HiResrpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
4.2、免密
分发ssh密钥
在 所有服务器(包括 host1, host2, host3)上执行以下操作:# 生成各自的密钥对(如果没有)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""# 将所有服务器的公钥收集到 host1
for host in 192.168.157.80 192.168.157.81 192.168.157.82; doecho "收集 $host 的公钥:"ssh root@$host "cat ~/.ssh/id_rsa.pub" >> ~/.ssh/all_servers.pub
done# 在 host1 上,将所有公钥添加到 authorized_keys
cat ~/.ssh/all_servers.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys# 将 host1 的 authorized_keys 复制回所有服务器
for host in 192.168.157.80 192.168.157.81 192.168.157.82; doscp ~/.ssh/authorized_keys root@$host:~/.ssh/
done检查 host1 的 SSH 配置
确保 host1 的 /etc/ssh/sshd_config 配置正确:PermitRootLogin yes
PubkeyAuthentication yes
PasswordAuthentication no # 可选,取决于你的安全策略
AuthorizedKeysFile .ssh/authorized_keys重启ssh服务:
systemctl restart sshd手动验证 SSH 连接
在 host2 和 host3 上分别测试到 host1 的 SSH 连接:# 在 host2 上
ssh root@host1# 在 host3 上
ssh root@host1
4.3、创建mysql的软链接
# 在三个主机系统bin目录创建软连接(需root权限)
ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /usr/local/mysql/bin/mysqldump /usr/bin/mysqldump
4.4、创建用户
在host1,host2,host3中cd /usr/local/mysql
./bin/mysql -u root -pCREATE USER 'slave'@'%' IDENTIFIED BY 'abc123';
grant REPLICATION SLAVE on *.* to 'slave'@'%';
alter user 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123';
flush privileges;
4.5、配置环境变量
在三台主机上
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> ~/.bashrc
source ~/.bashrc
4.6、 创建manager的配置文件
#创建配置文件目录、日志目录
mkdir -p /etc/mha
mkdir -p /var/log/mha/log#编辑mha配置文件 vi /etc/mha/mha.cnf
[server default]
manager_log=/var/log/mha/log/manager # MHA 管理器的日志文件路径
manager_workdir=/var/log/mha/log # MHA 管理器的工作目录
master_binlog_dir=/usr/local/mysql/data # 主库二进制日志所在目录
user=root # MHA 连接 MySQL 的用户名
password=root # MHA 连接 MySQL 的密码
ping_interval=2 # 检查服务器状态的间隔时间(秒)
repl_user=slave # 复制用户(用于从库同步)
repl_password=abc123 # 复制用户的密码
ssh_user=root # SSH 连接用户(用于远程操作服务器)
[server1]
hostname=host1 # 服务器 1 的主机名或 IP
port=3306 # 服务器 1 的 MySQL 端口
[server2]
hostname=host2 # 服务器 2 的主机名或 IP
port=3306 # 服务器 2 的 MySQL 端口
candidate_master=1 # 可提升为主库的候选从库,搞了多主模式可加入
check_repl_delay=0 # 忽略复制延迟检查(根据需求设置)
[server3]
hostname=host3 # 服务器 3 的主机名或 IP
port=3306 # 服务器 3 的 MySQL 端口
4.7、检查互信
masterha_check_ssh --conf=/etc/mha/mha.cnf
4.8、 检查主从复制状态
masterha_check_repl --conf=/etc/mha/mha.cnf
注:出现问题
1、需要注释三台主机中my.cnf中 [client]下的字符配置;
2、配置三台主机中MySQL的环境变量;
3、如果之前测试过故障自动转移,需要将/var/log/mha/log文件夹下的对应的 complete文件删除
以上处理完成之后再进行检测集群是否健康。
4.9、开启MHA-manager
nohup masterha_manager --conf=/etc/mha/mha.cnf > /var/log/mha/log/manager.log < /dev/null 2>&1 &
4.10、查看MHA状态
masterha_check_status --conf=/etc/mha/mha.cnf
4.11、 测试HA高可用的自动切换
在host1上,执行shutdown操作
mysqladmin -uroot -proot shutdownMHA会自动进行主从切换。切换完成后,MHA进程会自动停止运行。在host2和host3上观察,执行下面的语句:
show slave status\G;
host1:
host2:
host3:
4.12、 回到主
在新主库(host3)上
STOP SLAVE; 在host2上
STOP SLAVE; 在旧主库(host1)上
STOP SLAVE;
RESET SLAVE ALL; -- 清除原复制配置在host1上
SHOW MASTER STATUS;在host2,host3上
change master to master_host='192.168.157.80',master_user='slave',master_password='abc123', master_log_file='mysql-bin.000002',master_log_pos=152;start slave;SHOW SLAVE STATUS\G;
五、MHA+VIP部署
5.1、修改mha.cnf配置文件
vim /etc/mha/mha.cnf在server-default下添加如下代码
master_ip_failover_script=/etc/mha/master_ip_failover
5.2、编写 master_ip_failover文件
vim /etc/mha/master_ip_failover#!/bin/bash
# 完整的 MHA VIP 管理脚本(支持自动切换 VIP)
# 配置参数
VIP="192.168.157.88" # VIP 地址
NETMASK="24" # 子网掩码
INTERFACE="ens33" # 网络接口(修正拼写错误:end33 → ens33)
ARPING_COUNT=3 # ARP 广播次数
LOG_FILE="/var/log/mha/vip_scripts.log"
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=10" # SSH 选项# 解析参数
command=""
ssh_user=""
orig_master_host=""
orig_master_ip=""
orig_master_port=""
new_master_host=""
new_master_ip=""
new_master_port=""while [[ $# -gt 0 ]]; docase "$1" in--command=*)command="${1#*=}"shift;;--ssh_user=*)ssh_user="${1#*=}"shift;;--orig_master_host=*)orig_master_host="${1#*=}"shift;;--orig_master_ip=*)orig_master_ip="${1#*=}"shift;;--orig_master_port=*)orig_master_port="${1#*=}"shift;;--new_master_host=*)new_master_host="${1#*=}"shift;;--new_master_ip=*)new_master_ip="${1#*=}"shift;;--new_master_port=*)new_master_port="${1#*=}"shift;;*)shift;;esac
done# 日志函数
log() {local level=$1local message=$2local timestamp=$(date '+%Y-%m-%d %H:%M:%S')echo "$timestamp [$level] $message" >> "$LOG_FILE"# 同时输出到控制台(便于调试)echo -e "[$timestamp] [$level] $message"
}# 执行 SSH 命令并返回结果
ssh_exec() {local host=$1local cmd=$2log "INFO" "在 $host 执行命令: $cmd"# 执行 SSH 命令并捕获输出和退出码local output=$(ssh $SSH_OPTS "$ssh_user@$host" "$cmd" 2>&1)local exit_code=$?if [ $exit_code -ne 0 ]; thenlog "ERROR" "SSH 命令执行失败($host): $output"elselog "INFO" "SSH 命令执行成功($host): $output"fireturn $exit_code
}# 添加 VIP 到新主库
add_vip() {local host=$1log "INFO" "开始在新主库 $host 添加 VIP: $VIP/$NETMASK"# 1. 检查网络接口是否存在local check_interface="ip link show $INTERFACE > /dev/null 2>&1"if ! ssh_exec "$host" "$check_interface"; thenlog "ERROR" "网络接口 $INTERFACE 在 $host 上不存在"return 1fi# 2. 添加 VIPlocal add_cmd="ip addr add $VIP/$NETMASK dev $INTERFACE label ${INTERFACE}:0"if ! ssh_exec "$host" "$add_cmd"; thenlog "ERROR" "在 $host 上添加 VIP 失败"return 1fi# 3. 发送 ARP 广播(更新网络缓存)local arp_cmd="arping -c $ARPING_COUNT -A -I $INTERFACE $VIP > /dev/null 2>&1"if ! ssh_exec "$host" "$arp_cmd"; thenlog "WARN" "ARP 广播发送失败,但 VIP 已添加"filog "INFO" "VIP 已成功添加到 $host"return 0
}# 从原主库移除 VIP
remove_vip() {local host=$1log "INFO" "开始从原主库 $host 移除 VIP: $VIP"# 1. 检查 VIP 是否存在local check_vip="ip addr show $INTERFACE | grep -q '$VIP/$NETMASK'"if ! ssh_exec "$host" "$check_vip"; thenlog "WARN" "VIP $VIP 在 $host 上不存在,跳过移除"return 0fi# 2. 移除 VIPlocal del_cmd="ip addr del $VIP/$NETMASK dev $INTERFACE"if ! ssh_exec "$host" "$del_cmd"; thenlog "ERROR" "从 $host 上移除 VIP 失败"return 1fi# 3. 发送 ARP 广播(通知网络更新)local arp_cmd="arping -c $ARPING_COUNT -A -I $INTERFACE $VIP > /dev/null 2>&1"ssh_exec "$host" "$arp_cmd"log "INFO" "VIP 已成功从 $host 移除"return 0
}# 主逻辑
main() {# 初始化日志目录mkdir -p "$(dirname "$LOG_FILE")"log "INFO" "===== VIP 管理脚本启动 ====="log "INFO" "解析到的参数: command=$command, 原主库=$orig_master_host, 新主库=$new_master_host"case "$command" in"start")# 新主库启动 VIPif [ -z "$new_master_host" ]; thenlog "ERROR" "start 命令缺少新主库参数"exit 1fiif add_vip "$new_master_host"; thenlog "INFO" "VIP 切换到新主库 $new_master_host 成功"exit 0elselog "ERROR" "VIP 切换到新主库 $new_master_host 失败"exit 1fi;;"stop"|"stopssh")# 从原主库移除 VIPif [ -z "$orig_master_host" ]; thenlog "ERROR" "stop 命令缺少原主库参数"exit 1fiif remove_vip "$orig_master_host"; thenlog "INFO" "从原主库 $orig_master_host 移除 VIP 成功"exit 0elselog "ERROR" "从原主库 $orig_master_host 移除 VIP 失败"exit 1fi;;"status")# MHA 状态检查(必须返回 0)log "INFO" "脚本状态正常,支持 VIP 管理"exit 0;;*)log "ERROR" "未知命令: $command(支持的命令: start/stop/stopssh/status)"exit 1;;esac
}# 执行主函数
main "$@"
5.3、添加 master_ip_failover的权限
chmod +x /etc/mha/master_ip_failover
5.4、添加虚拟ip
添加虚拟IP:ifconfig ens33:0 192.168.157.88/24删除虚拟IP:ip addr del 192.168.157.88/24 dev ens33
5.5、 测试状态检查
/etc/mha/master_ip_failover --command=status --ssh_user=root
5.6、开启MHA-manager
nohup masterha_manager --conf=/etc/mha/mha.cnf > /var/log/mha/log/manager.log < /dev/null 2>&1 &查看MHA状态
masterha_check_status --conf=/etc/mha/mha.cnf
5.7、测试
在host1上,执行shutdown操作
mysqladmin -uroot -proot shutdown
5.8、查看IP
5.9、进入host2,查看ip
5.10、手动转移
# 测试状态检查(应返回成功)
/etc/mha/master_ip_failover --command=status --ssh_user=root# 测试添加 VIP 到 host2
/etc/mha/master_ip_failover --command=start --ssh_user=root --new_master_host=host2# 测试从 host2 移除 VIP
/etc/mha/master_ip_failover --command=stop --ssh_user=root --orig_master_host=host2