MySQL高可用和灾备调研

1.高可用和灾备方案概览

高可用方案的评价以组件能正常对外提供服务为主,而灾备方案的评价以数据稳定同步恢复时间尽量短为主,其他的还要求方案实现起来较简单,后期运维服务压力较小等。

当下业界比较流行的 mysql高可用灾备方案是主从复制galera,这里先对所有的方案进行简要介绍,然后详细介绍 基于主从复制这一种方案。

1.1 主从复制

在这里插入图片描述

使用双节点数据库,搭建单向或者双向的半同步复制(semi sync replication)。在 5.7以后的版本中,由于 lossless replication、logical多线程复制等一些列新特性的引入,使得 mysql原生半同步复制更加可靠。

优点:

  1. 架构比较简单,使用原生半同步复制作为数据同步的依据
  2. 双节点,没有主机宕机后的选主问题,直接切换即可
  3. 双节点,需求资源少,部署简单

缺点:

  1. 完全依赖于半同步复制,如果半同步复制退化为异步复制,数据一致性无法得到保证
  2. 需要额外考虑 haproxy、keepalived的高可用机制

1.2 MHA

在这里插入图片描述

MHA Manager会定时探测集群中的 master节点,当 master出现故障时,它可以自动将最新数据的 slave提升为新的 master,然后将所有其他的 slave重新指向新的 master,整个故障转移过程对应用程序完全透明。

优点:

  1. 可以进行故障的自动检测和转移;
  2. 可扩展性较好,可以根据需要扩展 mysql的节点数量和结构;
  3. 相比于双节点的 mysql复制,三节点/多节点的 mysql发生不可用的概率更低

缺点:

  1. 至少需要三节点,相对于双节点需要更多的资源;
  2. 逻辑较为复杂,发生故障后排查问题,定位问题更加困难;
  3. 数据一致性仍然靠原生半同步复制保证,仍然存在数据不一致的风险;
  4. 可能因为网络分区发生脑裂现象;

1.3 共享存储

在这里插入图片描述

SAN的概念是允许存储设备和处理器(服务器)之间建立直接的高速网络(与 LAN相比)连接,通过这种连接实现数据的集中式存储。

使用共享存储时,mysql服务器能够正常挂载文件系统并操作,如果主库发生宕机,备库可以挂载相同的文件系统,保证主库和备库使用相同的数据。

优点:

  1. 两节点即可,部署简单,切换逻辑简单;
  2. 很好的保证数据的强一致性;
  3. 不会因为 mysql的逻辑错误发生数据不一致的情况;

缺点:

  1. 需要考虑共享存储的高可用;
  2. 价格昂贵;

1.4 Galera

在这里插入图片描述

基于 Galera的 mysql高可用集群, 是多主数据同步的 mysql集群解决方案,使用简单,没有单点故障,可用性高。

优点:

  1. 多主写入,无延迟复制,能保证数据强一致性;
  2. 有成熟的社区,有互联网公司在大规模的使用;
  3. 自动故障转移,自动添加、剔除节点;

缺点:

  1. 需要为原生 mysql节点打 wsrep补丁
  2. 只支持 innodb储存引擎
  3. 至少三节点;

1.5 Paxos

在这里插入图片描述

Paxos 算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。这个算法被认为是同类算法中最有效的。Paxos与 mysql相结合可以实现在分布式的 mysql数据的强一致性。

优点:

  1. 多主写入,无延迟复制,能保证数据强一致性;
  2. 有成熟理论基础;
  3. 自动故障转移,自动添加、剔除节点;

缺点:

  1. 只支持 innodb储存引擎
  2. 至少三节点;

上面 5种方案只是介绍了其实现思路,并未描述实现细节,其中共享存储这种方案只适合用于做高可用,用于灾备不太合适。

下面将会详细介绍比较流行的主从复制方案的实现细节,所有步骤均在笔者的环境中验证通过,可以直接使用。

2.基于主从复制的高可用灾备方案

网上如何安装 mysql的文章非常多,这里就不做介绍了。

本方案选用的 mysq-5.7.36+ Keepalived-1.3.5。

方案架构如下(默认这两台服务器上都已安装了 mysql):

  • 主库1:192.168.5.21
  • 主库2:192.168.5.22

2.1 搭建 MySQL双主备份环境

第1步,修改主1(192.168.5.21)的 my.cnf文件

vim /etc/my.cnf

# 内容如下
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# 配置server-id 每个MySQL实例的server-id都不能相同
server-id=1
# MySQL的日志文件的名字
log-bin=mysql_master
# 作为从库时 更新操作是否写入日志 on:写入  其他数据库以此数据库做主库时才能进行同步
log-slave-updates=on

# MySQL系统库的数据不需要同步 我们这里写了3个  更加保险
# 同步数据时忽略一下数据库 但是必须在使用use db的情况下才会忽略;如果没有使用use db 比如create user  数据还是会同步的
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
replicate-ignore-db=sys
# 使用通配符忽略MySQL系统库的表  这样在create user时也不会进行同步了
replicate_wild_ignore_table=information_schema.%
replicate_wild_ignore_table=mysql.%
replicate_wild_ignore_table=performance_schema.%
replicate_wild_ignore_table=sys.%
# MySQL系统库的日志不计入binlog 这样更加保险了
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys

