MySQL高可用之双主实现

    技术2022-07-13  76

    MySQL的高可用方案有很多种,双主、MHA、MMM等等,这里只是写下最简单的双主这种高可用方案。

    一、配置MySQL互为主从

    1、环境准备

    系统IP主机名服务Centos 7.5192.168.100.2mysql1MySQL+keepalivedCentos 7.5192.168.100.3mysql2MySQL+keepalived

    2、开启二进制日志及中继日志

    #主机mysql1配置文件如下: [root@mysql1 ~]# cat /etc/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data port=3306 server_id=1 #server_id必须唯一 socket=/usr/local/mysql/mysql.sock log-error=/usr/local/mysql/data/mysqld.err log-bin=/usr/local/mysql/data/log_bin #指定二进制日志文件 relay-log=/usr/local/mysql/data/relay-bin #指定中继日志 relay-log-index=relay-bin.index auto_increment_increment=2 auto_increment_offset=1 #主机mysql2配置文件如下: [root@mysql2 ~]# cat /etc/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data port=3306 server_id=2 socket=/usr/local/mysql/mysql.sock log-error=/usr/local/mysql/data/mysqld.err log-bin=/usr/local/mysql/data/log_bin relay-log=/usr/local/mysql/data/relay-bin relay-log-index=relay-bin.index auto_increment_increment=2 auto_increment_offset=2

    注:mysql1和mysql2只有server-id和auto_increment_offset不同

    mysql中有自增长字段,在做数据库的主主同步时需要设置自增长的两个相关配置:auto_increment_offset和auto_increment_increment。 auto-increment-increment表示自增长字段每次递增的量,其默认值是1。它的值应设为整个结构中服务器的总数,我这里用到两台服务器,所以值设为2。 auto-increment-offset是用来设定数据库中自动增长的起点(即初始值),因为这两能服务器都设定了一次自动增长值2,所以它们的起点必须得不同,这样才能避免两台服务器数据同步时出现主键冲突。 注:可以在my.cnf文件中添加“binlog_do_db=数据库名”配置项(可以添加多个)来指定要同步的数据库

    3、将mysql2设置为mysql1的从服务器

    1)mysql1上创建授权用户

    [root@mysql1 ~]# mysql -uroot -p123.com mysql> grant replication slave on *.* to rep@'192.168.20.%' identified by '123.com';

    2)查看mysql1的当前binlog状态信息

    mysql> show master status\G *************************** 1. row *************************** File: log_bin.000001 #这个值会用到 Position: 609 #这个值会用到 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 1 row in set (0.00 sec)

    3)在mysql2上指定mysql1为master,并开启slave功能

    #指定master地址 mysql> change master to master_host='192.168.100.2', -> master_user='rep', -> master_password='123.com', -> master_log_file='log_bin.000001', #必须和master上查看到的名字一样 -> master_log_pos=609; #同上,这个值也是在master上查看到的 #启动slave功能 mysql> start slave; #确定配置成功 mysql> show slave status\G #查看slave状态 *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.100.2 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: log_bin.000001 Read_Master_Log_Pos: 609 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 318 Relay_Master_Log_File: log_bin.000001 Slave_IO_Running: Yes # 这个值必须为Yes Slave_SQL_Running: Yes # 这个值也必须为Yes #只要上面两个值为yes,则表示主从没有问题, #其中,IO线程是去master上面读取二进制日志到本地的中继日志中; SQL线程是将本地的中继日志中的内容转换为sql语句并执行。

    4、将mysql1设置为mysql2的从服务器

    #主机mysql2上操作如下: mysql> grant replication slave on *.* to rep@'192.168.100.%' identified by '123.com'; mysql> flush privileges; mysql> show master status\G #获取所需的file和Position *************************** 1. row *************************** File: log_bin.000002 Position: 609 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 1 row in set (0.00 sec) #主机mysql1上操作如下: #指定mysql2为master mysql> change master to master_host='192.168.100.3', -> master_user='rep', -> master_password='123.com', -> master_log_file='log_bin.000002', -> master_log_pos=609; mysql> start slave; #启动slave mysql> show slave status\G #查看slave状态 *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.100.3 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: log_bin.000002 Read_Master_Log_Pos: 609 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 318 Relay_Master_Log_File: log_bin.000002 #确保下面两个值为yes Slave_IO_Running: Yes Slave_SQL_Running: Yes

    5、测试主主同步

    1)主机mysql1创建测试数据

    mysql> create database test; mysql> use test mysql> create table test1(id int,name varchar(4)); mysql> insert into t1 values(1,'a'),(2,'b'); #确认mysql1的数据 mysql> select * from t1; +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | +------+------+ 2 rows in set (0.00 sec)

    2)确认mysql2已经同步并插入新的数据

    #以下操作在主机mysql2上进行 mysql> select * from test1; #确定数据已同步 +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | +------+------+ #插入数据测试 mysql> insert into test1 values(3,'c'),(4,'d'); mysql> select * from test1; #确定最新数据 +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | +------+------+

    3)确定mysql1可以同步mysql2的数据

    #在mysql1上查询,是否同步mysql2主机上的数据 mysql> select * from test1; +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | +------+------+ 4 rows in set (0.00 sec)

    至此,现在任何一台MySQL上更新数据都会同步到另一台MySQL,MySQL同步完成。

    注:若主MySQL服务器已经存在,只是后期业务拓展才搭建从服务器,在配置数据库同步前应先将MySQL服务器的要同步的数据库拷贝到从服务器上(如先在主MySQL上备份数据库,再用备份再从MySQL服务器上恢复)。

    二、配置keepalived高可用

    1、安装keepalived

    两个节点都需要执行以下命令,以便安装keepalived。

    [root@mysql1 ~]# yum -y install keepalived

    2、修改主机mysql1的keepalived配置文件

    [root@mysql1 ~]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id mysql-1 #此处的值必须唯一 } vrrp_instance VI_1 { state BACKUP #指定角色为backup,两台MySQL服务器的角色均为backup,设置backup将根据优先级决定主从 interface ens33 #指定承载虚拟IP的网卡 virtual_router_id 51 #指定组,同一个集群内的值必须一致。并且不可和局域网中的其他组冲突 priority 100 #优先级范围为:0~100 advert_int 1 #发vrrp包的时间间隔,即多久进行一次master选举(可认为是健康检查时间间隔) nopreempt #不抢占,即允许一个priority比较低的节点作为master, authentication { #认证区域 auth_type PASS auth_pass 1111 } virtual_ipaddress { #VIP区域,指定vip地址 192.168.100.20 } } virtual_server 192.168.100.100 3306 { #设置虚拟服务器,需要指定虚拟IP地址和服务端口,IP与端口之间用空格隔开 delay_loop 2 #设置运行情况检查时间,单位是秒 lb_algo rr #设置后端调度算法 lb_kind DR #设置lvs实现负载均衡的机制,有NATTUNDR三个模式,DR模式效率最高 persistence_timeout 60 #会话保持时间,单位是秒 protocol TCP #指定转发协议类型,有TCPUDP两种 real_server 192.168.100.2 3306 { #配置服务节点,这里指定的也就是本机的真实IP weight 1 #设置权重 notify_down /etc/keepalived/bin/mysql.sh #检测到real_server的MySQL服务宕机后执行的脚本。 TCP_CHECK { connect_port 3306 #健康检查端口 connect_timeout 3 #连接超时时间 retry 3 #重试次数 delay_before_retry 3 #重连间隔时间 } } } #准备指定的脚本 [root@mysql01 keepalived]# pwd /etc/keepalived [root@mysql01 keepalived]# mkdir bin [root@mysql01 keepalived]# vim bin/mysql.sh #!/bin/bash pkill keepalived #停止keepalived服务 [root@mysql01 keepalived]# chmod +x bin/mysql.sh #赋予脚本执行权限 [root@mysql01 ~]# systemctl start keepalived #启动keepalived服务

    3、确定ens33网卡有虚拟Ip

    [root@mysql01 ~]# ip a show ens33 #必须使用ip a命令才可以查看到,ifconfig命令查看不到 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:c0:39:80 brd ff:ff:ff:ff:ff:ff inet 192.168.20.2/24 brd 192.168.20.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.20.20/32 scope global ens33 #可以看到指定的VIP已经绑定到ens33上 valid_lft forever preferred_lft forever inet6 fe80::659e:9312:318a:e52b/64 scope link noprefixroute valid_lft forever preferred_lft forever #将keepalived的配置文件发送到mysql2主机上 [root@mysql01 ~]# scp /etc/keepalived/keepalived.conf root@192.168.100.3:/etc/keepalived/

    4、修改主机mysql2的keepalived配置文件

    #修改msyql1发送来的配置文件 [root@mysql02 keepalived]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id mysql-2 #更改router_id,此处在热备组中必须要唯一 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 90 #更改优先级 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.100.20 } } virtual_server 192.168.100.20 3306 { delay_loop 2 lb_algo rr lb_kind DR persistence_timeout 60 protocol TCP real_server 192.168.100.3 3306 { #更改为本机的IP地址及监听端口 weight 1 notify_down /etc/keepalived/bin/mysql.sh TCP_CHECK { connect_port 3306 connect_timeout 3 retry 3 delay_before_retry 3 } } } #准备所需脚本 [root@mysql1 keepalived]# pwd /etc/keepalived [root@mysql2 keepalived]# mkdir bin [root@mysql2 keepalived]# vim bin/mysql.sh #!/bin/bash pkill keepalived [root@mysql2 keepalived]# chmod +x bin/mysql.sh #启动keepalived [root@mysql2 ~]# systemctl start keepalived

    三 最终总结

    至此,即可实现MySQL的双主效果(只要VIP所在的节点,MySQL服务端口无法连接, 那么VIP将切换至另一台节点,即使宕机的mysql服务器恢复,也不会对VIP进行抢占)。 虽然有两台MySQL数据库,但是其使用keepalived提供的虚拟IP地址来对外提供服务, 不管这个虚拟Ip地址落在哪台服务器上, 都可以保证数据的一致性,因为它们互为主从, 并且keepalived的状态都为backup, 也设置了不抢占(减少VIP的切换次数), 这样可以大大的避免keepalived的脑裂问题。
    Processed: 0.029, SQL: 9