一.规划
IP、操作系统、主机名、角色、软件包版本、安装方式
【node1】
ip地址:10.10.1.211
OS:CentOS 7.6
主机名:vl7bjsqltest01
角色:master
MySQL版本:5.7.28
安装方式:通用二进制包
【node2】
ip地址:10.10.1.212
OS:CentOS 7.6
主机名:vl7bjsqltest02
角色:slave1
MySQL版本:5.7.28
安装方式:通用二进制包
【node3】
ip地址:10.10.1.213
OS:CentOS 7.6
主机名:vl7bjsqltest03
角色:slave2
MySQL版本:5.7.28
安装方式:通用二进制包
【node4】
ip地址:10.10.1.214
OS:CentOS 7.6
主机名:vl7bjsqltest04
角色:ProxySQL
Proxy版本:1.4.16
安装方式:rpm
二.MySQL节点基础环境准备
1.配置主机名
编辑四个主机名和ip映射关系
vim /etc/hosts
修改主机名
vim /etc/sysconfig/network
2.清理历史环境
rpm -qa |grep mariadb
如我这里打印出来的信息是mariadb-libs-5.5.60-1.el7_5.x86_64
rpm -e --nodeps mariadb-libs-5.5.60-1.el7_5.x86_64
3.创建用户和目录
useradd mysql -s /sbin/nologin
id mysql
mkdir -p /app/database/
mkdir -p /data/3306/
mkdir -p /binlog/
chown -R mysql.mysql /app/ /data/ /binlog/
三.MySQL安装
上传tar.gz文件至/app/database/目录,并解压:
tar xf mysql-5.7.28-el7-x86_64.tar.gz
我们重命名为mysql
mv mysql-5.7.28-el7-x86_64/ mysql/
环境变量配置:
vim /etc/profile
添加一行:
export PATH=/app/database/mysql/bin:$PATH
生效配置:
source /etc/profile
验证:
mysql -V
初始化:
mysqld --initialize-insecure --user=mysql --basedir=/app/database/mysql --datadir=/data/3306/
基本配置文件,以master节点为例,不同节点server_id需要设置不同数字(之后还会增加MGR参数和其他参数) [mysqld] user=mysql basedir=/app/database/mysql datadir=/data/3306 server_id=1 port=3306 socket=/tmp/mysql.sock [mysql] socket=/tmp/mysql.sock EOF 准备mysql启动脚本 cd /app/database/mysql/support-files/ cp mysql.server /etc/init.d/mysqld 将脚本添加到systemd管理中 chkconfig --add mysqld 启动 systemctl start mysqld mysql -uroot -p进入,不需要输入密码 创建自己的账号 create user 'wenjie.wang' identified by'123456'; grant all privileges on *.* to 'wenjie.wang'@'%'; 更改5.7版本的root密码: update mysql.user set authentication_string = password('123456') where user='root'; 重启mysql后生效 四.MGR配置文件 master节点: [mysqld] user=mysql datadir=/data/3306 basedir=/app/database/mysql port=3306 socket=/data/3306/mysql.sock pid-file=/data/3306/mysqld.pid log-error=/data/3306/mysqlerr.log innodb_file_per_table=1 skip_name_resolve=1 slow_query_log=1 slow_query_log_file=/data/3306/mysql-slow.log long_query_time=1 symbolic-links=0 explicit_defaults_for_timestamp=1 log_bin=/binlog/mysqlbin log_bin_index=/binlog/mysql-bin.index binlog_format=row sync_binlog=1 server_id=1 gtid_mode=ON enforce_gtid_consistency=ON master_info_repository=TABLE relay_log_info_repository=TABLE binlog_checksum=NONE log_slave_updates=ON transaction_write_set_extraction=XXHASH64 loose-group_replication_group_name="03f43914-7f38-4a00-919f-f748794c04ac" loose-group_replication_start_on_boot=off loose-group_replication_local_address="10.10.1.211:33061" loose-group_replication_group_seeds="10.10.1.211:33061,10.10.1.212:33062,10.10.1.213:33063" loose-group_replication_bootstrap_group=off loose-group_replication_single_primary_mode=on loose-group_replication_enforce_update_everywhere_checks= off [mysql] socket=/data/3306/mysql.sock slave节点配置文件只需要把loose-group_replication_local_address改成对应的即可; 五.开启MGR 主节点: 创建用户 set sql_log_bin=0; grant replication slave,replication client on *.* to repl@'localhost' identified by '123456'; grant replication slave,replication client on *.* to repl@'127.0.0.1' identified by '123456'; grant replication slave,replication client on *.* to repl@'10.10.1.%' identified by '123456'; SET SQL_LOG_BIN=1; 开启分布式复制 change master to master_user='repl',master_password='123456' for channel 'group_replication_recovery'; 加载GR插件 install plugin group_replication soname 'group_replication.so'; show plugins; 启动复制程序 set global group_replication_bootstrap_group=ON; start group_replication; set global group_replication_bootstrap_group=OFF; #检测组是否创建并已加入新成员 select * from performance_schema.replication_group_members; 从节点: 创建用户 set sql_log_bin=0; grant replication slave,replication client on *.* to repl@'localhost' identified by '123456'; grant replication slave,replication client on *.* to repl@'127.0.0.1' identified by '123456'; grant replication slave,replication client on *.* to repl@'10.10.1.%' identified by '123456'; SET SQL_LOG_BIN=1; 开启分布式复制 change master to master_user='repl',master_password='123456' for channel 'group_replication_recovery'; 加载GR插件 install plugin group_replication soname 'group_replication.so'; show plugins; 启动复制程序 start group_replication; #检测组是否创建并已加入新成员 select * from performance_schema.replication_group_members; #查看主节点UUID,并结合上一条语句的打印结果来判断(8.0之后上面一条语句就够了) SHOW STATUS LIKE 'group_replication_primary_member'; 六.MGR同步验证 主节点创建测试数据: create database wwj; use wwj; create table tb(id int unsignedauto_increment primary key not null,age int not null); insert into tb(age) values(35),(40); 从节点检查: select * from wwj.tb; 正常同步; 七.主节点宕机测试 宕机前 select * from performance_schema.replication_group_members; show status like‘group_replication_primary_member’; 查看当前谁是master 根据当前master的uuid和上面打印结果对比,可得知当前master的主机名 这时候我们停止主节点服务 然后到从节点查看当前master的uuid,果然变了: 再查看复制组: 当前02节点为主 此时重新开启主节点服务,然后重新加入组: change master tomaster_user='repl',master_password='123456' for channel'group_replication_recovery'; start group_replication; 重新加入组成功,之后检查主节点就是之前的02节点。 正式环境很难这样直接加入,很可能slave执行的事务gtid与master不一致,因此就需要停机时间将宕机节点重新同步。如果直接加入的话,后面可以通过查看一张表记录来判断落后多少事务。 select * from sys.gr_member_routing_candidate_status; 这个是由ProxySQL需要的脚本创建的,在全部部署完成后才可使用。 八.安装ProxySQL 在node4上 安装依赖: yum -y install perl.x86_64 yum install -y libaio.x86_64 yum -y install net-tools.x86_64 yum install perl-DBD-MySQL -y 官网下载rpm https://www.percona.com/downloads/proxysql/ 我这里是proxysql-1.4.16-1.1.el7.x86_64.rpm rpm -ivh proxysql-1.4.16-1.1.el7.x86_64.rpm 启动 systemctl start proxysql netstat -anlp | grep proxysql 6032是ProxySQL的管理端口号,6033是对外服务的端口号 proxysql --help 然后按正常方法在本机二进制安装mysql 九.ProxySQL配置用户和服务器 ProxySQL管理用的用户名和密码都是默认的admin mysql -uadmin -p -h127.0.0.1 -P6032 --prompt='proxysql> ' master节点创建ProxySQL的监控用户monitor和对外访问用户proxysql,并赋予权限: mysql> create user 'monitor'@'%' identified by '123456'; mysql> grant all on *.* to 'monitor'@'%'; mysql> create user 'proxysql'@'%' identified by '123456'; mysql> grant all on *.* to 'proxysql'@'%'; mysql> flush privileges; 在proxysql节点添加主从服务器列表: proxysql> select * from mysql_servers; 当前是空值 proxysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(10,'10.10.1.212',3306,1,'master'),(10,'10.10.1.211',3306,1,'slave1'),(10,'10.10.1.213',3306,3,'slave2'); proxysql> load mysql servers to runtime; proxysql> save mysql servers to disk; proxysql> select * from mysql_servers; 备注: (1)表mysql_servers:后端可以连接MySQL主机的列表 (2)所有节点都是ONLINE状态 (3)slave2节点的查询权重调整为3,为了让更多的读请求路由到这台配置更好的主机上 (4)表mysql_servers常用字段说明,参考: https://blog.51cto.com/qiuyue/2413300 配置和注册监控用户monitor,并验证监控信息: proxysql> set mysql-monitor_username='monitor'; proxysql> set mysql-monitor_password='123456'; proxysql> load mysql variables to runtime; proxysql> save mysql variables to disk; proxysql> select * from global_variables where variable_name in ('mysql-monitor_username','mysql-monitor_password'); select * from monitor.mysql_server_connect_log order by time_start_us desc limit 6; select * from monitor.mysql_server_ping_log order by time_start_us desc limit 6; 配置ProxySQL主从分组信息: 查看表中的字段可使用命令proxysql> show create table mysql_replication_hostgroups\G proxysql> insert into mysql_replication_hostgroups values (10,20,'proxysql'); proxysql> load mysql servers to runtime; proxysql> save mysql servers to disk; proxysql> select * from mysql_replication_hostgroups; 可看到读写组的id proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers; 此时hostgroup_id会按照我们设置的显示 此时再select * from mysql_servers;发现hostgroup_id也按照我们设置的改变 备注:ProxySQL会根据MySQL中read_only的取值将主机进行分组,read_only=0的master节点被分配到编号为10的写入组,而read_only=1的两个slave节点则被分配到编号为20的读取组 配置对外访问用户proxysql: proxysql> insert into mysql_users(username,password,default_hostgroup) values('proxysql','123456',10); proxysql> load mysql users to runtime; proxysql> save mysql users to disk; proxysql> select * from mysql_users\G 区别于之前的mysql-monitor_username的查看方式 我们随便进入主节点或从节点 mysql -uproxysql -p -h10.10.1.214 -P6033 -e 'select @@hostname;' 最后打印的结果都是主节点主机名vl7bjsqltest02,即此时的master 十.配置路由规则 proxysql> insert into mysql_query_rules(active,match_pattern,destination_hostgroup,apply) values(1,'^select.*for update$',10,1),(1,'^select',20,1); proxysql> load mysql query rules to runtime; proxysql> save mysql query rules to disk; proxysql> select rule_id,active,match_pattern,destination_hostgroup,apply from mysql_query_rules; 十一.读写分离测试 清空stats_mysql_query_digest表: # mysql -uadmin -p -h127.0.0.1 -P6032 --prompt='proxysql> ' proxysql> select * from stats_mysql_query_digest_reset; proxysql> select * from stats_mysql_query_digest; 表stats_mysql_query_digest:SQL的执行次数、时间消耗等 # mysql -uproxysql -p -h10.10.1.214 -P6033 mysql> select * from wwj.tb; mysql> insert into wwj.tb(age) values(0),(100); mysql> select * from wwj.tb for update; 再来看stats_mysql_query_digest表中记录 十二.查询的负载均衡测试 # for i in {1..12}; do mysql -uproxysql -p123456 -h10.10.1.214 -P6033 -e 'select @@hostname' -s -N; done 选项说明: (1)-s:以制表符作为分隔符打印结果 (2)-N:结果中不包含列名 上述命令执行结果可得出读请求在两台slave节点间切换,且vl7bjsqltest03和vl7bjsqltest01的出现比例接近1:1不符合配置的1:3的权重 有待后续考量 十三.故障转移测试 单主模型脚本gr_sw_mode_checker.sh, 下载地址https://github.com/ZzzCrazyPig/proxysql_groupreplication_checker 或直接查看 https://github.com/ZzzCrazyPig/proxysql_groupreplication_checker/blob/master/gr_sw_mode_checker.sh 将下载的脚本gr_sw_mode_checker.sh放置至/var/lib/proxysql目录中,并赋予执行权限和修改属主属组: # chmod +x /var/lib/proxysql/gr_sw_mode_checker.sh # chown proxysql.proxysql /var/lib/proxysql/gr_sw_mode_checker.sh 下载addition_to_sys.sql, 下载地址https://github.com/lefred/mysql_gr_routing_check/ 打不开的话CSDN下载,或者查看自己 用下载的sql文件在master节点创建表sys.gr_member_routing_candidate_status:# mysql -uroot -p < /addition_to_sys.sql mysql> select * from sys.gr_member_routing_candidate_status; 主节点和从节点显示不同,见截图 主: 从: 配置scheduler: proxysql> insert into scheduler(active,interval_ms,filename,arg1,arg2,arg3,arg4) values(1,5000,'/var/lib/proxysql/gr_sw_mode_checker.sh',10,20,1,'/var/lib/proxysql/gr_sw_mode_checker.log'); proxysql> load scheduler to runtime; proxysql> save scheduler to disk; proxysql> select * from scheduler\G 问题排查可查看日志文件/var/lib/proxysql/gr_sw_mode_checker.log 查看MGR状态信息: proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers; mysql> select * from performance_schema.replication_group_members; mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id; 主从显示信息不同 主: 从: master节点模拟MySQL服务故障:# systemctl stop mysqld.service 之后10.10.1.211变成主(is_primary_mode 变成 1) 当master节点意外宕机或下线,在满足大多数节点存活的情况下,group内部发起选举,选出下一个可用的读节点,提升其为master节点。master节点选举根据group内剩余存活节点的UUID按字典升序排列,然后选择排在最前的节点作为新的master节点。 is_primary_mode的值为1说明slave1节点已经被选举为新的master节点。 mysql> select * from performance_schema.replication_group_members; mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id; mysql> select * from sys.gr_member_routing_candidate_status; 创建测试数据: mysql> insert into wwj.tb(age) values(60),(80); mysql> select * from wwj.tb; 在proxySQL节点也查找 mysql -uproxysql -p -h10.10.1.214 -P6033 mysql> select * from wwj.tb; 发现一致 十四.恢复 原master节点10.10.1.212恢复MySQL服务:# systemctl start mysqld.service 原master节点加入复制组:mysql> start group_replication; select * from performance_schema.replication_group_members; select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id; select * from sys.gr_member_routing_candidate_status; 发现事务落后(transactions_behind)已为0 再查看数据 select * from wwj.tb;发现数据已同步 经验证proxy节点上,虽然最后列表中会有4个节点信息,但是依旧能正常写入 我们看一下会不会被负载均衡分掉 for i in {1..12}; do mysql -uproxysql -p123456 -h10.10.1.214 -P6033 -e 'select @@hostname' -s -N; done 发现依旧是分摊到vl7bjsqltest03和vl7bjsqltest01上 尝试重新配置: proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers; proxysql> delete from mysql_servers where hostgroup_id = 20 and hostname = '10.10.1.211'; proxysql> load mysql servers to runtime; proxysql> save mysql servers to disk; 发现全部分摊到vl7bjsqltest03上 后来重启服务 systemctl restart proxysql 发现vl7bjsqltest03和vl7bjsqltest02大致比为3:1,符合权重
cat > /etc/my.cnf <