• keepalived+MySQL实现高可用


    Snipaste_2020-08-03_23-21-47



    (一)keepalived概述

    Keepalived通过VRRP(虚拟路由冗余协议)协议实现虚拟IP的漂移。当master故障后,VIP会自动漂移到backup,这时通知下端主机刷新ARP表,如果业务是通过VIP连接到服务器的,则此时依然能够连接到正常运行的主机,RedHat给出的VRRP工作原理如下图:

    wps1


    本来对VIP漂移有一定了解的我,看了上面的图后,越来越懵了。因此只能根据我的个人理解,来对keepalived的VIP漂移做一个解释了,假设我现在有一套这样的环境:
    主机A的IP地址为:192.168.10.11
    主机B的IP地址为:192.168.10.12

    我们再单独定义一个keepalived使用的VIP:192.168.10.10

    当2台主机安装了keepalive并正常运行时,keepalive会选择一个节点做为主节点(这里假设为主机A,IP为192.168.10.11),由于A是主节点,所以主机A上还会生成一个IP地址192.168.10.10,即虚拟IP(Virtual IP,也称VIP),此时我们使用192.168.10.10访问主机,访问到的主机是A;假如A主机上的keepalived由于某些原因(例如服务器宕机、用户主动关闭…)关闭了,keepalived备用节点会检查与主节点keepalived的通信是否正常,检测到不正常,则会提升一个备节点为主节点,相应的虚拟IP也会在对应的主机上生成,从而实现高可用的目的。

    Snipaste_2020-08-03_18-54-27


    (二)MySQL是如何结合keepalived实现高可用的

    在MySQL中,通过搭建MySQL双主复制,保持2台主机上的MySQL数据库一模一样,并在2台主机上安装keepalived软件,启用VIP,用户应用程序通过VIP访问数据库。当包含VIP的主机上的数据库发生故障时,关闭keepalived,从而将VIP漂移到另一个节点,用户依然可以正常访问数据库。 (这里需要注意,虽然MySQL架构双主复制,2个节点都可以写入数据,但是我们在使用的时候,是通过VIP访问其中一个实例,并没有2个数据库实例一起使用)。这里我简单画了一个流程图,来说明keepalive与MySQL实现高可用的过程:

    Snipaste_2020-08-03_19-30-48


    (三)keepalived+MySQL实现高可用过程实现

    基础环境规划:

    主机名 IP地址 备注
    服务器A hosta 192.168.10.11 keepalive主节点
    服务器B hostb 192.168.10.12 keepalive备节点
    192.168.10.10 虚拟IP,会在keepalive启动后分配到上面2台机器的主节点上


    (3.1)搭建MySQL双主复制环境

    STEP1:安装MySQL过程见:https://www.cnblogs.com/lijiaman/p/10743102.html

    STEP2:配置双主复制参数

    服务器A 服务器B

    [mysqld]
    basedir=/usr/local/mysql
    datadir=/mysql/data

    server_id = 1
    binlog_format=ROW
    log_bin=/mysql/binlog/master-bin
    auto-increment-increment = 2            #字段变化增量值
    auto-increment-offset = 1               #初始字段ID为1
    slave-skip-errors = all                 #忽略所有复制产生的错误
    gtid_mode=ON
    enforce-gtid-consistency=ON


    [mysqld]
    basedir=/usr/local/mysql
    datadir=/mysql/data

    server_id = 2
    binlog_format=ROW
    log_bin=/mysql/binlog/master-bin
    auto-increment-increment = 2            #字段变化增量值
    auto-increment-offset = 2               #初始字段ID为2
    slave-skip-errors = all                 #忽略所有复制产生的错误
    gtid_mode=ON
    enforce-gtid-consistency=ON

    STEP3:创建复制用户,2个数据库上都要创建

    grant replication slave on *.* to 'rep'@'%' identified by '123';

    STEP4:将hosta的数据拷贝到hostb,并应用

    [root@hostb ~]# mysqldump -uroot -p123456 -h 192.168.10.11 --single-transaction --all-databases --master-data=2  > hosta.sql
    [root@hostb ~]# mysql -uroot -p123456 < hosta.sql

    STEP5:hostb上开启复制,以下脚本在hostb上执行

    -- 配置复制
    mysql> CHANGE MASTER TO
         ->   master_host='192.168.10.11',
         ->   master_port=3306,
         ->   master_user='rep',
         ->   master_password='123',
         ->   MASTER_AUTO_POSITION = 1;
    Query OK, 0 rows affected, 2 warnings (0.01 sec)
    
    -- 开启复制
    mysql> start slave;
     Query OK, 0 rows affected (0.00 sec)
    
    
    -- 查看复制状态
    mysql> show slave status G
     *************************** 1. row ***************************
                    Slave_IO_State: Waiting for master to send event
                       Master_Host: 192.168.10.11
                       Master_User: rep
                       Master_Port: 3306
                     Connect_Retry: 60
                   Master_Log_File: master-bin.000001
               Read_Master_Log_Pos: 322
                    Relay_Log_File: hostb-relay-bin.000002
                     Relay_Log_Pos: 417
             Relay_Master_Log_File: master-bin.000001
                  Slave_IO_Running: Yes
    
                 Slave_SQL_Running: Yes

    STEP6:hosta上开启复制,以下脚本在hosta上执行

    mysql> CHANGE MASTER TO
        ->    master_host='192.168.10.12',
        ->    master_port=3306,
        ->    master_user='rep',
        ->    master_password='123',
        ->    MASTER_AUTO_POSITION = 1;
    Query OK, 0 rows affected, 2 warnings (0.01 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show slave status G;
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.10.12
                      Master_User: rep
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: master-bin.000001
              Read_Master_Log_Pos: 154
                   Relay_Log_File: hosta-relay-bin.000002
                    Relay_Log_Pos: 369
            Relay_Master_Log_File: master-bin.000001
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes

    STEP7:测试双主复制

    在hosta上创建数据库testdb,到hostb服务器上查看数据库是否已经创建

    -- hosta上创建数据库
    create database testdb;
    
    
    --hostb上查看数据库,发现已经创建
    mysql> show databases;
     +--------------------+
     | Database           |
     +--------------------+
     | information_schema |
     | db1                |
     | lijiamandb         |
     | mysql              |
     | performance_schema |
     | sbtest             |
     | sys                |
     | testdb             |
     +--------------------+
     8 rows in set (0.01 sec)

    在hostb的testdb数据库上创建表t1,并插入数据,到hosta上查看是否复制过来

    -- 在hostb上创建表并插入数据
    mysql> use testdb
    Database changed
    mysql> create table t1(id int,name varchar(20));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> insert into t1 values(1,'a');
    Query OK, 1 row affected (0.01 sec)
    
    
    -- 在hosta上查看数据,数据已经过来
    mysql> select * from testdb.t1;
    +------+------+
    | id   | name |
    +------+------+
    |    1 | a    |
    +------+------+
    1 row in set (0.00 sec)

    到这,双主复制已经搭建完成,接下来安装配置keepalived。


    (3.2)安装配置keepalived

    (3.2.1)keepalived的安装与管理

    keepalived可以使用源码安装,也可以使用yum在线安装,这里直接使用yum在线安装:

    [root@hosta data]# yum install -y keepalived

    使用如下命令查看安装路径:

    [root@hosta data]# rpm -ql keepalived
    /etc/keepalived
    /etc/keepalived/keepalived.conf
    /etc/sysconfig/keepalived
    /usr/bin/genhash
    /usr/lib/systemd/system/keepalived.service
    /usr/libexec/keepalived
    /usr/sbin/keepalived
    /usr/share/doc/keepalived-1.3.5
    … 略


    使用如下命令管理keepalived

    # 开启keepalived
    systemctl start keepalived 或者 service keepalived start 
    
    # 关闭keepalived
    systemctl stop keepalived 或者 service keepalived stop 
    
    # 查看keepalived运行状态
    systemctl status keepalived 或者 service keepalived status
    
    # 重新启动keepalived
    systemctl restart keepalived 或者 service keepalived restart


    (3.2.2)keepalived的配置

    keepalived的配置文件为:/etc/keepalived/keepalived.conf,我的配置文件如下:

    【hosta主机的配置文件】

    [root@hosta keepalived]# cat keepalived.conf
    ! Configuration File for keepalived
           
    global_defs {
    notification_email {
    ops@wangshibo.cn
    tech@wangshibo.cn
    }
           
    notification_email_from ops@wangshibo.cn
    smtp_server 127.0.0.1 
    smtp_connect_timeout 30
    router_id MASTER-HA
    }
           
    vrrp_script chk_mysql_port {       #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
        script "/mysql/chk_mysql.sh"   #这里通过脚本监测
        interval 2                     #脚本执行间隔,每2s检测一次
        weight –5                      #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
        fall 2                         #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
        rise 1                         #检测1次成功就算成功。但不修改优先级
    }
           
    vrrp_instance VI_1 {
        state BACKUP                  #这里所有节点都定义为BACKUP
        interface ens34               #指定虚拟ip的网卡接口
        mcast_src_ip 192.168.10.11    #本地IP 
        virtual_router_id 51          #路由器标识,MASTER和BACKUP必须是一致的
        priority 101                  #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。 
        advert_int 1
        nopreempt                     #不抢占模式,在优先级高的机器上设置即可,优先级低的机器可不设置         
        authentication {   
            auth_type PASS 
            auth_pass 1111     
        }
        virtual_ipaddress {    
            192.168.10.10             #虚拟IP 
        }
          
    track_script {               
       chk_mysql_port             
    }
    }


    【hostb主机的配置文件】

    [root@hostb keepalived]# cat keepalived.conf
    ! Configuration File for keepalived
           
    global_defs {
    notification_email {
    ops@wangshibo.cn
    tech@wangshibo.cn
    }
           
    notification_email_from ops@wangshibo.cn
    smtp_server 127.0.0.1 
    smtp_connect_timeout 30
    router_id MASTER-HA
    }
           
    vrrp_script chk_mysql_port {
        script "/mysql/chk_mysql.sh"
        interval 2            
        weight -5                 
        fall 2                 
        rise 1               
    }
           
    vrrp_instance VI_1 {
        state BACKUP
        interface ens34 
        mcast_src_ip 192.168.10.12
        virtual_router_id 51    
        priority 99          
        advert_int 1         
        authentication {   
            auth_type PASS 
            auth_pass 1111     
        }
        virtual_ipaddress {    
            192.168.10.10
        }
          
    track_script {               
       chk_mysql_port             
    }
    }

    需要特别注意:nopreempt这个参数只能用于state为BACKUP的情况,所以在配置的时候要把master和backup的state都设置成BACKUP,这样才会实现keepalived的非抢占模式!


    在配置完成之后,启动MySQL数据库和keepalive,需要注意,先启动MySQL,再启动keepalive,因为keepalive启动后会检测MySQL的运行状态,如果MySQL运行异常,keepalive会自动关闭。


    (3.3)高可用测试

    时间轴

    (时间递增)

    hosta操作hostb操作
    时间1

    # 数据库运行正常
    [root@hosta ~]# service mysqld status
      SUCCESS! MySQL running (8530)

    #keepalived运行正常
    [root@hosta ~]# service keepalived status
        Active: active (running) since Mon 2020-08-03 22:29:10 CST; 1min 32s ago

    # 此时虚拟IP在hosta上
    [root@hosta ~]# ip addr
    3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
         link/ether 00:0c:29:fb:62:0a brd ff:ff:ff:ff:ff:ff
         inet 192.168.10.11/24 brd 192.168.10.255 scope global ens34
            valid_lft forever preferred_lft forever
         inet 192.168.10.10/32 scope global ens34
            valid_lft forever preferred_lft forever
         inet6 fe80::20c:29ff:fefb:620a/64 scope link
            valid_lft forever preferred_lft forever

    # 数据库运行正常

    [root@hostb ~]# service mysqld status
      SUCCESS! MySQL running (8022)
     

    #keepalived运行正常

    [root@hostb ~]# service keepalived status
        Active: active (running) since Mon 2020-08-03 22:31:09 CST; 8s ago

    [root@hostb ~]# ip addr
    3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
         link/ether 00:0c:29:92:3d:5a brd ff:ff:ff:ff:ff:ff
         inet 192.168.10.12/24 brd 192.168.10.255 scope global ens34
            valid_lft forever preferred_lft forever
         inet6 fe80::20c:29ff:fe92:3d5a/64 scope link
            valid_lft forever preferred_lft forever

    时间2

    # 通过VIP访问数据库,访问到的都是hosta上的实例
    [root@hosta keepalived]# mysql -uroot -p123456 -h192.168.10.10 -e "select @@hostname"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hosta      |
    +------------+

    # 通过VIP访问数据库,访问到的都是hosta上的实例
    [root@hostb ~]# mysql -uroot -p123456 -h192.168.10.10 -e "select @@hostname"
      mysql: [Warning] Using a password on the command line interface can be insecure.
      +------------+
      | @@hostname |
      +------------+
      | hosta      |
      +------------+


    时间3

    # 主节点关闭MySQL
    [root@hosta keepalived]# service mysqld stop
    Shutting down MySQL............ SUCCESS!


    时间4

    # keepalived检测到MySQL关闭后,会自动关闭
    [root@hosta keepalived]# service keepalived status
        Active: inactive (dead)

    # 此时VIP已经不存在
    [root@hosta keepalived]# ip addr
    3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
         link/ether 00:0c:29:fb:62:0a brd ff:ff:ff:ff:ff:ff
         inet 192.168.10.11/24 brd 192.168.10.255 scope global ens34
            valid_lft forever preferred_lft forever
         inet6 fe80::20c:29ff:fefb:620a/64 scope link
            valid_lft forever preferred_lft forever

    # hostb上的keepalived运行正常
    [root@hostb ~]# service keepalived status
        Active: active (running) since Mon 2020-08-03 22:31:09 CST; 6min ago

    # 发现VIP已经切换到了hostb
    [root@hostb ~]#  ip addr
    3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
         link/ether 00:0c:29:92:3d:5a brd ff:ff:ff:ff:ff:ff
         inet 192.168.10.12/24 brd 192.168.10.255 scope global ens34
            valid_lft forever preferred_lft forever
         inet 192.168.10.10/32 scope global ens34
            valid_lft forever preferred_lft forever
         inet6 fe80::20c:29ff:fe92:3d5a/64 scope link
            valid_lft forever preferred_lft forever

    时间5

    # 通过VIP访问数据库,访问到的都是hosta上的实例
    [root@hosta keepalived]# mysql -uroot -p123456 -h192.168.10.10 -e "select @@hostname"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hostb      |
    +------------+

    # 通过VIP访问数据库,访问到的都是hosta上的实例
    [root@hostb ~]# mysql -uroot -p123456 -h192.168.10.10 -e "select @@hostname"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hostb      |
    +------------+

    时间6

    # 重启MySQL
    [root@hosta keepalived]# service mysqld start
    Starting MySQL. SUCCESS!

    # 重启keepalived
    [root@hosta keepalived]# service keepalived start
    Redirecting to /bin/systemctl start keepalived.service
    [root@hosta keepalived]#
    [root@hosta keepalived]# service keepalived status
    Redirecting to /bin/systemctl status keepalived.service
        Active: active (running) since Mon 2020-08-03 22:40:08 CST; 6s ago

    # 因为使用了非抢占模式,VIP不会漂回来
    # 如果要把VIP漂回来,可以关闭hostb上的数据库或者直接关闭hostb服务器

    [root@hosta keepalived]# ip addr
    3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
         link/ether 00:0c:29:fb:62:0a brd ff:ff:ff:ff:ff:ff
         inet 192.168.10.11/24 brd 192.168.10.255 scope global ens34
            valid_lft forever preferred_lft forever
         inet6 fe80::20c:29ff:fefb:620a/64 scope link
            valid_lft forever preferred_lft forever



    【完】

  • 相关阅读:
    解决php网页运行超时问题:Maximum execution time of 30 seconds exceeded
    C#操作Xml:XSLT语法 在.net中使用XSLT转换xml文档示例
    C#操作Xml:XPath语法 在C#中使用XPath示例
    C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化
    C#操作Xml:如何定义Xsd文件
    C#操作Xml:linq to xml操作XML
    C#操作Xml:使用XmlWriter写Xml
    C#操作Xml:使用XmlReader读Xml
    C#操作Xml:通过XmlDocument读写Xml文档
    XML的序列化和反序列化 详细介绍
  • 原文地址:https://www.cnblogs.com/lijiaman/p/13430668.html
Copyright © 2020-2023  润新知