HAProxy+Keepalived+MyCat+MySQL高可用集群

1、集群环境分配

由于硬件有限,安装了6台Linux虚拟机,做如下分配:
MySQL master1:192.168.1.103
MySQL slave1:192.168.1.104
MySQL master2/MyCat1:192.168.1.105
MySQL slave2/MyCat2:192.168.1.106
HAProxy1:192.168.1.107
HAProxy2:192.168.1.108
        VIP:192.168.1.8
使用软件:
        haproxy-1.7.1.tar.gz
        keepalived-1.2.18.tar.gz
        Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz
MySQL在最初的时候就安装好,每台机器克隆后都有MySQL,需要说明的是,把需要使用MySQL的uuid修改,因为都是克隆的,所以这个值是一样的[root@localhost ~]# cat /usr/local/mysql-5.6.31/data/auto.cnf 修改文件里边,随机改一下就即可。
其他文件,分别对应上传到服务器。

2、配置MySQL主从和主主

在103和105配置主库,分别执行如下操作,其中105的auto_increment_offset=2
 vim /etc/my.cnf 修改配置
 [client]
 port = 3306 #客户端端口
 default-character-set = utf8mb4  #客户端默认字符集
 [mysqld]
 default_storage_engine = InnoDB #默认数据库引擎
 port = 3306
 character_set_server=utf8
 log_bin=master_bin #开启二进制日志
 server_id=1 #设置server_id
 #步进值,一般有n台主MySQL就填n
 auto_increment_increment=2  
 #起始值,一般填第n台主MySQL。
 auto_increment_offset=1  
 # 做为从库时,数据库的修改也会写到bin-log里
 log-slave-updates  
 # 表示自动删除5天以前的binlog,可选
 expire_logs_days=5
 #忽略mysql库
 #binlog-ignore=mysql  
 #忽略information_schema库
 #binlog-ignore=information_schema  
 #要同步的数据库,默认所有库
 #replicate-do-db=demo

 103/104/105/106的server_id分别是1/3/2/4

 在104和106配置从库,分别执行如下操作:
 vim /etc/my.cnf 修改配置
 [client]
 port = 3306 #客户端端口
 default-character-set = utf8mb4  #客户端默认字符集
 [mysqld]
 default_storage_engine = InnoDB #默认数据库引擎
 port = 3306
 character_set_server=utf8
 server_id=3 #设置server_id

 分别启动两台master,在两台master中的MySQL中创建用户供Slave使用
 mysql> grant all privileges on *.* to 'slave'@'192.168.1.%' identified by 'slave' with grant option;
 mysql> flush privileges;

查看master状态,记录文件名

SHOW MASTER STATUS;

分别启动Slave,配置Slave,登录MySQL,先停止stop slave;再执行Slave配置,执行代码如下:

103:CHANGE MASTER TO MASTER_HOST='192.168.1.105',MASTER_USER='slave',MASTER_PASSWORD='slave',MASTER_LOG_FILE='master_bin.000001';
104:CHANGE MASTER TO MASTER_HOST='192.168.1.103',MASTER_USER='slave',MASTER_PASSWORD='slave',MASTER_LOG_FILE='master_bin.000001';
105:CHANGE MASTER TO MASTER_HOST='192.168.1.103',MASTER_USER='slave',MASTER_PASSWORD='slave',MASTER_LOG_FILE='master_bin.000001';  因为两个master互为主从,所以在两边都要配置对方的master
106:CHANGE MASTER TO MASTER_HOST='192.168.1.105',MASTER_USER='slave',MASTER_PASSWORD='slave',MASTER_LOG_FILE='master_bin.000001';

再次启动start slave

通过命令 show slave status\G; 查看每个节点信息,主从都是一致的。没问题。数据测试也ok。

测试双主从:开启日志查询set global general_log = on;,动态监控日志信息tail -f /usr/local/mysql-5.6.31/data/localhost.log

