基于keepalived+MySQLrouter+Gtid半同步复制的MySQL集群
零、项目概要
本项目旨在搭建一个数据库集群,利用半同步操作和Gtid两种方法实现主从复制,利用主从复制保持数据的一致性,并开启数据备份功能,将数据丢失成本降低。利用MySQLrouter中间件实现对用户的鉴权与隔离,并使用keepalived配置2个vrrp实例实现双vip的高可用功能。
单击进入支持文档和问题解释
一、准备工作
0.ip分配
1.修改主机名(参照机器名表,每台机器都需要修改)
hostnamectl sethostname [机器名]
su
2.关闭NetworkManger(每台机器都需要关闭)
service NetworkManger stop
systemctl disable NetworkManger
3.关闭防火墙(每台机器都需要关闭)
service firewalld stop
systemctl disable firewalld
4.关闭selinux(每台机器都需要关闭)
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
5.关闭交换分区(每台机器都需要关闭)
swapoff -a
#注释swap挂载,给swap这行开头加一下注释
vim /etc/fstab
6.加载相关内核模块(每台机器都需要加载)
modprobe br_netfilter
echo "modprobe br_netfilter" >> /etc/profile
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl -p /etc/sysctl.d/k8s.conf
7.配置时间同步(每台机器都需要同步)
#安装ntpdate命令
[root@ xianchaonode1 ~]# yum install ntpdate -y
#跟网络时间做同步
[root@ xianchaonode1 ~]#ntpdate cn.pool.ntp.org
crontab -e
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org
service crond restart
配置epel源(每台机器都需要配置)
yum install epel-release -y
8.配置静态ip地址(每台机器都需要配置,注意IP地址不同!)
vim /etc/sysconfig/network-scripts/ifcfg-ens33
配置完后重启网卡
ifdown ens33
ifup ens33
service network restart
9.添加hosts解析
vim /etc/hosts
10.建立免密通道(每台机器都需要相互建立免密通道)
生成密钥
![](/qrcode.jpg)
ssh-keygen
一路回车
传输公钥
ssh-copy-id [要传送的机器]
测试登录
[root@master ~]# ssh slave1
Last login: Fri Oct 13 12:10:06 2023 from 192.168.224.1
[root@slave1 ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:fd:19:8c brd ff:ff:ff:ff:ff:ff
inet 192.168.224.147/24 brd 192.168.224.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fefd:198c/64 scope link
valid_lft forever preferred_lft forever
[root@slave1 ~]# exit
登出
Connection to slave1 closed.
[root@master ~]#
如果ssh出现问题,参照此文
二、下载配置数据库
1.下载数据库
下载mysql: 点击进入链接
我下载的是5.7.37版本,你也可以直接在linux系统里面下载
yum install wget -y
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.37-linux-glibc2.12-i686.tar.gz
解决软件的依赖关系
yum install cmake ncurses-devel gcc gcc-c++ vim lsof bzip2 openssl-devel ncurses-compat-libs -y
解压mysql二进制安装包
tar xf mysql-5.7.37-linux-glibc2.12-x86_64.tar.gz
移动mysql解压后的文件到/usr/local下改名叫mysql
mv mysql-5.7.37-linux-glibc2.12-x86_64 /usr/local/mysql
新建组和用户 mysql
groupadd mysql
mysql这个用户的shell 是/bin/false 属于mysql组
useradd -r -g mysql -s /bin/false mysql
新建存放数据的目录
mkdir /data/mysql -p
修改/data/mysql目录的权限归mysql用户和mysql组所有,这样mysql用户可以对这个文件夹进行读写了
chown mysql:mysql /data/mysql/
只是允许mysql这个用户和mysql组可以访问,其他人都不能访问
chmod 750 /data/mysql/
进入/usr/local/mysql/bin目录
cd /usr/local/mysql/bin/
2.配置数据库
初始化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进程
service mysqld start
将mysqld添加到linux系统里服务管理名单里
/sbin/chkconfig --add mysqld
设置mysqld服务开机启动
/sbin/chkconfig mysqld on
3.测试登录
初始化密码
mysql -uroot -p$tem_passwd --connect-expired-password -e "set password='Sanchuang123#';"
检验上一步修改密码是否成功,如果有输出能看到mysql里的数据库,说明成功
mysql -uroot -p'Sanchuang123#' -e "show databases;"
重新登录,以新的身份登入数据库
su
mysql -uroot p'Sanchuang123#'
三、实现mysql的半同步
1.同步数据
实现半同步之前需要使master和slave数据库的数据保持一致
从master里面导出数据
mysqldump -uroot -p'Sanchuang123#' --all-databases >all_db.SQL
将导出的数据传输到其他3台slave机器上
scp all_db.SQL slave1:/root
scp all_db.SQL slave2:/root
scp all_db.SQL slave3:/root
slave机器将数据导入到本地数据库
mysqldump -uroot -p'Sanchuang123#' --all-databases <all_db.SQL
2.配置同步
修改配置文件,开启二进制日志文件
[root@slave2 ~]# vim /etc/my.cnf
#在mysqld下面添加如下两行,注意master机器的server_id的值是1,slave机器的值分别是2,3,4
log_bin
server_id = 1
在master数据库上给一个用户授权,以便其他用户可以连接上来复制二进制日志
先登录进数据库
mysql -uroot -p'Sanchuang'
#授权
root@NO1database 10:02 mysql>grant replication slave on *.* to 'zyj'@'192.168.224.%' identified by 'Sanchuang123#';
Query OK, 0 rows affected, 1 warning (4.16 sec)
root@NO1database 10:06 mysql>
首先先确认master数据库目前的状态
在master数据库上
show master status;
在slave数据库上进行从配置
CHANGE MASTER TO MASTER_HOST='192.168.224.146' ,
MASTER_USER='zyj',
MASTER_PASSWORD='Sanchuang123#',
MASTER_PORT=3306,
MASTER_LOG_FILE='master-bin.000002',
MASTER_LOG_POS=630;
开始从进程
root@(none) 10:33 mysql>start slave;
查看开启状态
root@(none) 10:33 mysql>show slave status\G;
3.测试同步效果
在master上建立一个新的数据库
root@(none) 10:36 mysql>create database funny;
Query OK, 1 row affected (0.05 sec)
在slave数据库中也能看到funny库
查看连接情况
[root@master ~]# netstat -anplut|grep ES
root@hello 10:48 mysql>show processlist;
4.配置半同步
在master上安装配置半同步的插件
root@(none) 09:59 scmysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.31 sec)
root@(none) 09:59 scmysql>SET GLOBAL rpl_semi_sync_master_timeout = 1;
Query OK, 0 rows affected (0.00 sec)
root@(none) 09:59 scmysql>SET GLOBAL rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
root@(none) 10:00 scmysql>
永久配置,修改配置文件
[root@master ~]# vim /etc/my.cnf
[mysqld]
rpl_semi_sync_master_enabled=1 #添加
rpl_semi_sync_master_timeout=1000 # 1 second 添加
刷新mysql服务
[root@sc-master ~]# service mysqld restart
在从服务器上配置安装半同步的插件
root@(none) 10:01 mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.71 sec)
root@(none) 10:01 mysql>SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.04 sec)
root@(none) 10:01 mysql>
永久修改从服务器上的配置文件
[root@sc-slave ~]# vim /etc/my.cnf
[mysqld]
rpl_semi_sync_slave_enabled=1 #添加
刷新mysql服务
[root@sc-slave ~]# service mysqld restart
在master和slave上执行SQL查看是否激活半同步
master机器
root@(none) 10:10 scmysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME
LIKE '%semi%';
slave机器
root@(none) 10:24 scmysql>
root@(none) 11:28 mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME
LIKE '%semi%';
5.测试同步效果
现在一台从数据库上查看表,目前只有系统表
在主数据库上操作
root@(none) 10:46 mysql>create database hello;
Query OK, 1 row affected (0.00 sec)
root@(none) 10:46 mysql>use hello;
Database changed
root@hello 10:47 mysql>create table test1(id int, name varchar(20));
Query OK, 0 rows affected (0.00 sec)
root@hello 10:47 mysql>insert into test1 values(1,'张三'),(2,'李四')
-> ;
Query OK, 2 rows affected (2.07 sec)
Records: 2 Duplicates: 0 Warnings: 0
root@hello 10:48 mysql>desc test1;
root@hello 10:48 mysql>select * from test1;
root@hello 10:48 mysql>
6.开启延迟备份
在三台从服务器上操作
root@(none) 10:43 mysql>stop slave;
Query OK, 0 rows affected (0.00 sec)
root@(none) 10:51 mysql>CHANGE MASTER TO MASTER_DELAY = 10;
Query OK, 0 rows affected (0.00 sec)
root@(none) 10:51 mysql>start slave;
Query OK, 0 rows affected (0.00 sec)
root@(none) 10:51 mysql>show slave status\G;
可自行测试,在主服务器修改数据后,从服务器10s后才修改。
7.其他
关不掉数据库的话直接杀死mysql_safe和mysqld相关的进程即可(先杀safe再杀mysqld)
ps -aux|grep mysql
四、Gtid
1.清除脏配置
移除之前所有的主从信息
在master机器上的数据库中清除主机器约束及信息
reset master;
在slave机器上的数据库中清除从机器约束及信息
reset slave all;
2.搭建Gtid功能
开启Gtid功能(master和3台slave都需要配置)
[root@master ~]# vim /etc/my.cnf
在mysqld下面添加下面这几行
gtid-mode=ON
enforce-gtid-consistency=ON
log_slave_updates=ON
重新建立约束
CHANGE MASTER TO MASTER_HOST='192.168.224.146' ,
MASTER_USER='zyj',
MASTER_PASSWORD='Sanchuang123#',
MASTER_PORT=3306,
master_auto_position=1;
在从服务器上查看slave是否成功启动
root@(none) 11.00 mysql>show slave status\G;
3.测试Gtid功能
可以在主从机器上分别查看主从功能是否开启(具体参考半同步复制,一样的检验方法。也可以通过在主服务器上建表,看从服务器是否同步建表来检验)
root@(none) 11.00 mysql>show variables like "%semi_sync%";
五、中间件MySQLrouter
1.MySQLrouter中间件搭建
在两台MySQLrouter中操作
[root@routerm ~]# yum install wget -y
[root@routerm ~]# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.23-1.el7.x86_64.rpm-bundle.tar
[root@routerm ~]# rpm -ivh mysql-router-community-8.0.21-1.el7.x86_64.rpm
[root@routerm ~]# yum install net-tools -y
[root@routerm ~]# vim mysqlrouter.conf
#添加如下配置(bind_address后面接的是本机ip+端口)
[routing:slaves]
bind_address = 192.168.224.151:7001
destinations = 192.168.224.147:3306,192.168.224.148:3306
mode = read-only
connect_timeout = 1
[routing:masters]
bind_address = 192.168.224.151:7002
destinations = 192.168.224.146:3306
mode = read-write
connect_timeout = 1
2.测试监听转发效果
netstat -anplut |grep mysql
在一台独立客户机(cd2机器,注意本次实现cd2仅在此处用到)上测试访问
mysql -h 192.168.224.150 -P 7001 -uread -p'Sanchuang123#'
可以成功登录,自行测试
当使用read账号登录时,无法对数据库进行写操作
当使用write账户登录时,可以对数据库进行读写操作
六、keepalived实现
1.下载、配置
在两台数据路由服务器上下载keepalived
cd /etc/keepalived/
vim keepalived.conf
进行如下修改,在state这行,M中间件设置为MASTER,B中间件设置为BACKUP
设置完之后重启keepalived
service keepalived restart
在routerM上查看ip
发现在ens33接口出现VIP
在routerB上未发现VIP
当把routerM上的keepalived停掉之后可以发现routerM上的VIP消失,而routerB上出现了VIP,即可以实现高可用的功能,一台宕机了另一台仍然可以用。
2.双VIP配置(互为主从)
在两台中间件上分别加入V2配置,其中V2的state中,routerB配置为MASTER,routerM配置为BACKUP,虚拟地址为192.168.224.199
vrrp_instance VI_2 {
state master
interface ens33
virtual_router_id 81
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.224.199
}
}
重启keepalived服务
service keepalived restart
在routerM上查看ip,只能看到192.168.224.188这个虚拟IP
在routerB上查看ip,只能看到192.168.224.199这个虚拟IP
当把routerM上的keepalived服务关闭之后,会发现routerB上出现了192.168.224.188这个虚拟IP,而routerM上的虚拟IP消失。这样的话,就算某台服务器宕机,另外一台服务器仍然能够暂时接替它的工作。