目录:
MySQL+Keepalived主从高可用集群原理+实战
背景
随着公司业务的发展,对数据库的要求越来越高,以前的单机MySQL肯定是玩不转了,亟需升级成MySQL集群,这是一个公司在业务发展时不得不面临的问题
就单机MySQL而言,自己玩玩可以,运用到实际项目中,那肯定要挨批的。一方面数据不安全,万一数据库的电脑磁盘坏了,就坑了。另一方面数据库的并发能力是有限的,一般并发数200~500就差不多了,当然你要继续往上增,也是可以的,那就影响整体Mysql的响应时间。
那么有哪些集群方案呢?
集群方案
集群方案之前已经讨论过了,可以参考之前的【MySQL主从集群原理+实战】,今天我们来实现这种Keepalived+双主热备级联复制集群
优点:
- 读写分离,增加整体性能
- Master有故障转移(采用Keepalived实现),当Master宕机时,备用Master自动顶上去,且IP无变化(VIP)
- Master和备用Master之间采用半同步机制,最大程度上保证数据一致性
缺点:
- Master故障转移时,Slave需要用脚本手动切换,增加复杂度
- 数据存在一致性问题,因为异步,所以Slave的数据一定不是最新的,需要等待一个时间窗后才能读取
- Slave过多时Slave对Master的负载以及网络带宽都会成为一个严重的问题
Keepalived双主热备级联复制集群
m1和m2作为双主,互为主从且同步方式为半同步,为什么呢?因为这样在Master主机宕机恢复,对Master备机写入的数据也能重新同步到Master主,此时的主备角色正好颠倒过来,所以要设置互为主从且半同步。
m3作为级联复制的中间节点,新增加m4和m5作为新的Slave,正常情况下架构如下
[图片上传失败…(image-2ebe09-1618044537000)]
当发生故障时,VIP自动漂移到Master备机上面,且通过Keepalived的状态脚本自动切换Slave,即m3到Master备机上,当Master主机(m1)恢复时,VIP又会自动漂移到m1上并且m3也会自动切换到m1上!
Keepalived状态切换脚本需要ssh和mysql免密登录的支持,其原理就是m1或者m2检测到自己成为Master角色时,通过ssh登录到m3上执行MySQL的切换命令
环境准备
docker run -dit --name m1 --privileged mysql5.7.24 /usr/sbin/init
docker run -dit --name m2 --privileged mysql5.7.24 /usr/sbin/init
docker run -dit --name m3 --privileged mysql5.7.24 /usr/sbin/init
docker run -dit --name m4 --privileged mysql5.7.24 /usr/sbin/init
docker run -dit --name m5 --privileged mysql5.7.24 /usr/sbin/init
各个IP如下:
VIP 172.17.0.101
m1 172.17.0.10
m2 172.17.0.11
m3 172.17.0.15
m4 172.17.0.16
m5 172.17.0.17
MYSQL_HOME变量定义,每台都定义下,后面的命令都依赖MYSQL_HOME
# 定义变量
MYSQL_VERSION=5.7.24
MYSQL_HOME=/usr/local/mysql-$MYSQL_VERSION
需要注意的是每台上要重置一下server_uuid,否则后面的主从复制会出错,直接删掉auto.cnf让MySQL自动生成即可
rm -rf $MYSQL_HOME/data/auto.cnf
由于是在docker里面,可能没有ssh,每台都装上ssh服务,后面的从机自动切换需要用到
yum install -y openssh-server openssh-clients passwd
双主配置
重置配置
如果哪个步骤出问题了,需要重新来,可以通过下面的方法重置
- 删除所有的库,分开执行
mysql -uroot -p -e "show databases" | grep -vE 'mysql|information_schema|performance_schema|test|sys|Database' | awk '{ print "drop database "$1";" }' > drop.sql && cat drop.sql
mysql -uroot -p < drop.sql
- 重置Slave
STOP SLAVE;
RESET SLAVE;
- 重置Master,binlog将会重新开始
STOP MASTER;
Master主机
# 先用-15优雅杀掉进程
ps aux | grep -v grep | grep mysql | awk '{ print $2 }' | xargs kill -15
sleep 1
# 修改配置
cat > /etc/my.cnf <<EOF
[client]
user=root
password=root
[mysqld]
user=mysql
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
datadir=$MYSQL_HOME/data
log-bin=mysql-bin-master
expire_logs_days=5
server-id=1
log-slave-updates=1
plugin-load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl-semi-sync-master-enabled=1
rpl-semi-sync-slave-enabled=1
[mysqld_safe]
log-error=$MYSQL_HOME/logs/mysqld.log
pid-file=$MYSQL_HOME/pids/mysqld.pid
[client]
default-character-set=utf8mb4
EOF
# 启动
/etc/init.d/mysqld start
# 查看启动日志
tail -f $MYSQL_HOME/logs/mysqld.log
- log-slave-updates=1:这个参数需要注意下,互为主从的时候两台都需要写入自己从对方取到的数据到binlog里面
- plugin-load = “rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so” rpl-semi-sync-master-enabled=1 rpl-semi-sync-slave-enabled=1主从半同步都需开启,因为是互为主从
- [client]:需要注意下,配置了可以免密执行SQL,方便后面实现自动切换从机脚本!
执行完毕后登陆MySQL创建同步用户
DROP USER 'repl'@'%' ;
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
flush privileges;
看一下Master状态
SHOW MASTER STATUS;
+-------------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------------+----------+--------------+------------------+-------------------+
| mysql-bin-master.000001 | 154 | | | |
+-------------------------+----------+--------------+------------------+-------------------+
Master备机
# 先用-15优雅杀掉进程
ps aux | grep -v grep | grep mysql | awk '{ print $2 }' | xargs kill -15
sleep 1
# 修改配置
cat > /etc/my.cnf <<EOF
[client]
user=root
password=root
[mysqld]
user=mysql
character-set-server&