都不宕机的情况下,不管是从哪一台master修改数据,其他节点都能显示,同步一致性。
当master1停止MySQL情况下,master2修改了数据,master再次启动也会把master2修改的同步到master1和Slave1。反之亦然没问题。

3、配置MyCat

分别在105、106解压MyCat文件到/usr/local/mycat下

直接运行测试一下:

[root@localhost mycat]# bin/mycat start

没问题,配置MyCat逻辑表,进行测试,两个都一致。这里配置只是为了测试用,实际中按照实际需求配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!--逻辑库表创建-->
<schema name="demo" checkSQLschema="false" sqlMaxLimit="100">
<table name="user" dataNode="demo1"/>
</schema>
<schema name="demo1" checkSQLschema="true" sqlMaxLimit="100">
<table name="user" dataNode="demo111" />
</schema>


<!--逻辑节点,对应物理库-->
<dataNode name="demo1" dataHost="host103" database="demo" />
<dataNode name="demo2" dataHost="host105" database="demo" />
<dataNode name="demo111" dataHost="host111" database="demo" />

<!--物理库配置-->
<dataHost name="host103" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave status</heartbeat>
<writeHost host="hostM1" url="192.168.1.103:3306" user="root" password="123456"/>
<writeHost host="hostS1" url="192.168.1.104:3306" user="root" password="123456"/>
</dataHost>
<dataHost name="host105" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave status</heartbeat>
<writeHost host="hostM2" url="192.168.1.105:3306" user="root" password="123456"/>
<writeHost host="hostS2" url="192.168.1.106:3306" user="root" password="123456"/>
</dataHost>
<dataHost name="host111" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave status</heartbeat>
<writeHost host="hosstM1" url="192.168.1.103:3306" user="root" password="123456">
<readHost host="hostsS1" url="192.168.1.104:3306" user="root" password="123456"/>
</writeHost>
<writeHost host="hostsM2" url="192.168.1.105:3306" user="root" password="123456">
<readHost host="hostsS2" url="192.168.1.106:3306" user="root" password="123456"/>
</writeHost>
</dataHost>
</mycat:schema>

server.xml中增加逻辑库访问。在远程分别访问两台MyCat并测试。

 ①、每个节点都不宕机的情况下测试都没任何问题。
 ②、如果master1宕机,停止MySQL,在插入数据,日志可以看到往master2插入,salve2同步,再次恢复master1,数据变化将同步回master1
 ③、读数据,通常都分配到Slave和master2上,只有出现io延迟才会在master1读取。
两台MyCat搭配MySQL都没问题,下一步:

4、安装xinetd

xinetd是新一代的网络守护进程服务程序,又叫超级internet服务器。经常用来托管轻量级服务。
这里安装xinetd的目的是检测MyCat的服务状态,为HAProxy提供MyCat服务状态的依据。
A、安装如下:
        yum install -y xinetd
        检查/etc/xinetd.conf 的末尾是否有 includedir /etc/xinetd.d ,没有就加上
        检查 /etc/xinetd.d 目录是否存在,不存在则创建mkdir /etc/xinetd.d/

B、增加 Mycat 存活状态检测服务配置:vim /etc/xinetd.d/mycat_status
        service mycat_status
        {
                flags = REUSE
                ## 使用该标记的 socket_type 为 stream,需要设置 wait 为 no
                socket_type = stream ## 封包处理方式,Stream 为 TCP 数据包
                port = 48700 ## 服务监听端口
                wait = no ## 表示不需等待,即服务将以多线程的方式运行
                user = root ## 执行此服务进程的用户
                server =/usr/local/bin/mycat_status ## 需要启动的服务脚本
                log_on_failure += USERID ## 登录失败记录的内容
                disable = no ## 要启动服务,将此参数设置为 no
        }

