个人博客,记录知识防止遗忘
mysql 双主+keepalived +1从
mysql 双主+keepalived +1从

mysql 双主+keepalived +1从

内容大纲

1    架构

1.1    架构图

clipboard.png

1.2    大概的搭建过程:

注: 主从复制要采用gtid模式,需要以下条件
① 101和102搭建mysql双主
② 101和102搭建keepalived, 设定虚拟ip 100,
设置角色为backup,关闭抢占,关联mysql端口检测脚本;
优先启动101上的mysql和keepalived,使得vip落在101上
③ 103作为slave,将对应的主设定为100即可,gtid模式不需要指定bin-log文件名和偏移;

1.3    架构缺点:

①每增加1个mysql从,都会增大mysql主的负担,
②101宕机后,vip会通过keepalived漂移至102, 但是期间有几秒钟会中断业务
③101和102是主备关系,同时只能有一台机器参与工作

2    搭建过程

2.1    准备(本文以centos7为例)

下载 mariadb yum源
https://downloads.mariadb.org/mariadb/repositories/#distro=CentOS&distro_release=centos7-amd64–centos7&mirror=tuna&version=10.5

repo配好后,通过yum安装

yum install -y mariadb-server

mysql安全初始化

mysql_secure_installation

进入mysql,创建同步账户,赋予相应权限

drop user 'data_sync'@'10.4.7.%' 
create user 'data_sync'@'10.4.7.%' identified by '123456';
grant replication slave on *.* to 'data_sync'@'10.4.7.%';
flush privileges;
show master status;

2.2    mysql双主

mariadb10.0以后默认启用gtid,无需手动开启;但是mysql需要使用命令手动指定

2.2.1    配置文件:

完整配置(仅写101),103配置仅需指明自身server-id

[root@localhost ~]# cat /etc/my.cnf.d/server.cnf
[mysqld]
server-id=101
log_bin=binlog-mariadb         # bin-log文件名
binlog_format = row            # 行模式复制
auto-increment-offset = 1      # 自增id的起始值,102改成2
auto-increment-increment = 2   # 自增id的步长
log-slave-updates              # 开启级联复制,自身成为中继节点

2.2.2    各mysql中指明复制方向

101/102 如下2项为Yes,则表示正常,
103需要等到keepalived启动后才会显示正常
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

# 101上配置
mysql -e "
change master to master_host='10.4.7.102',
  MASTER_PORT = 3306,
  master_user='data_sync',
  master_password='123456',
  master_use_gtid=current_pos;
start slave;
show slave status \G"

# 102上配置
mysql -e "
change master to master_host='10.4.7.101',
  MASTER_PORT = 3306,
  master_user='data_sync',
  master_password='123456',
  master_use_gtid=current_pos;
start slave;
show slave status \G"

# 103上配置
mysql -e "
change master to master_host='10.4.7.100',
  MASTER_PORT = 3306,
  master_user='data_sync',
  master_password='123456',
  master_use_gtid=current_pos;
start slave;
show slave status \G"

2.3    keepalived 相关:

2.3.1    主的配置(10.4.7.101)

其实角色都配置为backup后,优先级就失去了作用
再配置 nopreempt 后,就没有主备的概念了 (本来就只有2台,谁先启动谁就是主)

