查看源文件

MGR部署MySQL5.7

MySQL高可用工具

MGR

  • MGR(MySQL Group Replication)是一种数据库集群技术,允许多个 MySQL 服务器协同工作,形成一个高可用的数据库集群。当一个mysql出现故障时,其他mysql可以继续工作,确保服务的连续性和数据的高可用性。
  • MGR允许多个 MySQL 实例组成一个组,这些实例之间会自动同步数据,确保数据的一致性和高可用性。如果某个实例出现故障,其他实例会继续工作,从而保持服务的连续性。
  • MGR 由 MySQL 提供,但使用前需要加载 group_replication 插件;下文通过 plugin_load_add 加载。MGR集群也有一些限制和要求,例如需要使用InnoDB存储引擎。

适用于需要高度自动化和数据一致性的场景。它提供了内置的高可用性解决方案,适合不希望依赖第三方工具的用户。

MMM

  • MMM(MySQL Multi-Master Replication Manager)是一种用于管理 MySQL 主从复制的工具。它允许你配置多个主节点和从节点,并在主节点发生故障时自动进行故障转移。MMM 可以帮助你实现读写分离,提升系统性能。

适用于需要复杂复制拓扑和读写分离的场景。它允许配置多个主节点和从节点,但需要手动管理和监控。

MHA

  • MHA(Master High Availability Manager and tools)MHA 是一种用于 MySQL 主从复制环境中的高可用性管理工具。它在主节点发生故障时,能够自动选举一个新的主节点,并重新配置复制关系,从而实现快速故障转移。

适用于需要快速故障转移和高可用性的主从复制环境。它能够自动处理主节点故障,但不支持多主复制。


部署 MGR 单主集群

环境准备

IPhostnamePortServerIDOS
192.168.40.100xianchaomaster1330663CentOS 7.9
192.168.40.101xianchaomaster2330664CentOS 7.9
192.168.40.102xianchaomaster3330662CentOS 7.9

安装 MySQL

  • 配置三台hosts文件
tee -a /etc/hosts <<'EOF'
192.168.40.102    xianchaomaster3
192.168.40.100    xianchaomaster1
192.168.40.101    xianchaomaster2
EOF
  • 安装mysql
#所有节点,上传预先准备好的压缩包:mysql-5.7.tar.gz,包括了安装mysql5.7主要的软件包
tar xvf mysql-5.7.tar.gz
yum -y install ./mysql*.rpm
systemctl start mysqld
#启动MySQL会生成临时密码。
#在MySQL的配置文件/etc/my.cnf中关闭密码强度审计插件,并重启MySQl服务。
vim /etc/my.cnf	
#修改MySQL的配置文件,在[mysqld]标签处末行添加以下项:
validate_password=OFF     	#不使用密码审计插件
 
systemctl restart mysqld
grep 'password'  /var/log/mysqld.log #获取临时密码。
  • 登录mysql修改root密码
mysql -u root -p'buL.UJp!T2Od' #使用临时密码登录MySQl,注意临时密码要引号
mysql> set password for root@localhost = password('123456');		
#修改root用户密码为123456
mysql> use mysql;
mysql> update user set host = '192.168.40.%' where user = 'root';
mysql> update user set host = '%' where user = 'root';
mysql> flush privileges;

配置master1主节点

#group_name可以通过uuidgen生成
uuidgen
 