C、添加 /usr/local/bin/mycat_status 服务脚本 vim /usr/local/bin/mycat_status
        #!/bin/bash
        Mycat=`/usr/local/mycat/bin/mycat status | grep 'not running' | wc -l`
        if [ "$Mycat" = "0" ]; then
                /bin/echo -e "HTTP/1.1 200 OK\r\n"
                else
                /bin/echo -e "HTTP/1.1 503 Service Unavailable\r\n"
        fi  
D、脚本赋予可执行权限
        chmod 755 /usr/local/bin/mycat_status

E、在 /etc/services 中加入 mycat_status 服务
        vim /etc/services 在末尾加入:
        mycat_status 48700/tcp # mycat_status
        保存后,重启 xinetd 服务 service xinetd restart

F、验证 mycat_status 服务是否成功启动
        netstat -antup|grep 48700

G、测试脚本
        /usr/local/bin/mycat_status

5、安装HAProxy

在107和108中安装HAProxy,解压文件到/usr/local下。
①、编译安装:
        依赖yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
        编译:make TARGET=linux2628 ARCH=x86_64 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 PREFIX=/usr/local/haproxy
                TARGET 是指定内核版本,高于 2.6.28 的建议设置为 linux2628,低于的是多少写多少。内核版本查看命令# uname -r, ARCH 指定系统架构,openssl pcre zlib 这三个包需要安装不然不支持
        安装:创建安装目录mkdir /usr/local/haproxy
        执行make install PREFIX=/usr/local/haproxy安装