[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

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 101

   vrrp_skip_check_adv_addr
   # vrrp_strict                   # 开启后vrrp将会以组播方式发布报文,此时不用配置unicast地址
                   # 但是组播方式每次生成虚拟ip时,都会自动添加一条iptables规则,导致虚拟ip不可访问
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script chk_mysql_port {     #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
    script "/opt/chk_mysql.sh"   #这里通过脚本监测
    interval 2                   #脚本执行间隔,每2s检测一次
    weight -20                    #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
    fall 2                    #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
    rise 1                    #检测1次成功就算成功。但不修改优先级
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens32
    virtual_router_id 121
    priority 110
    advert_int 1
    nopreempt               # 非抢占模式
    authentication {
        auth_type PASS
        auth_pass 1211
    }
    virtual_ipaddress {
        10.4.7.100/24 dev ens32 label ens32:1
    }

    unicast_src_ip 10.4.7.101          # 本机IP地址
    unicast_peer {                     # 对端IP地址,若有多个节点可设多个ip
        10.4.7.102                     # 上述2行配置意味着各节点间会采用单播交换心跳信息
    }                      # 若要采用组播,则取消注释 vrrp_strict ,并删除上述2行;
                     #  组播方式每次生成虚拟ip时,都会添加一条iptables,导致虚拟ip不可访问

    track_script {
     chk_mysql_port
    }
}

2.3.2    备的配置(10.4.7.102)

其实角色都配置为backup后,优先级就失去了作用
再配置 nopreempt 后,就没有主备的概念了 (本来就只有2台,谁先启动谁就是主)

[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

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 102

   vrrp_skip_check_adv_addr
   # vrrp_strict                   # 开启后vrrp将会以组播方式发布报文,此时不用配置unicast地址
                                   # 但是组播方式每次生成虚拟ip时,都会自动添加一条iptables规则,导致虚拟ip不可访问
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script chk_mysql_port {     #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
    script "/opt/chk_mysql.sh"   #这里通过脚本监测
    interval 2                   #脚本执行间隔,每2s检测一次
    weight -10                    #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
    fall 2                    #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
    rise 1                    #检测1次成功就算成功。但不修改优先级
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens32
    virtual_router_id 121
    priority 100
    advert_int 1
    nopreempt               # 非抢占模式
    authentication {
        auth_type PASS
        auth_pass 1211
    }
    virtual_ipaddress {
        10.4.7.100
    }

    unicast_src_ip 10.4.7.102          # 本机IP地址
    unicast_peer {                     # 对端IP地址,若有多个节点可设多个ip
        10.4.7.101                     # 上述2行配置意味着各节点间会采用单播交换心跳信息
    }                                  # 若要采用组播,则取消注释 vrrp_strict ,并删除上述2行; 
                                         #  组播方式每次生成虚拟ip时,都会添加一条iptables,导致虚拟ip不可访问

    track_script {
     chk_mysql_port
    }
}

2.3.3    检测mysql端口的脚本(需授予执行权限)

[root@localhost ~]# cat /opt/chk_mysql.sh 
#!/bin/bash
counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
if [ "${counter}" -eq 0 ]; then
    systemctl  stop keepalived
fi  
chmod +x  /opt/chk_mysql.sh 

3    验证:

首先需要持续 查询/写入 mysql,
在此期间手动kill 101上的 mysql进程, 同时观察是否能切换,以及切换用时

① 持续查询/写入mysql

此处用root用户密码进行操作

# 插入数据命令
for ((i=1;i<=10000;i++));do \
  mysql -u data_sync -p123456  -h 10.4.7.100 -e "insert into test.test (dest_number) values ($i)" 2>&1 > /dev/null  \
    && echo "date "+%Y-%m-%d %H:%M:%S" 第$i次插入正常" ;
done

# 查询数据命令
for ((i=1;i<=10000000;i++)); do \
  mysql -u data_sync -p123456  -h 10.4.7.103 -e "select * from test.test" 2>&1 >/dev/null \
    && echo "date "+%Y-%m-%d %H:%M:%S" 第$i次查询正常" ;
done

② 手动kill 101的mysql

发现虚拟ip成功切换至102上,证明可以实现热备
clipboard.png
期间使用tcpdump抓包, 并通过wireshark打开查看, 发现
正常情况下是101主动通告vrrp心跳信息给102;
当101上的mysql服务被手动kill后,101keepalivrd触发脚本,随即"自杀";
102上的keepalivrd开始接管, 主动通告vrrp心跳信息给101, 说明keepalivrd已完成切换
clipboard2.png

③ 查看切换间隔时间

业务等待大概3秒左右
clipboard3.png

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注