#服务器xianchaomaster1配置/etc/my.cnf
#参考:官网配置https://dev.mysql.com/doc/refman/5.7/en/group-replication-configuring-instances.html
vim /etc/my.cnf   
#在  [mysqld] 配置组中,增加以下红色内容:
server_id = 63 
#这个设置给当前 MySQL 服务分配了一个唯一的标识号码,用来在复制和集群中区分不同的服务。
gtid_mode = ON 
#开启全局事务标识(GTID),用于在数据库复制和高可用性方案中确保事务的唯一性和一致性。
enforce_gtid_consistency = ON       
#强制 GTID 一致性,确保所有数据库节点上执行的事务顺序和一致性。
master_info_repository = TABLE 
#将主数据库的元数据(如位置信息)保存在系统表中,以便管理和复制时使用。
relay_log_info_repository = TABLE   
#将中继日志的元数据(如位置信息)也保存在系统表中,用于复制进程的管理和监控。
binlog_checksum = NONE  		
#禁用二进制日志事件的校验,简化日志记录过程。
log_slave_updates = ON  		
#允许从服务器也记录其接收和执行的更改,支持级联复制(即从服务器再次作为主服务器向下游复制)。
log_bin = binlog 
#开启二进制日志记录,将数据库的更改以二进制格式记录下来,以便复制和恢复。
binlog_format = ROW  		
#以行的格式记录二进制日志,记录每行数据的变化,有助于准确复制数据的变更。
plugin_load_add='group_replication.so'   
#加载并启用 MySQL 的组复制插件,用于实现多个数据库实例之间的同步和协作。
transaction_write_set_extraction=XXHASH64  
#使用哈希算法将事务写入集提取为散列,有助于数据库更有效地处理和记录事务。
group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"
#设置组复制的唯一标识符,确保每个参与组复制的数据库实例都能识别并加入正确的组。 
group_replication_start_on_boot=off  
#设置数据库实例不会在启动时自动加入组复制,需要手动控制启动过程。
group_replication_local_address="xianchaomaster1:33063"  
#指定本地 MySQL 实例接受其他组成员的连接的地址和端口号。
group_replication_group_seeds="xianchaomaster1:33063, xianchaomaster2:33064, xianchaomaster3:33062" 
#指定组成员的地址和端口,用于初始化组复制中的初始通信和连接。
group_replication_bootstrap_group=off 
#禁用组引导功能,避免在启动时自动创建一个新的复制组。
 
#重启MySQL服务
systemctl restart mysqld

配置参数详解

  1. ==server_id = 63==:每个MySQL服务都像一个独特的身份证号码一样,以便在集群中识别和区分不同的服务器。
  2. ==gtid_mode = ON==:开启了一个全球唯一的事务ID,可以用来标识数据库中的每个事务,有助于跟踪和管理数据库复制。
  3. ==enforce_gtid_consistency = ON==:确保在数据库复制时,所有事务都以一致的方式被复制到其他服务器,以避免数据不一致问题。
  4. ==master_info_repository = TABLE 和 relay_log_info_repository = TABLE==:将有关主服务器和中继日志的一些关键信息保存在MySQL系统表中,以便服务器能够管理和访问这些信息。
  5. ==binlog_checksum = NONE==:关闭了对二进制日志的数据完整性检查,可能会提高性能,但要小心数据一致性问题。
  6. ==log_slave_updates = ON==:从服务器可以记录自己的二进制日志,允许其他服务器复制这个从服务器的数据。
  7. ==log_bin = binlog 和 binlog_format = ROW==:将数据库的更改操作以二进制形式记录,以行的方式记录每个操作的详细信息。
  8. ==plugin_load_add=‘group_replication.so’==:启用一个名为group_replication.so的插件,用于启用MySQL的组复制功能。
  9. ==transaction_write_set_extraction=XXHASH64==:用一种特定的哈希算法来处理事务的写入操作。
  10. group_replication_group_name:为组复制集群起一个唯一的名称,以便其他服务器可以加入这个集群。
  11. ==group_replication_start_on_boot=off==:不要在服务器启动时自动开始组复制,需要手动启用。
  12. group_replication_local_address:指定服务器在哪个IP地址和端口上接收其他组成员的连接请求。
  13. group_replication_group_seeds:告诉服务器在哪些IP地址和端口上可以找到其他组成员,以便它们可以建立连接。
  14. ==group_replication_bootstrap_group=off==:不要启动一个新的组,而是让服务器加入一个已经存在的组。
  • master1配置复制账号
mysql -u root -p123456
mysql> set SQL_LOG_BIN=0;   	#停掉日志记录
mysql> grant replication slave on *.* to repl@'192.168.40.%' identified by '123456';
#创建一个用户名为 repl 的用户,并允许该用户从 192.168.40.* 范围内的任何 IP 地址以123456这个密码连接到 MySQL 服务,同时授予该用户进行数据复制所需的权限
 
mysql> grant replication slave on *.* to repl@'%' identified by '123456';
#创建一个用户repl,后期用于其他节点,同步数据。
 
mysql> flush privileges; #重新加载授权表,从而使对用户权限所做的更改立即生效
mysql> set SQL_LOG_BIN=1;  	#开启日志记录

为什么创建repl用户需要关闭二进制日志功能?

