Heartbeat、haproxy及MySQL双主复制实现读写负载均衡及高可用详细教程
目录
一、中间件简述
1. heartbeat简介
2. haproxy简介
二、安装配置
1. 基本环境
2. 配置mysql双主复制
3. 安装配置haproxy
4. 安装配置heartbeat
5. 创建mysql服务检测脚本
三、功能测试
1. 验证haproxy的负载均衡轮询策略
2. 验证mysql的高可用性
3. 验证宕机重新上线后自动添加到haproxy中
4. 验证haproxy的高可用性
四、总结
本篇我们将做另一个实验,利用haproxy实现mysql双主复制的读写负载均衡与mysql的高可用,同时用heartbeat保证两台负载均衡器的高可用性。
一、中间件简述
1. heartbeat简介
一、heartbeat简介。
2. haproxy简介
haproxy是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备、虚拟主机、基于tcp和http应用代理等功能。其配置简单,而且拥有很好的对服务器节点的健康检查功能(相当于keepalived健康检查),当其代理的后端服务器出现故障时,haproxy会自动的将该故障服务器摘除,当服务器的故障恢复后haproxy还会自动重新添加回服务器主机。
haproxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制、调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户空间(user-space)实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么必须对其进行优化以使每个cpu时间片(cycle)做更多的工作。
haproxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。haproxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进当前架构中,同时可以保护web服务器不被暴露到网络上。
haproxy软件引入了frontend,backend的功能,frontend(acl规则匹配)可以根据任意http请求头做规则匹配,然后把请求定向到相关的backend(server pools等待前端把请求转过来的服务器组)。通过frontend和backend,我们可以很容易的实现haproxy的7层代理功能。
二、安装配置
1. 基本环境
os:centos linux release 7.2.1511 (core)
172.16.1.126:heartbeat + haproxy + mysql replication master
172.16.1.127:heartbeat + haproxy + mysql replication master
172.16.1.100:vip
整体架构图如图1所示。
图1
2. 配置mysql双主复制
所谓mysql双主复制,就是两个mysql服务器都能读能写,数据记录通过二进制传达给对方从而保持数据的一致性。就本例简而言之,172.16.1.126到172.16.1.127的主从复制 + 172.16.1.127到172.16.1.126的主从复制 = 172.16.1.126、172.16.1.127的双主复制。双主复制的详细配置步骤可以参考这篇文章:https://www.cnblogs.com/phpstudy2015-6/p/6485819.html#_label7,这里从略。
与主从复制相比,双主复制需要注意以下三个参数的设置:
log_slave_updates:要设置为true,将复制事件写入本机binlog。一台服务器既做主库又做从库时此选项必须要开启。 auto_increment_offset和auto_increment_increment:为避免自增列冲突,需要设置这两个参数,例如在双主复制中,可以配置如下:
# mastera自增长id auto_increment_offset = 1 auto_increment_increment = 2 #奇数id # masterb自增加id auto_increment_offset = 2 auto_increment_increment = 2 #偶数id
3. 安装配置haproxy
以下步骤用root用户在172.16.1.126、172.16.1.127两个主机上执行。
(1)从以下地址下载haproxy
https://www.haproxy.org/download/1.8/src/haproxy-1.8.12.tar.gz
(2)创建haproxy运行账户和组
groupadd haproxy #添加haproxy组 useradd -g haproxy haproxy -s /bin/false #创建账户haproxy并加入到haproxy组
(3)解压
tar zxvf haproxy-1.8.12.tar.gz cd haproxy-1.8.12
(4)查看操作系统版本信息
[root@hdp3~/haproxy-1.8.12]#uname -r 3.10.0-327.el7.x86_64 [root@hdp3~/haproxy-1.8.12]#
(5)编译与安装
make target=linux3100 cpu=x86_64 prefix=/usr/local/haprpxy make install prefix=/usr/local/haproxy
参数说明:
target:使用uname -r查看内核,如:2.6.18-371.el5,此时该参数就为linux26。kernel 等于2.6.28的用:target=linux2628,等等。 cpu:使用uname -r查看系统信息,如x86_64 gnu/linux,此时该参数就为x86_64。 prefix:指定haprpxy安装路径。(6)设置haproxy
mkdir -p /usr/local/haproxy/conf #创建配置文件目录 mkdir -p /etc/haproxy #创建配置文件目录 touch /usr/local/haproxy/conf/haproxy.cfg #创建配置文件 ln -s /usr/local/haproxy/conf/haproxy.cfg /etc/haproxy/haproxy.cfg #添加配置文件软连接 cp -r /root/haproxy-1.8.12/examples/errorfiles /usr/local/haproxy/errorfiles #拷贝错误页面 ln -s /usr/local/haproxy/errorfiles /etc/haproxy/errorfiles #添加软连接 mkdir -p /usr/local/haproxy/log #创建日志文件目录 touch /usr/local/haproxy/log/haproxy.log #创建日志文件 ln -s /usr/local/haproxy/log/haproxy.log /var/log/haproxy.log #添加软连接 cp /root/haproxy-1.8.12/examples/haproxy.init /etc/rc.d/init.d/haproxy #拷贝开机启动文件 chmod +x /etc/rc.d/init.d/haproxy #添加脚本执行权限 chkconfig haproxy on #设置开机启动 ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin #添加软连接
(7)配置haproxy.cfg参数
编辑/usr/local/haproxy/conf/haproxy.cfg,内容如下:
global log 127.0.0.1 local2 # 日志定义级别(err | warning | info | debug) chroot /usr/local/haproxy # 当前工作目录 pidfile /var/run/haproxy.pid # 进程id maxconn 4000 # 最大连接数 user haproxy # 运行改程序的用户 group haproxy daemon # 后台形式运行 stats socket /usr/local/haproxy/stats defaults mode tcp # haproxy运行模式(http | tcp | health) log global # 采用全局定义的日志 option dontlognull # 不记录健康检查的日志信息 option redispatch # serverid对应的服务器挂掉后,强制定向到其他健康的服务器 retries 3 # 三次连接失败则服务器不用 timeout http-request 10s timeout queue 1m timeout connect 10s # 连接超时 timeout client 1m # 客户端超时 timeout server 1m # 服务器超时 timeout http-keep-alive 10s timeout check 10s # 心跳检测 maxconn 600 # 最大连接数 listen stats # 配置haproxy状态页(用来查看的页面) mode http bind :8888 stats enable stats hide-version # 隐藏haproxy版本号 stats uri /haproxyadminstats # 一会用于打开状态页的uri stats realm haproxy\ statistics # 输入账户密码时的提示文字 stats auth admin:admin # 用户名:密码 frontend main bind 0.0.0.0:6603 # 使用6603端口。监听前端端口(表示任何ip访问6603端口都会将数据轮番转发到mysql服务器群组中) default_backend mysql # 后端服务器组名 backend mysql balance roundrobin # 使用轮询方式调度 server mysql1 172.16.1.126:3306 check port 3306 maxconn 300 server mysql2 172.16.1.127:3306 check port 3306 maxconn 300
(8)启动日志
编辑/etc/rsyslog.conf文件,去掉以下两行的注释,并在其后添加一行:
# provides tcp syslog reception $modload imtcp # 去掉注释 $inputtcpserverrun 514 # 去掉注释 local2.* /var/log/haproxy.log # 添加此行
(9)启动haproxy
systemctl start haproxy systemctl status haproxy -l systemctl stop haproxy systemctl restart haproxy
此时打开输入172.16.1.126:8888/haproxyadminstats,用admin/admin登陆后如图2所示,表明安装haproxy成功。
图2
4. 安装配置heartbeat
heartbeat的源码编译安装需要依次安装cluster glue、resource agents和heartbeat 三个软件,并且三个软件要安装在相同目录下。详细安装配置步骤参考:https://blog.csdn.net/wzy0623/article/details/81188814#二、安装heartbeat。
这里需要注意的是haresources的设置。在上一篇中,我们建立了一个名为mysql的脚本,它调用remove_slave.sh。当heartbeat主机获得资源时,将自动把mysql主从复制中的slave置为master。这次我们用/usr/local/heartbeat/etc/ha.d/haresources来启动haproxy,文件内容只有如下一行:
hdp3 172.16.1.100 haproxy
而/usr/local/heartbeat/etc/ha.d/resource.d/haproxy文件中也只有如下一行:
/etc/init.d/haproxy restart
资源只有vip,我们用这种配置保证haproxy的高可用性。当初始启动heartbeat后,vip绑定在172.16.1.126上。
5. 创建mysql服务检测脚本
与上一篇的实验类似,这里保留自定义mysql_check脚本用于检查本机mysql的服务器状态。脚本内容与部署参见https://blog.csdn.net/wzy0623/article/details/81188814#4.%20创建mysql服务检测脚本。
三、功能测试
1. 验证haproxy的负载均衡轮询策略
用客户端连接vip,并多次执行mysql查询,可以看到查询请求依次被发送到在两个主机上执行。
c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>
2. 验证mysql的高可用性
在172.16.1.126上杀掉mysql:
pkill -9 mysqld
用客户端连接vip,并多次执行mysql查询,可以看到查询请求都被发送到172.16.1.127。一台mysql宕机不影响应用的正常使用,保证了mysql服务的高可用性。
c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'" mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>
3. 验证宕机重新上线后自动添加到haproxy中
在172.16.1.126再次启动mysql,并重启haproxy服务:
service mysql start systemctl restart haproxy
用客户端连接vip,并多次执行mysql查询,可以看到查询请求依次被发送到在两个主机上执行。
c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>
4. 验证haproxy的高可用性
初始vip在126,126的haproxy启动,127的haproxy停止。客户端访问:
c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>
停止172.16.1.126上的mysql服务:
pkill -9 mysqld
mysql_check会检测到本机mysql服务宕机,触发停止heartbeat服务。vip漂移到172.16.1.127,同时172.16.1.127上的haproxy被拉起:
[root@hdp4~]#ip a 1: lo: mtu 65536 qdisc noqueue state unknown link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens160:mtu 1500 qdisc mq state up qlen 1000 link/ether 00:50:56:a5:49:7f brd ff:ff:ff:ff:ff:ff inet 172.16.1.127/24 brd 172.16.1.255 scope global ens160 valid_lft forever preferred_lft forever inet 172.16.1.100/24 brd 172.16.1.255 scope global secondary ens160:0 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fea5:497f/64 scope link valid_lft forever preferred_lft forever [root@hdp4~]# [root@hdp4~]# [root@hdp4~]#/etc/init.d/haproxy status ● haproxy.service - sysv: ha-proxy is a tcp/http reverse proxy which is particularly suited for high availability environments. loaded: loaded (/etc/rc.d/init.d/haproxy) active: active (running) since thu 2018-07-26 11:25:47 cst; 26s ago docs: man:systemd-sysv-generator(8) process: 532199 execstop=/etc/rc.d/init.d/haproxy stop (code=exited, status=0/success) process: 532205 execstart=/etc/rc.d/init.d/haproxy start (code=exited, status=0/success) main pid: 532210 (haproxy) cgroup: /system.slice/haproxy.service └─532210 /usr/sbin/haproxy -d -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid jul 26 11:25:47 hdp4 systemd[1]: starting sysv: ha-proxy is a tcp/http reverse proxy which is particularly suite...ts.... jul 26 11:25:47 hdp4 haproxy[532205]: starting haproxy: [ ok ] jul 26 11:25:47 hdp4 systemd[1]: started sysv: ha-proxy is a tcp/http reverse proxy which is particularly suited...ents.. hint: some lines were ellipsized, use -l to show in full. [root@hdp4~]#
客户端访问不受影响:
c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 126 | +---------------+-------+ c:\windows\system32>mysql -utest -p123456 -p6603 -h172.16.1.100 -e "show variables like 'server_id'"\ mysql: [warning] using a password on the command line interface can be insecure. +---------------+-------+ | variable_name | value | +---------------+-------+ | server_id | 127 | +---------------+-------+ c:\windows\system32>
在172.16.1.126上再次启动heartbeat,vip并不发生漂移,仍然停留在172.16.1.127上。
[root@hdp3~]#systemctl start heartbeat [root@hdp3~]# [root@hdp3~]# [root@hdp3~]#ip a 1: lo: mtu 65536 qdisc noqueue state unknown link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens32:mtu 1500 qdisc pfifo_fast state up qlen 1000 link/ether 00:50:56:a5:0f:77 brd ff:ff:ff:ff:ff:ff inet 172.16.1.126/24 brd 172.16.1.255 scope global ens32 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fea5:f77/64 scope link valid_lft forever preferred_lft forever [root@hdp3~]#
四、总结
之所以要使用mysql双主复制而不是主从复制,是因为本方案中并没有涉及读写分离,而是在两个等价的mysql服务器之间做读写负载均衡。 heartbeat利用实现了haproxy的ha,避免了haproxy的单点故障,出现故障时可以自动切换到正常的节点。 haproxy服务器提供了负载均衡的作用,将用户请求分发到多个backend。同时,一台mysql故障并不会影响整个集群,因为haproxy会检测backend的状态,并据此自动添加或删除集群中的mysql服务。 如本例的配置,需要考虑单台mysql服务器的负载最好不要超过50%,否则一旦某台mysql服务器故障,可能出现另一台正常mysql不堪重负的情况。 只采用本例的配置无法处理“脑裂”问题。例如,当心跳线闪断,slave获得vip,而此时master除了与slave失去联系,本身并无任何问题,也绑定同一vip。当心跳恢复正常时,就会出现vip的冲突等问题。脑裂是一个比较复杂的话题,通常需要引入其它插件,并且“多管齐下”才能彻底解决。