②、配置:
        创建配置文件目录
                mkdir -p /usr/local/haproxy/conf
                mkdir -p /etc/haproxy/
        添加配置文件并创建软连接
                vi /usr/local/haproxy/conf/haproxy.cfg
                        # Simple configuration for an HTTP proxy listening on port 80 on all
                        # interfaces and forwarding requests to a single backend "servers" with a
                        # single server "server1" listening on 127.0.0.1:8000
                        global
                                daemon
                                maxconn 256
                                defaults
                                mode http
                                timeout connect 5000ms
                                timeout client 50000ms
                                timeout server 50000ms
                                frontend http-in
                                bind *:80
                        default_backend servers
                        backend servers
                        server server1 127.0.0.1:8000 maxconn 32
                        # The same configuration defined with a single listen block. Shorter but
                        # less expressive, especially in HTTP mode. global
                        daemon
                        maxconn 256
                        defaults
                        mode http
                        timeout connect 5000ms
                        timeout client 50000ms
                        timeout server 50000ms
                        listen http-in
                        bind *:80
                        server server1 127.0.0.1:8000 maxconn 32
                创建软连接:ln -s /usr/local/haproxy/conf/haproxy.cfg /etc/haproxy/haproxy.cfg

        ③、拷贝错误页面并创建软连接
                cp -r /usr/local/haproxy-1.7.1/examples/errorfiles /usr/local/haproxy/
                ln -s /usr/local/haproxy/errorfiles /etc/haproxy/errorfiles

        ④、添加 HAProxy 命令脚本软连接
                ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin
        设置自启动(可选)
                cp /usr/local/haproxy-1.7.1/examples/haproxy.init /etc/rc.d/init.d/haproxy
                chmod +x /etc/rc.d/init.d/haproxy

                chkconfig --add haproxy
                chkconfig haproxy on
        ⑤、配置MyCat负载均衡集群
                修改配置;vi /usr/local/haproxy/conf/haproxy.cfg
                107:        
                        global
                                log 127.0.0.1 local0 info
                                chroot /usr/share/haproxy
                                group haproxy
                                user haproxy
                                daemon
                                nbproc 1
                                maxconn 4096
                                node haproxy1
                                description haproxy1
                        defaults
                                log global
                                mode http
                                option httplog
                                retries 3
                                option redispatch
                                maxconn 2000
                                timeout connect 5000ms
                                timeout client 50000ms
                                timeout server 50000ms
                        listen admin_stats
                                bind :48800
                                stats uri /admin-status
                                stats auth admin:admin
                                mode http
                                option httplog
                        listen mycat_servers
                                bind :3307
                                mode tcp
                                option tcplog
                                option tcpka
                                option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
                                balance roundrobin
                                server mycat_01 192.168.1.105:8066 check port 48700 inter 2000ms rise 2 fall 3 weight 10
                                server mycat_02 192.168.1.106:8066 check port 48700 inter 2000ms rise 2 fall 3 weight 10                                

                108:
                        global
                                log 127.0.0.1 local0 info
                                chroot /usr/share/haproxy
                                group haproxy
                                user haproxy
                                daemon
                                nbproc 1
                                maxconn 4096
                                node haproxy2
                                description haproxy2
                        defaults
                                log global
                                mode http
                                option httplog
                                retries 3
                                option redispatch
                                maxconn 2000
                                timeout connect 5000ms
                                timeout client 50000ms
                                timeout server 50000ms
                        listen admin_stats
                                bind :48800
                                stats uri /admin-status
                                stats auth admin:admin
                                mode http
                                option httplog
                        listen mycat_servers
                                bind :3307
                                mode tcp
                                option tcplog
                                option tcpka
                                option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
                                balance roundrobin
                                server mycat_01 192.168.1.105:8066 check port 48700 inter 2000ms rise 2 fall 3 weight 10
                                server mycat_02 192.168.1.106:8066 check port 48700 inter 2000ms rise 2 fall 3 weight 10

        ⑥、为 HAProxy 创建 Linux 系统用户                
                groupadd haproxy
                useradd -g haproxy haproxy

        ⑦、创建 chroot 运行的路径mkdir /usr/share/haproxy

        ⑧、开启 rsyslog 的 haproxy 日志记录功能
                默认情况下 haproxy 是不记录日志的,如果需要记录日志,还需要配置系统的 syslog,在 linux 系统中是 rsyslog 服务。syslog 服务器可以用作一个网络中的日志监控中心,rsyslog是一个开源工具,被广泛用于 Linux 系统以通过 TCP/UDP 协议转发或接收日志消息。安装配置 rsyslog 服务。
                        yum install -y rsyslog  
                修改配置:
                        vi /etc/rsyslog.conf                                
                                $ModLoad imudp # 模块名,支持 UDP 协议
                                $UDPServerRun 514  #允许 514 端口接收使用 UDP 和 TCP 协议转发过来的日志,默认端口
                        确认 #### GLOBAL DIRECTIVES #### 段中是否有 $IncludeConfig /etc/rsyslog.d/*.conf 没有则增加上此配置。rsyslog 服务会来此目录加载配置                                
                        创建 haproxy 的日志配置文件
                        vi /etc/rsyslog.d/haproxy.conf
                                local0.* /var/log/haproxy.log
                                &~
                        注:如果不加上&~,除了在/var/log/haproxy.log中写日志之外,也会写入/var/log/massage中

                        保存后重启rsyslog服务service rsyslog restart
                等到 HAProxy 服务启动后,就能在/var/log/haproxy.log中就会有日志。                                
        ⑨、配置系统内核IP包转发规则,Linux默认不会转发tcp层的包
                vi /etc/sysctl.conf
                                net.ipv4.ip_forward = 1
                生效: sysctl -p                
        ⑩、启动HAProxy
                service haproxy start
                ps -ef | grep haproxy


                测试:查看 HAProxy 提供的 WEB 统计应用
                        http://192.168.1.107:48800/admin-status
                        http://192.168.1.108:48800/admin-status

20200420192551