因为用于同步数据的用户名repl和密码,必须在所有节点上有,且用户名和密码必须一样。所以,创建用户和密码时,先关闭二进制日志功能,这样不产生二进制日志数据。创建成功后,再开启二进制日志功能。这样repl用户信息,每台机器上都有了,而且不会在MGR同步数据时产生冲突。

mysql> change master to master_user='repl',master_password='123456'  for channel 'group_replication_recovery';

CHANGE MASTER TO 命令说明

  • CHANGE MASTER TO: 这是 MySQL 的命令,用于修改从节点的复制配置。
  • ==MASTER_USER=‘repl’==: 指定连接主节点的用户名为 repl,这是一个在主节点上用于复制的已授权用户。
  • ==MASTER_PASSWORD=‘123456’==: 指定连接主节点的密码,这里设置为 123456,以确保从节点能够安全地连接到主节点进行数据复制。
  • FOR CHANNEL 'group_replication_recovery': 指定这个配置是为名为 group_replication_recovery 的复制通道进行的。在MySQL 组复制中,每个从节点都会为复制通道分配一个唯一的标识符,这里使用通道名称来区分不同的复制配置。
#查看MySQL服务器xianchaomaster1上安装的group replication插件,这个组件在my.cnf配置文件中,plugin_load_add='group_replication.so'有指定。
mysql> show plugins;
#如果没有安装成功,可以执行这个命令,手动再次安装:安装插件
mysql> install PLUGIN group_replication SONAME 'group_replication.so';
#启动服务器xianchaomaster1上MySQL的group replication
# 只在首个成员上临时启用 bootstrap,以创建复制组;这不决定后续成员的角色。
mysql> set global group_replication_bootstrap_group=ON; 
  • 作为首个节点启动mgr集群

    mysql> start group_replication;
    mysql> set global group_replication_bootstrap_group=OFF;   #启动成功后,这台服务器已经是master了。有了master后,引导器就没有用了,就可以关闭了。
  • 查看mgr的状态

    #查询表performance_schema.replication_group_members
    mysql> select * from performance_schema.replication_group_members;
  • 测试服务器xianchaomaster1上的MySQL

    mysql> create database test;
    mysql> use test;
    mysql> create table t1 (id int primary key,name varchar(20));  #注意创建主键
    mysql> insert into t1 values (1,'man');
    mysql> select * from t1;
    mysql> show binlog events;

将 master2 加入集群

  • 复制组添加新实例xianchaomaster2

    #在master2上面,修改/etc/my.cnf 配置文件,方法和之前相同。 
    vim /etc/my.cnf   #在mysqld配置,追加以下内容
     
    server_id=64  #注意服务ID不能一样
    gtid_mode=ON
    enforce_gtid_consistency=ON
    master_info_repository=TABLE
    relay_log_info_repository=TABLE
    binlog_checksum=NONE
    log_slave_updates=ON
    log_bin=binlog
    binlog_format=ROW
     
    plugin_load_add='group_replication.so'
    transaction_write_set_extraction=XXHASH64
    group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"  #这保持和master一样
    group_replication_start_on_boot=off
    group_replication_local_address="xianchaomaster2:33064"   #以本机端口33064接受来自组中成员的传入连接
    group_replication_group_seeds="xianchaomaster1:33063, xianchaomaster2:33064, xianchaomaster3:33062" #组成员列表
    group_replication_bootstrap_group=off
    systemctl restart mysqld
  • 用户授权

mysql -u root -p123456
mysql> set SQL_LOG_BIN=0;   #停掉日志记录
mysql> grant replication slave on *.* to repl@'192.168.40.%' identified by '123456';
mysql> grant replication slave on *.* to repl@'%' identified by '123456';
mysql> flush privileges;
mysql> set SQL_LOG_BIN=1;  #开启日志记录
mysql> change master to master_user='repl',master_password='123456'  for channel 'group_replication_recovery';  #构建group replication集群
  • 把实例添加到之前的复制组
#master2上
# 加入前确认数据与 GTID 集合兼容,不绕过不相交 GTID 检查。
mysql> start group_replication;
#去master1上面查看复制组状态
mysql> select * from performance_schema.replication_group_members;
#master2上可以看到数据已经同步
mysql> select * from test.t1;

将 master3 加入集群

  • 修改配置
#master3上
vim /etc/my.cnf
server_id=62  #注意服务id不一样
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW
 