第2步,修改主2(192.168.5.22)的 my.cnf文件

# 把主1上的配置文件复制到主2
scp /etc/my.cnf 192.168.5.12:/etc

# 然后修改下面两个配置即可
# 配置server-id=2
server-id=2
# MySQL的日志文件的名字,这里主要为了区分
log-bin=mysql_slave

第3步,重启MySQL服务并开放防火墙 3306端口

systemctl restart mysqld

firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --reload

第4步,配置主从

A.主(192.168.5.21),从(192.168.5.22):

先在主1(192.168.5.21)上执行下面的命令:

mysql -uroot -pqwer2022

CREATE USER 'repl_master'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'abcd2022';
GRANT REPLICATION SLAVE ON *.* TO 'repl_master'@'%';
FLUSH PRIVILEGES;

# 查看主节点状态
SHOW MASTER STATUS;
+---------------------+----------+--------------+-------------------------------------------------+-------------------+
| File                | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+---------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql_master.000001 |      761 |              | information_schema,mysql,performance_schema,sys |                   |
+---------------------+----------+--------------+-------------------------------------------------+-------------------+

这里看到 binlog的文件名称(mysql_master.000001)和位置(761),接下来在主2(192.168.5.22)上进行操作:

mysql -uroot -pqwer2022

CHANGE MASTER TO MASTER_HOST='192.168.5.11',MASTER_PORT=3306,MASTER_USER='repl_master',MASTER_PASSWORD='abcd2022',MASTER_LOG_FILE='mysql_master.000001',MASTER_LOG_POS=761;
START SLAVE;

# 查看从库的状态,这里可以看下结果里面有没有异常
SHOW SLAVE STATUS;

B.主(192.168.5.22),从(192.168.5.21):

先在主2(192.168.5.22)上执行下面的命令:

mysql -uroot -pqwer2022

CREATE USER 'repl_slave'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'abcd2022';
GRANT REPLICATION SLAVE ON *.* TO 'repl_slave'@'%';
FLUSH PRIVILEGES;

# 查看主节点状态
SHOW MASTER STATUS;
+---------------------+----------+--------------+-------------------------------------------------+-------------------+
| File                | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+---------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql_slave.000001 |      759 |              | information_schema,mysql,performance_schema,sys |                   |
+---------------------+----------+--------------+-------------------------------------------------+-------------------+

这里看到 binlog的文件名称(mysql_slave.000001)和位置(759),接下来在主1(192.168.5.21)上进行操作:

mysql -uroot -pqwer2022

CHANGE MASTER TO MASTER_HOST='192.168.5.12',MASTER_PORT=3306,MASTER_USER='repl_slave',MASTER_PASSWORD='abcd2022',MASTER_LOG_FILE='mysql_slave.000001',MASTER_LOG_POS=759;
START SLAVE;

# 查看从库的状态,这里可以看下结果里面有没有异常
SHOW SLAVE STATUS;

第5步,验证

在主1(192.168.5.21)上创建一个数据库,然后在主2(192.168.5.22)看是否同步过来,正常同步则成功,反之失败。

2.2 安装配置 Keepalived

注意:一定要确保 SELinux已关闭

第1步,安装 mysql-community-libs-compat

rpm -ivh mysql-community-libs-compat-5.7.36-1.el7.x86_64.rpm

第2步,安装 Keepalived

yum install keepalived,psmisc -y

第3步,配置 Keepalived

A.编辑主1(192.168.5.21)上的配置文件

vim /etc/keepalived/keepalived.conf

# 内容如下
! Configuration File for keepalived

global_defs {
    
    
   notification_email {
    
    
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   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
   script_user root
   enable_script_security
}

vrrp_script chk_mysql {
    
    
    # 用于检测 mysql进程是否存在
    script "/usr/bin/killall -0 mysqld"
    interval 3
    fall 2
}

vrrp_instance VI_1 {
    
    
    state MASTER
    interface ens192 # 【注意】这个网卡 ens192请用 ip addr中的实际值
    virtual_router_id 51
    priority 101
    advert_int 1
    authentication {
    
    
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
    
    
        192.168.5.198 # 【注意】这是一个虚拟IP,需要跟主机在同一个 IP段,且没有被别的机器使用
    }

    track_script {
    
    
        chk_mysql
    }
}

B.编辑主2(192.168.5.22)上的配置文件

把主1上修改过的配置文件复制到主2,然后修改下面几个配置项即可:

state BACKUP
interface ens192
# 数值越大优先级越高,从节点的数值要小于主节点的
priority 99

第4步,启动 Keepalived

systemctl start keepalived
# 查看虚拟IP是否已生效
ip addr
# 能看到这个 inet 192.168.5.198/32 scope global ens192即为正常

第5步,验证

使用一个 mysql的远程连接工具通过虚拟 IP(192.168.5.198)来连接 mysql,当关闭其中一个 mysql服务时,远程连接工具依旧能正常访问到 mysql服务即为正确。

3.总结

mysql 使用主从复制这种方案来实现高可用和灾备,操作简单且运行稳定,后期的运维压力也较小,应对普通的高可用或者灾备场景足矣。对于 Galera这种方案,适合于比较大规模的集群场景,且具有专业的运维人员参与才行。

猜你喜欢

转载自blog.csdn.net/Daphnisz/article/details/124570176