6、安装Keepalived

 A、安装
         yum -y install keepalived
         keepalived相关文件:
         /etc/keepalived
         /etc/keepalived/keepalived.conf     #keepalived服务主配置文件
         /etc/rc.d/init.d/keepalived         #服务启动脚本(centos 7 之前的用init.d 脚本启动,之后的systemd启动)
         /etc/sysconfig/keepalived
         /usr/bin/genhash
         /usr/libexec/keepalived
         /usr/sbin/keepalived
 B、配置 /etc/keepalived/keepalived.conf  
 192.168.1.107:
         ! Configuration File for keepalived
         global_defs {
                 # keepalived 自带的邮件提醒需要开启 sendmail 服务。建议用独立的监控或第三方SMTP
                 router_id haproxy1 ## 标识本节点的字符串,通常为 hostname,需要修改/etc/hosts
         }
         # keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整 vrrp_instance的优先级。
         # 如果脚本执行结果为 0,并且 weight 配置的值大于 0,则优先级相应的增加。
         # 如果脚本执行结果非 0,并且 weight 配置的值小于 0,则优先级相应的减少。
         # 其他情况,维持原本配置的优先级,即配置文件中 priority 对应的值。
         vrrp_script chk_haproxy {
                 script "/etc/keepalived/haproxy_check.sh"  # 检测 haproxy 状态的脚本路径
                 interval 2  # 检测时间间隔
                 weight 2    # 如果条件成立,权重+2
         }
         # 定义虚拟路由, VI_1 为虚拟路由的标示符,自己定义名称
         vrrp_instance VI_1 {
                 state BACKUP         # 默认主设备(priority 值大的)和备用设备(priority 值小的)都设置为 BACKUP,通常由priority 来控制同时启动情况下的默认主备,否则先启动的为主设备
                 interface eth4         # 绑定虚拟 IP 的网络接口,与本机 IP 地址所在的网络接口相同
                 virtual_router_id 35 # 虚拟路由的 ID 号,两个节点设置必须一样,可选 IP 最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址
                 priority 100         # 节点优先级,值范围 0-254, MASTER 要比 BACKUP 高
                 nopreempt                 # 主设备(priority 值大的)配置一定要加上 nopreempt,否则非抢占也不起作用
                 advert_int 1         # 组播信息发送间隔,两个节点设置必须一样,默认 1s
                 # 设置验证信息,两个节点必须一致
                 authentication {
                         auth_type PASS
                         auth_pass 1111  
                 }
                 # 将 track_script 块加入 instance 配置块
                 track_script {
                         chk_haproxy   # 检查 HAProxy 是否正常运行
                 }
                 # 虚拟 IP 池, 两个节点设置必须一样
                 virtual_ipaddress {
                         192.168.1.10  # 虚拟 ip,可以定义多个,每行一个
                 }
         }

192.168.1.108:
         ! Configuration File for keepalived
         global_defs {
                 # keepalived 自带的邮件提醒需要开启 sendmail 服务。建议用独立的监控或第三方SMTP
                 router_id haproxy2 ## 标识本节点的字符串,通常为 hostname,需要修改/etc/hosts
         }
         # keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整 vrrp_instance的优先级。
         # 如果脚本执行结果为 0,并且 weight 配置的值大于 0,则优先级相应的增加。
         # 如果脚本执行结果非 0,并且 weight 配置的值小于 0,则优先级相应的减少。
         # 其他情况,维持原本配置的优先级,即配置文件中 priority 对应的值。
         vrrp_script chk_haproxy {
                 script "/etc/keepalived/haproxy_check.sh"  # 检测 haproxy 状态的脚本路径
                 interval 2  # 检测时间间隔
                 weight 2    # 如果条件成立,权重+2
         }
         # 定义虚拟路由, VI_1 为虚拟路由的标示符,自己定义名称
         vrrp_instance VI_1 {
                 state BACKUP         # 默认主设备(priority 值大的)和备用设备(priority 值小的)都设置为 BACKUP,通常由priority 来控制同时启动情况下的默认主备,否则先启动的为主设备
                 interface eth4         # 绑定虚拟 IP 的网络接口,与本机 IP 地址所在的网络接口相同
                 virtual_router_id 35 # 虚拟路由的 ID 号,两个节点设置必须一样,可选 IP 最后一段使用,相同的 VRID 为一个组,他将决定多播的 MAC 地址
                 priority 99         # 节点优先级,值范围 0-254, MASTER 要比 BACKUP 高
                 advert_int 1         # 组播信息发送间隔,两个节点设置必须一样,默认 1s
                 # 设置验证信息,两个节点必须一致
                 authentication {
                         auth_type PASS
                         auth_pass 1111  
                 }
                 # 将 track_script 块加入 instance 配置块
                 track_script {
                         chk_haproxy   # 检查 HAProxy 是否正常运行
                 }
                 # 虚拟 IP 池, 两个节点设置必须一样
                 virtual_ipaddress {
                         192.168.1.10  # 虚拟 ip,可以定义多个,每行一个
                 }
         }