plugin_load_add='group_replication.so'
transaction_write_set_extraction=XXHASH64
group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"
group_replication_start_on_boot=off
group_replication_local_address="xianchaomaster3:33062"
group_replication_group_seeds="xianchaomaster1:33063, xianchaomaster2:33064, xianchaomaster3:33062"
group_replication_bootstrap_group=off
 
systemctl restart mysqld
  • 用户授权
#用户授权
mysql -u root -p123456
mysql> set SQL_LOG_BIN=0;   #停掉日志记录
mysql> grant replication slave on *.* to repl@'192.168.40.%' identified by '123456';
mysql> grant replication slave on *.* to repl@'%' identified by '123456';
mysql> flush privileges;
mysql> set SQL_LOG_BIN=1;  #开启日志记录
mysql> change master to master_user='repl',master_password='123456'  for channel 'group_replication_recovery';  #构建group replication集群
  • 添加到复制组
#把实例添加到之前的复制组
# 加入前确认数据与 GTID 集合兼容,不绕过不相交 GTID 检查。
mysql> start group_replication;
 
#在xianchaomaster1上查看复制组状态
mysql> select * from performance_schema.replication_group_members;

测试集群读写

#xianchaomaster1查看集群参数设置列表:
mysql> show variables like 'group_replication%';
#显示与组复制(Group Replication)相关的系统变量的信息。
 
#查看xianchaomaster1是否只读,发现xianchaomaster1 master,可读可写。
mysql> show variables like '%read_only%';
#另外两台查看,发现xianchaomaster2和xianchaomaster3,是只读的
mysql>  show variables like '%read_only%';

切换为多主模式

由单主模式修改为多主模式

MySQL 5.7 的组模式配置必须在所有成员上保持一致。切换前暂停客户端写入,停止全部成员的组复制,再修改模式;重新引导时应选择事务集最新的成员,不能仅凭原主节点身份判断。操作步骤见 MySQL 5.7 组模式说明与重新启动复制组。

  1. 在三个成员上分别执行 STOP GROUP_REPLICATION;,确认全部成员都已停止组复制。

  2. 在三个成员上分别设置相同的模式参数:

    SET GLOBAL group_replication_single_primary_mode = OFF;
    SET GLOBAL group_replication_enforce_update_everywhere_checks = ON;
  3. 比较各成员已执行及已认证的事务,选择事务集最新的成员引导复制组。以下命令仅在选定成员上执行:

    SET GLOBAL group_replication_bootstrap_group = ON;
    START GROUP_REPLICATION;
    SET GLOBAL group_replication_bootstrap_group = OFF;
  4. 在另外两个成员上分别执行 START GROUP_REPLICATION;,然后检查成员状态和只读设置:

    SELECT * FROM performance_schema.replication_group_members;
    SHOW VARIABLES LIKE '%read_only%';

不要在其他成员仍运行组复制时单独引导新组,也不要长期保持 group_replication_bootstrap_group=ON。

测试集群读写

#查看组复制成员
mysql> select * from performance_schema.replication_group_members;
#测试 Multi-primary多主模式实现多节点同时读写
#xianchaomaster1上执行
mysql> insert into test.t1 values (2,'aa');
#xianchaomaster2上执行:
mysql> insert into test.t1 values (3,'cc');
#xianchaomaster3上执行: 
mysql> insert into test.t1 values (6,'cc');
mysql> select * from test.t1;

测试节点故障

三成员组需要多数派(至少 2 个成员)才能继续处理写入。依次停止一个成员并确认剩余两台仍在线;再停止第二个成员时,剩余单节点不能继续写入。恢复成员后,先检查事务状态和组成员状态,再重新加入复制组。

# 在 master1 停止 MySQL,随后从 master2 或 master3 检查组状态与写入。
systemctl stop mysqld
 
# 如继续在 master3 停止 MySQL,master2 将失去多数派;此时不要期待 INSERT 成功。
systemctl stop mysqld
SELECT * FROM performance_schema.replication_group_members;
-- 成员恢复后,在恢复的实例上检查 GTID 和数据状态,再执行:
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;

如果全部成员都已离组,应按 MySQL 官方的 重新启动复制组流程确认最新事务集后再引导,不应盲目从固定节点启动。


使用 Nginx 和 Keepalived 提供访问入口

安装nginx主备

