项目名称:MHA 高可用半同步主从复制 MYSQL 集群
项目描述
简介
模拟企业具体应用状态构建一个高可用并且高性能的MySQL集群项目,具备处理大并发的后端MySQL业务的能力。
- 进行四台mysql服务器的配置,安装mysql软件,并完成半同步相关插件的下载以及相关的配置
- 配置好ansible服务器,实现ansible和集群内部机器的双向免密通道
- 使用mysqldump将数据冷备至ansible服务器上,然后使用ansible服务将master数据传输至所有slave,完成集群数据统一
- 创建计划任务实现将master服务器的数据定时传入ansible,使ansible作为mysql集群的异地备份服务器
- 开启gtid服务,启动集群的主从复制,并且配置一台延时服务器slave3在slave1上获取数据,增强系统稳定性,便于出现问题时进行回档
- 使用MHA配置MYSQL集群的自动failover功能,从而实现集群的高可用性
- 启动MYSQLrouter服务,实现router服务器对于外部访问的转接,从而实现读写分离的负载均衡,提高mysql面对大并发时的处理能力
- 安装keepalive,通过vrrp协议实现mysqlrouter中间件的高可用
- 使用sysbench压力测试工具检验集群性能,确定集群系统资源的上限
项目架构图
项目ip规划
- master 192.168.2.137
- slave1 192.168.2.136
- slave2 192.168.2.135
- slave3 192.168.2.138
- ansible 192.168.2.139
- router1 192.168.2.140
- router2 192.168.2.141
- mha manager 192.168.2.142
- sysbench 192.168.2.143
- mha vip 192.168.2.200
- keepalive vip 192.168.2.188
项目环境
- CentOS:CentOS Linux release 7.9.2009 (Core)
- MySQL:mysql Ver 14.14 Distrib 5.7.38, for linux-glibc2.12 (x86_64)
- mha manager:mha4mysql-manager-0.58
- mha node:mha4mysql-node-0.58
- Keepalived: Keepalived v1.3.5 (03/19,2017)
- sysbench:sysbench 1.0.17
- Ansible:ansible 2.9.27
项目步骤
一. 进行四台mysql服务器的配置,安装mysql软件,并完成半同步相关插件的下载以及相关的配置
- 配置好相关环境
[root@master ~]# ls install_exporter.sh mha4mysql-node-0.58.tar.gz
install_exporter.sh脚本如下
[root@master ~]# cat onekey_install_mysql_binary.sh #!/bin/bash #解决软件的依赖关系 yum install cmake ncurses-devel gcc gcc-c++ vim lsof bzip2 openssl-devel ncurses-compat-libs -y #解压mysql二进制安装包 tar xf mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz #移动mysql解压后的文件到/usr/local下改名叫mysql #/usr/local/mysql 是mysql的安装目录--》门店 mv mysql-5.7.38-linux-glibc2.12-x86_64 /usr/local/mysql #新建组和用户 mysql groupadd mysql #mysql这个用户的shell 是/bin/false 属于mysql组 useradd -r -g mysql -s /bin/false mysql #关闭firewalld防火墙服务,并且设置开机不要启动 service firewalld stop systemctl disable firewalld #临时关闭selinux setenforce 0 #永久关闭selinux sed -i '/^SELINUX=/ s/enforcing/disabled/' /etc/selinux/config #新建存放数据的目录--》仓库 mkdir /data/mysql -p #修改/data/mysql目录的权限归mysql用户和mysql组所有,这样mysql用户启动mysql进程可以对这个文件夹进行读写了 chown mysql:mysql /data/mysql/ #只是允许mysql这个用户和mysql组可以访问,其他人都不能访问 chmod 750 /data/mysql/ #进入/usr/local/mysql/bin目录 cd /usr/local/mysql/bin/ #初始化mysql ./mysqld --initialize --user=mysql --basedir=/usr/local/mysql/ --datadir=/data/mysql &>passwd.txt #让mysql支持ssl方式登录的设置 ./mysql_ssl_rsa_setup --datadir=/data/mysql/ #获得临时密码 tem_passwd=$(cat passwd.txt |grep "temporary"|awk '{print $NF}') #$NF表示最后一个字段 # abc=$(命令) 优先执行命令,然后将结果赋值给abc # 修改PATH变量,加入mysql bin目录的路径 #临时修改PATH变量的值 export PATH=/usr/local/mysql/bin/:$PATH #重新启动linux系统后也生效,永久修改 echo 'PATH=/usr/local/mysql/bin:$PATH' >>/root/.bashrc #复制support-files里的mysql.server文件到/etc/init.d/目录下叫mysqld cp ../support-files/mysql.server /etc/init.d/mysqld #修改/etc/init.d/mysqld脚本文件里的datadir目录的值 sed -i '70c datadir=/data/mysql' /etc/init.d/mysqld #生成/etc/my.cnf配置文件 cat >/etc/my.cnf <<EOF [mysqld_safe] [client] socket=/data/mysql/mysql.sock [mysqld] socket=/data/mysql/mysql.sock port = 3306 open_files_limit = 8192 innodb_buffer_pool_size = 512M character-set-server=utf8 [mysql] auto-rehash prompt=\\u@\\d \\R:\\m mysql> EOF #修改内核的open file的数量 ulimit -n 1000000 #设置开机启动的时候也配置生效 echo "ulimit -n 1000000" >>/etc/rc.local chmod +x /etc/rc.d/rc.local #将mysqld添加到linux系统里服务管理名单里 /sbin/chkconfig --add mysqld #设置mysqld服务开机启动 /sbin/chkconfig mysqld on #启动mysqld进程 service mysqld start #初次修改密码需要使用--connect-expired-password 选项 #-e 后面接的表示是在mysql里需要执行命令 execute 执行 #set password='123456'; 修改root用户的密码为123456 mysql -uroot -p$tem_passwd --connect-expired-password -e "set password='123456';" #检验上一步修改密码是否成功,如果有输出能看到mysql里的数据库,说明成功。 mysql -uroot -p'123456' -e "show databases;"
在其余的slave机器上也重复进行操作即可
- 配置/etc/my.cnf文件
完成之后进行service mysqld restart 重启服务[mysqld_safe] [client] socket=/data/mysql/mysql.sock [mysqld] socket=/data/mysql/mysql.sock port = 3306 open_files_limit = 8192 innodb_buffer_pool_size = 512M character-set-server=utf8 #二进制日志 log_bin server_id=1 #该数值不可重复,且master服务器上应当为1 #设定日志数据清空的时间 expire_logs_days = 15 #半同步主从复制配置 需要提前安装半同步插件 rpl_semi_sync_master_enabled=1 log-slave-updates=ON [mysql] auto-rehash prompt=\u@\d \R:\m mysql>
-
进入mysql,下载半主从复制相关插件
[root@sc-master ~]# mysql -uroot -p'Sanchuang123#' #master服务器操作 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.7.38-log MySQL Community Server (GPL) Copyright (c) 2000, 2022, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. root@(none) 20:29 mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; [root@sc-slave1 ~]# mysql -uroot -p'Sanchuang123#' #slave服务器操作 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 41 Server version: 5.7.38-log MySQL Community Server (GPL) Copyright (c) 2000, 2022, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. root@(none) 20:33 mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
二.配置ansible服务器,打通ansible和集群内部机器的双向免密通道
- 在ansible服务器上生成密钥对
[root@ansible ~]# ssh-keygen
- 将ansible服务器上的密钥对发到各个mysql服务器上
ssh-copy-id root@192.168.2.137 ssh-copy-id root@192.168.2.136 ssh-copy-id root@192.168.2.135
- 安装部署ansible服务
[root@ansible ~]# yum install -y epel-release [root@ansible ~]# yum install ansible
- 配置好/etc/ansible/hosts文件
[root@ansible ~]# cd /etc/ansible/ [root@ansible ansible]# ls ansible.cfg hosts roles [root@ansible ansible]# vim hosts [db] 192.168.2.135 192.168.2.136 192.168.2.137 192.168.2.138 [dbslaves] 192.168.2.135 192.168.2.136 192.168.2.138
三. 使用mysqldump将数据冷备至ansible服务器上,然后使用ansible服务将master数据传输至所有slave,完成集群数据统一
- 使用mysqldump对master服务器的数据进行提取
[root@master backup]# mysqldump -uroot -p'1232456' --all-databases >/backup/all_db.sql mysqldump: [Warning] Using a password on the command line interface can be insecure.#该报错并不会产生影响
- 使用scp命令,将数据传输到ansible服务器
[root@master backup]# scp ./all_db.sql ansible:/root
- 在ansible服务器上通过ansible服务将数据传输至slave中
[root@localhost ~]# ansible -m copy -a "src=/root/all_db.sql dest=/root" dbslaves
- 在各个slave服务器上将数据导入至mysql
[root@sc-slave2 ~]# mysql -uroot -p'Sanchuang123#' <all_db.sql
此时在mysql集群中数据达成一致
四. 创建计划任务实现将master服务器的数据定时传入ansible,使ansible作为mysql集群的异地备份服务器
- 在master上编写脚本,利用mysqldump实现数据的备份,并对ansible服务器进行传输
[root@sc-master backup]# vim backup_alldb.sh #!/bin/bash mkdir -p /backup mysqldump -uroot -p'Sanchuang123#' --all-databases --triggers --routines --events >/backup/$(date +%Y%m%d%H%M%S)_all_db.SQL scp /backup/$(date +%Y%m%d%H%M%S)_all_db.SQL 192.168.2.139:/backup
- 制定计划任务,实现对于脚本的定期实行,使得数据定时被传入到ansible服务器中
[root@sc-master backup]# crontab -e 30 2 * * * bash /backup/backup_alldb.sh #需要提前在ansible服务器上建立好对应文件夹进行接收,否则会报错
五. 开启gtid服务,启动集群的主从复制,并且配置一台延时服务器slave3在slave1上获取数据,增强系统稳定性,便于出现问题时进行回档
- 对mysql服务器的/etc/my.cnf文件进行配置,开启gtid功能
[root@sc-master backup]# vim /etc/my.cnf [mysqld_safe] [client] socket=/data/mysql/mysql.sock [mysqld] socket=/data/mysql/mysql.sock port = 3306 open_files_limit = 8192 innodb_buffer_pool_size = 512M character-set-server=utf8 #二进制日志 log_bin server_id=1 #半同步主从复制配置 需要提前安装半同步插件 rpl_semi_sync_master_enabled=1 log-slave-updates=ON #新增配置 gtid-mode=ON enforce-gtid-consistency=ON [mysql] auto-rehash prompt=\u@\d \R:\m mysql>
- 在master服务器上进入mysql,并且创建一个具备访问日志文件权限的用户,使得slave服务器可以通过该用户获取master上的日志数据
root@(none) 21:34 mysql>grant replication slave on *.* to 'slave'@'192.168.2.%' identified by '123456'; #允许2网段的IO线程通过用户slave密码123456来拿取二进制日志 Query OK, 0 rows affected, 1 warning (0.01 sec) root@(none) 21:38 mysql>select user,host from mysql.user; +---------------+--------------+ | user | host | +---------------+--------------+ | slave | 192.168.2.% | | mysql.session | localhost | | mysql.sys | localhost | | root | localhost | +---------------+--------------+ 4 rows in set (0.00 sec)
- 在slave机器上配置master信息
root@(none) 21:42 mysql>stop slave; root@(none) 21:42 mysql>change master to master_host='192.168.2.137',master_user='slave',master_password='123456',master_port=3306,master_auto_position=1;
master_host=‘192.168.2.137’ #master ip地址
master_user=‘slave’ #master授权的用户
master_password=‘123456’ #授权用户密码
master_port=3306 #master端口号
master_auto_position=1 #gtid中事务数自增量为1
#在slave3上将master改为slave1的ip,并且增加MASTER_DELAY=10(单位为秒),从而实现slave3的延时备份 root@(none) 21:42 mysql>stop slave; root@(none) 21:42 mysql>change master to master_host='192.168.2.136',master_user='slave',master_password='123456',master_port=3306,master_auto_position=1,master_delay=600; #mysql中大小写不敏感
- 查看master信息,确认连接效果
root@(none) 15:43 mysql>start slave; root@(none) 15:43 mysql>show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.2.137 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000002 Read_Master_Log_Pos: 154 Relay_Log_File: slave-relay-bin.000004 Relay_Log_Pos: 369 Relay_Master_Log_File: master-bin.000002 Slave_IO_Running: Yes # 这两个是yes说明io线程正确联通,可以获得数据 Slave_SQL_Running: Yes # Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 154 Relay_Log_Space: 791 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: e1ae3fd1-db8f-11ee-859f-000c2974ba51 Master_Info_File: /data/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 600 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 1 ##表示gtid功能开启了 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version:
此时可以使用master服务器进入mysql进行一些操作,验证主从复制实现效果
六. 使用MHA配置MYSQL集群的自动failover功能,从而实现集群的高可用性
- 在ansible服务器上编写MHA主机清单,增加四个mha node节点和一个mha manager节点的ip地址
[root@ansible ansible]# vim /etc/ansible/hosts [mha_manager] 192.168.2.142 #mha manager [mha_node] 192.168.2.142 #mha manager 192.168.2.137 #master 192.168.2.136 #slave1 192.168.2.135 #slave2
- 准备好所需的部分软件包,并制作一键安装的脚本
node 脚本
manager脚本[root@ansible ~]# cat onekey_install_mha_node.sh #查看可以安装或者已安装的rpm包,并且作缓存 yum list #下载epel源 yum install epel-release --nogpgcheck -y #下载依赖包 yum install -y perl-DBD-MySQL \ perl-Config-Tiny \ perl-Log-Dispatch \ perl-Parallel-ForkManager \ perl-ExtUtils-CBuilder \ perl-ExtUtils-MakeMaker \ perl-CPAN #软件包mha4mysql-node-0.58.tar.gz放入/root目录下 cd ~ tar zxvf mha4mysql-node-0.58.tar.gz cd mha4mysql-node-0.58 #编译安装 perl Makefile.PL make && make install
#需要先运行node脚本,故而省略了部分依赖包 [root@ansible ~]# cat onekey_install_mha_manager.sh #软件包mha4mysql-manager-0.58.tar.gz放入/root目录下 tar zxvf mha4mysql-manager-0.58.tar.gz cd mha4mysql-manager-0.58 #编译安装 perl Makefile.PL make && make install
- 在ansible上编写playbook,直接远程执行本地脚本完成安装
[root@ansible ansible]# cat mha_install.yaml - hosts: mha_node remote_user: root tasks: - name: copy file copy: src=/root/mha4mysql-node-0.58.tar.gz dest=/root/ - name: install mha_node script: /root/onekey_install_mha_node.sh - hosts: mha_manager remote_user: root tasks: - name: copy file copy: src=/root/mha4mysql-manager-0.58.tar.gz dest=/root/ - name: install mha_manager script: /root/onekey_install_mha_manager.sh [root@ansible ansible]# ansible-playbook mha_install.yaml
- MHA服务器之间建立免密通道
#manager对node建立免密通道 [root@mha_manager bin]# ssh-keygen [root@mha_manager bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.137 [root@mha_manager bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.136 [root@mha_manager bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.135 master对slave1,slave2建立免密通道 [root@mha_master bin]# ssh-keygen [root@mha_master bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.135 [root@mha_master bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.136 slave1对master,slave2建立免密通道 [root@mha_slave1 bin]# ssh-keygen [root@mha_slave1 bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.137 [root@mha_slave1 bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.135 slave2对slave1,master建立免密通道 [root@mha_slave2 bin]# ssh-keygen [root@mha_slave2 bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.137 [root@mha_slave2 bin]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.2.136
- 搭建好主从复制后,配置mha相关信息
- 配置各服务器的/etc/my.cnf
#开启二进制日志 log_bin server_id = 1 #主从切换时,主从服务器身份都可能对换,从服务器重演relay_log日志操作时,也写入自己的log_bin中 log-slave-updates
配置完成后记得刷新配置文件
-
mysql服务器(master、slave1、slave2)将mysql命令和mysqlbinlog命令软链接到/usr/sbin,方便manager管理节点
[root@master ~]# ln -s /usr/local/mysql/bin/mysql /usr/sbin/ [root@master ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/ [root@slave1 ~]# ln -s /usr/local/mysql/bin/mysql /usr/sbin/ [root@slave1 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/ [root@slvae2 ~]# ln -s /usr/local/mysql/bin/mysql /usr/sbin/ [root@slave2 ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/
- 在mha服务器上配置用户,使得manager可以使用其进行访问
root@(none) 11:16 mysql>grant all on *.* to 'mha'@'192.168.2.%' identified by '123456'; Query OK, 0 rows affected, 1 warning (0.03 sec) root@(none) 11:19 mysql>grant all on *.* to 'slave'@'192.168.2.%' identified by '123456'; Query OK, 0 rows affected, 1 warning (0.01 sec) root@(none) 11:18 mysql>grant all on *.* to 'mha'@'192.168.2.137' identified by '123456'; Query OK, 0 rows affected, 1 warning (0.01 sec) root@(none) 11:19 mysql>grant all on *.* to 'mha'@'192.168.2.136' identified by '123456'; Query OK, 0 rows affected, 1 warning (0.00 sec) root@(none) 11:19 mysql>grant all on *.* to 'mha'@'192.168.2.135' identified by '123456'; Query OK, 0 rows affected, 1 warning (0.01 sec) root@(none) 11:19 mysql>select user,host from mysql.user; +---------------+----------------+ | user | host | +---------------+----------------+ | mha | 192.168.2.% | | slave | 192.168.2.% | | mha | 192.168.2.137 | | mha | 192.168.2.136 | | mha | 192.168.2.135 | | mysql.session | localhost | | mysql.sys | localhost | | root | localhost | +---------------+----------------+ 8 rows in set (0.00 sec)
- 配置各服务器的/etc/my.cnf
- 在mha_manager服务器上配置好服务器相关脚本
- 在mha_manager上复制相关脚本
[root@mha_manager bin]# cp -rp /root/mha4mysql-manager-0.58/samples/scripts/ /usr/local/bin/ [root@mha_manager bin]# cd /usr/local/bin/ [root@mha_manager bin]# ls apply_diff_relay_logs masterha_check_repl masterha_check_status masterha_manager masterha_master_switch masterha_stop save_binary_logs filter_mysqlbinlog masterha_check_ssh masterha_conf_host masterha_master_monitor masterha_secondary_check purge_relay_logs scripts [root@mha_manager bin]# cd scripts/ [root@mha_manager scripts]# ls master_ip_failover master_ip_online_change power_manager send_report
-
复制管理自动切换vip的脚本
[root@mha_manager scripts]# cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin/
-
修改master_ip_failover文件,配置vip
[root@mha_manager scripts]# >/usr/local/bin/master_ip_failover #清空文件内容,复制以下内容 [root@mha_manager scripts]# 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.2.200'; #指定vip的地址,自己指定 my $brdc = '192.168.2.255'; #指定vip的广播地址 my $ifdev = 'ens33'; #指定vip绑定的网卡 my $key = '1'; #指定vip绑定的虚拟网卡序列号 my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; #代表此变量值为ifconfig ens33:1 192.168.2.200 my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down"; #代表此变量值为ifconfig ens33:1 192.168.2.200 down my $exit_code = 0; #指定退出状态码为0 #my $ssh_start_vip = "/usr/sbin/ip addr add $vip/24 brd $brdc dev $ifdev label $ifdev:$key;/usr/sbin/arping -q -A -c 1 -I $ifdev $vip;iptables -F;"; #my $ssh_stop_vip = "/usr/sbin/ip addr del $vip/24 dev $ifdev label $ifdev:$key"; ################################################################################## 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 = 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(); $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 \"`; } ## 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_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"; }
-
创建 MHA 软件目录并复制配置文件,使用app1.cnf配置文件来管理 mysql 节点服务器,配置文件一般放在/etc/目录下
tip:脚本使用过程中需要将注释包括空格全部删除[root@mha_manager scripts]# mkdir /etc/masterha [root@mha_manager scripts]# cp /root/mha4mysql-manager-0.58/samples/conf/app1.cnf /etc/masterha/ [root@mha_manager scripts]# cd /etc/masterha/ [root@mha_manager masterha]# ls app1.cnf [root@mha_manager masterha]# >app1.cnf #清空原有内容 [root@mha_manager masterha]# vim app1.cnf [server default] manager_log=/var/log/masterha/app1/manager.log #manager日志(产生报错可以选择自建) manager_workdir=/var/log/masterha/app1.log #manager工作目录 master_binlog_dir=/data/mysql/ #master保存binlog的位置,这里的路径要与master里配置的binlog的路径一致,以便MHA能找到 master_ip_failover_script=/usr/local/bin/master_ip_failover #设置自动failover时候的切换脚本,也就是上面的那个脚本 master_ip_online_change_script=/usr/local/bin/master_ip_online_change #设置手动切换时候的切换脚本 user=mha #设置监控用户mha password=123456 #设置mysql中mha用户的密码,这个密码是前文中创建监控用户的那个密码 ping_interval=1 #设置监控主库,发送ping包的时间间隔1秒,默认是3秒,尝试三次没有回应的时候自动进行failover remote_workdir=/tmp #设置远端mysql在发生切换时binlog的保存位置 repl_user=slave #设置复制用户的用户slave repl_password=123456 #设置复制用户slave的密码 report_script=/usr/local/send_report #设置发生切换后发送的报警的脚本 secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.31.222 -s 192.168.31.223 #指定检查的从服务器IP地址 shutdown_script="" #设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用) ssh_user=root #设置ssh的登录用户名 [server1] #master hostname=192.168.2.137 port=3306 [server2] #slave1 hostname=192.168.2.136 port=3306 candidate_master=1 #设置为候选master,设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中最新的slave check_repl_delay=0 #默认情况下如果一个slave落后master 超过100M的relay logs的话,MHA将不会选择该slave作为一个新的master, 因为对于这个slave的恢复需要花费很长时间;通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master [server3] #slave2 hostname=192.168.2.135 port=3306
- 在mha_manager上复制相关脚本
- 在master服务器上手动开启vip
[root@master mysql]# ifconfig ens33:1 192.168.2.200/24
ip add 时出现该ip则说明运行成功
- 在manager服务器上测试ssh免密通道,如果正常最后会输出successfully
[root@mha_manager masterha]# masterha_check_ssh -conf=/etc/masterha/app1.cnf Mon May 8 11:50:00 2023 - [info] All SSH connection tests passed successfully.
- 在manager服务器上测试测试 mysql 主从连接情况,最后出现 MySQL Replication Health is OK 字样说明正常
[root@mha_manager masterha]# masterha_check_repl -conf=/etc/masterha/app1.cnf MySQL Replication Health is OK.
- manager开启MHA
[root@localhost ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 & [1] 42889
- 查看MHA状态
[root@mha_manager masterha]# masterha_check_status --conf=/etc/masterha/app1.cnf app1 (pid:42889) is running(0:PING_OK), master:192.168.2.137
- 查看MHA日志
[root@mha_manager masterha]# cat /var/log/masterha/app1/manager.log | grep "current master" Mon May 8 11:57:07 2023 - [info] Checking SSH publickey authentication settings on the current master.. 192.168.2.137(192.168.2.137:3306) (current master)
- 查看MHA状态
- 测试故障转移效果,将master宕机,将slave指定为新的master
- manager查看监控日志记录
[root@mha_manager bin]# tail -f /var/log/masterha/app1/manager.log
- 将master宕机(顺序错误会导致报错)
[root@master mysql]# service mysqld stop
- ip add查看slave1上是否有vip,如果有出现则说明漂移成功
- 查看/etc/masterha/app1.cnf
原来的server1以及被删除了 - 查看slave2的master信息
会发现master已经改成了slave1的ip地址
- manager查看监控日志记录
此时已经成功完成了vip的飘移,集群中剩余的机器会从slave1中获取日志文件,此时MHA已经成功配置,实现了mysql集群的高可用
七. 启动MYSQLrouter服务,实现router服务器对于外部访问的转接,从而实现读写分离的负载均衡,提高mysql面对大并发时的处理能力
- 首先准备好MYSQLrouter相关安装包
- 修改相关的配置文件
cd /etc/mysqlrouter/ vim mysqlrouter.conf #read-only [routing:slaves] bind_address = 192.168.2.141:7001 destinations = 192.168.2.135:3306,192.168.2.136:3306 mode = read-only connnect_timeout = 1 #write and read [routing:masters] bind_address = 192.168.2.141:7002 destinations = 192.168.2.137:3306 mode = read-write connect_timeout = 2
- 手动开启mysqlrouter服务
service mysqlrouter start
- 在mysql服务器上创建读写用户和只读用户,用于外部访问
grant all on *.* to 'write'@'%' identified by 'Sanchuang1234#'; grant select on *.* to 'read'@'%' identified by 'Sanchuang1234#';
- 使用一台集群外的服务器,试图通过router对集群进行访问检查转发效果
mysql -h 192.168.2.141 -P 7002 -uwrite -p'Sanchuang1234#'
当成功进入mysql后,说明MYSQLrouter服务配置成功,需要注意的是,mysqlrouter服务器的端口并不决定用户的具体权限,用户访问时具体拥有的权限仅与登录时所采用的mysql用户所具备的权限相关,至此mysql集群完成读写分离,提高了应对大并发时的处理能力,减轻master服务器压力
八. 安装keepalive,通过vrrp协议实现mysqlrouter中间件的高可用
- 配置环境,在router机上安装keepalive
[root@mysqlroute1 mysqlrouter]# yum install keepalived
- 修改keepalive配置文件
在master上的配置
在backup上的配置[root@mysqlroute1 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 200 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.2.188 } }
[root@mysqlroute2 keepalived]# cat keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state backup interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.2.188 } }
- 配置完成后刷新服务
[root@mysqlroute1 keepalived]# service keepalived restart
- ip add查看是否出现vip 出现即为成功配置
九. 使用sysbench压力测试工具检验集群性能,确定集群系统资源的上限
- 安装sysbench并进行相关配置
[root@sysbench ~]# yum install -y sysbench
- 调整内核资源数据
[root@sysbench ~]# ulimit -n 50000 [root@sysbench ~]# ulimit -u 50000 [root@sysbench ~]# ulimit -s 50000
- 进行压力测试
- 写请求,准备1000个客户在10秒内访问
[root@sysbench ~]# sysbench --threads=1000 --time=10 --report-interval=5 --db-driver=mysql --mysql-user=root --mysql-password=123456 --mysql-port=8066 --mysql-host=192.168.2.188 --mysql-db=test1 oltp_insert prepare #–threads:并发数,这里模拟的是1000个客户端; #–time:测试时间,单位为秒; #–report-interval:每隔几秒输出一次详细结果; #–db-driver:测试的数据库,可以是mysql,postgresql等, #–mysql-user:数据库用户(因为这里测试入口是mycat,所以也创建也mycat用户); #–mysql-password:数据库密码; #–mysql-port:数据库端口号; #–mysql-host:数据库ip地址; #–mysql-db:针对哪个库进行测试(这里我使用的之前建立的逻辑库test1); #oltp_insert:测试的sql语句类型,因为场景为高并发写入,肯定是insert语句,所以选择oltp_insert; [root@sysbench ~]# sysbench --threads=1000 --time=60 --report-interval=5 --db-driver=mysql --mysql-user=root --mysql-password=123456 --mysql-port=8066 --mysql-host=192.168.2.188 --mysql-db=test1 oltp_insert run #运行测试 [root@sysbench ~]# sysbench --threads=1000 --time=60 --report-interval=5 --db-driver=mysql --mysql-user=root --mysql-password=123456 --mysql-port=8066 --mysql-host=192.168.2.188 --mysql-db=test1 oltp_insert cleanup #测试完成后清理数据
- io性能测试
router1上安装sysbench
准备好10个文件,总体大小为1G[root@mysqlroute1 ~]# sysbench fileio --file-num=10 --file-total-size=1G prepare [root@mysqlroute1 ~]# sysbench --events=5000 --threads=16 fileio --file-num=10 --file-total-size=1G --file-test-mode=rndrw --file-fsync-freq=0 --file-block-size=16384 run
- cpu性能测试
[root@mysqlroute1 ~]# sysbench cpu --threads=40 --events=5000 --cpu-max-prime=20000 run
- 写请求,准备1000个客户在10秒内访问
项目心得
- 项目开始前需要整理好服务器的关系,作好规划,可以使执行项目时的过程条理更加清晰,便于溯源和纠错
- 执行前可以定期进行存档,方便出现错误时通过回档进行规避
- 出错后仔细检查操作是否无误,配置是否出现问题,应当多根据日志和报错信息的提示来进行纠错
- 总体完成之后对于数据库主从复制的了解更加深入
- 对于如何应对大并发和实现高可用有了更加深刻的理解
- 掌握了sysbench压力测试软件的使用,对于系统的负载能力和具体资源情况的认知更加清楚
- 合理使用ansible服务可以避免很多的重复操作,但对于使用过程中个体化操作的应用应该更加谨慎
- 进行文件的配置时需要更加细致,记得要重启服务,并在重启出现问题时及时对于出现问题的部分进行查询和修改