如果非抢占模式不生效, 在 Keepalived 的故障节点恢复后会再次导抢占vip,从而因 vip 切换而闪断带来的风险。
按以上配置,配置了 Keepalived 非抢占模式, 配置及注意点如下:
        (1) 主设备、 从设备中的 state 都设置为 BACKUP
        (2) 主设备、从设备中都不要配置 mcast_src_ip (本机 IP 地址)
        (3) 默认主设备(priority 值大的 Keepalived 节点) 配置一定要加上 nopreempt,否则非抢占不起作用
        (4) 防火墙配置允许组播(主、备两台设备上都需要配置, keepalived 使用 224.0.0.18作为 Master 和 Backup 健康检查的通信 IP)


 ③、配置检测 haproxy 状态的脚本
 /etc/keepalived/haproxy_check.sh
 创建一个日志,如果发生haproxy异常需要切换,记录到日志中。
 mkdir -p /usr/share/haproxy/log
 脚本如下:如果 haproxy 停止运行,尝试启动,如果无法启动则杀死本机的 keepalived 进程,keepalied 自动将虚拟 ip 绑定到 BACKUP 机器上。
         #!/bin/bash
         START_HAPROXY="/etc/rc.d/init.d/haproxy start"
         STOP_HAPROXY="/etc/rc.d/init.d/haproxy stop"
         LOG_FILE="/usr/share/haproxy/log/haproxy-check.log"
         HAPS=`ps -C haproxy --no-header |wc -l`
         date "+%Y-%m-%d %H:%M:%S" >> $LOG_FILE
         echo "check haproxy status" >> $LOG_FILE
         if [ $HAPS -eq 0 ];then
                 echo $START_HAPROXY >> $LOG_FILE
                 $START_HAPROXY >> $LOG_FILE 2>&1
                 sleep 3
                 if [ `ps -C haproxy --no-header |wc -l` -eq 0 ];then
                         echo "start haproxy failed, killall keepalived" >> $LOG_FILE
                         killall keepalived
                 fi
         fi
 保存赋权:
 chmod +x /etc/keepalived/haproxy_check.sh

 ④、启动 Keepalived
 停止: service keepalived stop
 启动: service keepalived start
 重启: service keepalived restart
 看状态: service keepalived status

7、测试Keepalived+HAProxy

两台服务器启动Keepalived+HAProxy,测试:

20200420192826

此时,keepalived,VIP是在108上,如果停止108的haproxy,如下效果:

20200420192848

停止108的haproxy,keepalived检测haproxy异常,并且重启haproxy,所以haproxy继续运行且日志中记录重启haproxy记录,这样就实现keepalived对haproxy高可用。

如果直接停止108keepalived,VIP飘到107:

20200421123303

如果把107的/usr/local/haproxy/conf/haproxy.cfg配置文件修改错误,让haproxy不能重启,停止haproxy后测试效果如下:

20200421123317

可以看到,VIP漂移到108,而且107也访问不了haproxy,并且107keepalived状态:keepalived dead but subsys locked。
日志中显示启动haproxy报错信息,和杀死keepalived进程信息。

20200421123334

8、测试HAProxy+Keepalived+MyCat+MySQL高可用集群

全部机器启动并启动相关服务测试,通过VIP访问到mysql数据库,对数据的操作,没有问题。