#master1\2上安装nginx
yum install epel-release -y
yum install nginx-mod-stream -y
yum install nginx keepalived -y
#主备修改配置文件
tee /etc/nginx/nginx.conf <<'EOF'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
 
include /usr/share/nginx/modules/*.conf;
 
events {
    worker_connections 1024;
}
 
# 四层负载均衡,将 MySQL 连接转发到三个 MGR 成员
stream {
 
    log_format  main  '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
 
    access_log  /var/log/nginx/mysql-access.log  main;
 
    upstream mysql-server {
       server 192.168.40.100:3306 weight=5 max_fails=3 fail_timeout=30s; 
       server 192.168.40.101:3306 weight=5 max_fails=3 fail_timeout=30s;   
       server 192.168.40.102:3306 weight=5 max_fails=3 fail_timeout=30s;  
    }
    
    server {
       listen 13306; # 由于nginx与master节点复用,这个监听端口不能是3306,否则会冲突
       proxy_pass mysql-server;
    }
}
 
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log  /var/log/nginx/access.log  main;
 
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
 
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
 
    server {
        listen       80 default_server;
        server_name  _;
 
        location / {
        }
    }
}
EOF

keepalived配置

#master1主keepalived
tee /etc/keepalived/keepalived.conf <<'EOF'
global_defs { 
   notification_email { 
     acassen@firewall.loc 
     failover@firewall.loc 
     sysadmin@firewall.loc 
   } 
   notification_email_from Alexandre.Cassen@firewall.loc  
   smtp_server 127.0.0.1 
   smtp_connect_timeout 30 
   router_id NGINX_MASTER
} 
 
vrrp_script check_nginx {
    script "/etc/keepalived/check_nginx.sh"
}
 
vrrp_instance VI_1 { 
    state MASTER 
    interface ens33  # 修改为实际网卡名
    virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的 
    priority 100    # 优先级,备服务器设置 90 
    advert_int 1    # 指定VRRP 心跳包通告间隔时间,默认1秒 
    authentication { 
        auth_type PASS      
        auth_pass 1111 
    }  
    # 虚拟IP
    virtual_ipaddress { 
        192.168.40.199/24
    } 
    track_script {
        check_nginx
    } 
}
EOF
#vrrp_script:指定检查nginx工作状态脚本(脚本返回状态码(0为工作正常,非0不正常)判断是否故障转移。)
#master2备keepalived
tee /etc/keepalived/keepalived.conf <<'EOF' 
global_defs { 
   notification_email { 
     acassen@firewall.loc 
     failover@firewall.loc 
     sysadmin@firewall.loc 
   } 
   notification_email_from Alexandre.Cassen@firewall.loc  
   smtp_server 127.0.0.1 
   smtp_connect_timeout 30 
   router_id NGINX_BACKUP
} 
 
vrrp_script check_nginx {
    script "/etc/keepalived/check_nginx.sh"
}
 
vrrp_instance VI_1 { 
    state BACKUP 
    interface ens33
    virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的 
    priority 90
    advert_int 1
    authentication { 
        auth_type PASS      
        auth_pass 1111 
    }  
    virtual_ipaddress { 
        192.168.40.199/24
    } 
    track_script {
        check_nginx
    } 
}
EOF
#主备添加判断nginx存活的脚本
tee /etc/keepalived/check_nginx.sh <<'EOF' 
#!/bin/bash
#1、判断Nginx是否存活
counter=`ps -C nginx --no-header | wc -l`
if [ $counter -eq 0 ]; then
    #2、如果不存活则尝试启动Nginx
    service nginx start
    sleep 2
    #3、等待2秒后再次获取一次Nginx状态
    counter=`ps -C nginx --no-header | wc -l`
    #4、再次进行判断,如Nginx还不存活则停止Keepalived,让地址进行漂移
    if [ $counter -eq 0 ]; then
        service  keepalived stop
    fi
fi 
EOF
chmod +x /etc/keepalived/check_nginx.sh

启动服务

#主备
systemctl daemon-reload
systemctl enable nginx keepalived
systemctl start nginx
systemctl start keepalived
#测试通过VIP访问mysql
mysql -uroot -h192.168.40.199 -P13306 -p
#输入密码:123456可以访问MySQL。
# 三成员 MGR 需要多数派;任意两个 MySQL 成员停止后,剩余成员不能继续写入。

相关笔记