使用LVS+keepalived实现mysql负载均衡的实践和总结
前言
经过一段时间的积累,数据库的架构就需要根据项目不断的进行变化。
从单台数据库,到了两台数据库的主从,再到读写分离,再到双主,现在进一步需要更多的数据库服务器去支撑更加可怕的访问量。
那么经过那么多的学习,也了解到,进一步的架构还有很多,负载均衡,集群,等等。接下来作一一说明。
负载均衡的意义
可能有很多人一开始听见这个名词的时候,都觉得很厉害的样子。然后也不知道它是干嘛的,总觉得听起来很厉害。
举个例子,把10件事原本要求一个人完成,现在分给10个人去做。这就是负载均衡。
负载:压力很大的事,均衡:按照一定的规则分给不同的人去完成。
这样理解,你就能很清楚为什么要用负载均衡了,因为一个人忙不过来了。
负载均衡各种实现方式的比较
查阅相关资料发现,mysql负载均衡的实现方式真的有很多,如常见的nginx,LVS,HAProxy等等。还有一些不开源的实现方式这边就不列举了,下面对这些常见的方式进行比较。
一、nginx
1、首先nginx具有功能有:反向代理、负载均衡、HTTP服务器、正向代理。在反向代理上面很出众。
2、工作在网络的第七层也就是应用层,对于网络的稳定性依赖比较小,只要能ping通就能进行负载均衡。
3、某个节点出现问题,能在过程中就切换,比如上传文件,用户上传到一半,服务器突然宕机,nginx会把上传切到另一台服务器上面重新处理,而LVS如果没有任何第三方的检测软件等普通情况下直接就中断了和用户的请求。
4、配置简单,nginx毕竟面向的是应用,相对于别的来说配置简单,而且网上资料毕竟充足,基本上需要的配置都能查到资料。
5、动静分离,让动态网站里面的不变的资源和经常变动的资源分开,nginx能提供静态资源的访问,从而减轻tomcat等应用容器的压力。
6、反向代理,这里不进行细说,因为我们重点是负载均衡,但是nginx确实在这方面很出众。也是你选择的理由。
7、但是nginx仅仅支持的是http、https、email协议,适用的范围较小,对于服务器的检测只是通过端口检测,而不支持通过url检测。
8、在速度上面,毕竟nginx是工作在应用层的,和LVS相比,LVS是工作在网络层,所以性能上面自然没有LVS来的强大。
二、LVS
1、工作在网络层,抗负载均衡能力强大,没有流量产生,所以性能出众,对内存和cup消耗较低。
2、经常使用LVS+keepalived进行双机热备,所以相对来说稳定可靠。
3、无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了负载均衡服务器的IO性能不会受到大流量的影响。因为作为负载均衡服务器来说,当用户访问量大的时候,其实第一个访问的就是他自己,所以它自己的性能影响就变得重要。
4、工作范围广,几乎可以应对各种负载均衡的要求,没有很强的限制。
5、但是相对来说,配置相对复杂一些,不支持动静分离,一些健康检测需要自行编写脚本完成。
三、HAProxy
1、与nginx类似,但是支持session的保持,cookie的引导,支持通过获取指定的url来检测后端服务器的状态。
2、在并发处理的效率上面,比nginx来的高。
3、支持TCP协议的负载均衡转发。
4、负载均衡的策略比较多,可供选择的比较多。
5、速度和影响上面,没有LVS来的好。
那么你们一定会有问题,那么到底该如何选择呢?
其实网上比较多的方案都是使用Nginx/HAProxy+keepalived作为前端的负载均衡;而后端采用LVS+keepalived对一主多从的mysql数据库进行负载均衡。但是这也只是比较多的方案。
在我看来方案都是需要结合实际情况来考虑的。如果你的访问量并不是很大,其实nginx就完全够用了,配置简单,而且能实现反向代理和动静分离,而且出现问题也比较容易解决。而且当前的性能完全足够满足用户需求即可。而当你的访问量特别大的时候,比如PV超百万或者更大,那么就需要考虑使用LVS了,如果作为负载均衡的服务器挂了,那么你后面服务器再多也没用了,LVS首先能保证的就是你的负载均衡服务器不会挂。
所以可能你还是需要从实际的角度考虑,是否这样的架构满足你当前的性能支持。
LVS+keepalived实现mysql负载均衡
因为之前使用nginx做过反向代理和负载均衡,所以这次使用LVS+keepalived实现mysql负载均衡,看看区别到底在哪里。
首先我先实现的是LVS+keepalived对于Apache服务器的负载均衡,因为对于mysql,负载均衡是实现应该是和Apache一样的,而最不同的就是检测的方式,网站的访问一般采用80端口,而且只需要进行tcp的检测就知道是否能访问这个网站,keepalived默认就提供了这样的健康检测方式,这样我们就不需要过多的配置。而对于mysql状态来说,简单的tcp请求是不能检测出mysql服务是否正常启动或者mysql是否为可以被访问的状态。所以我们先从简单的着手。
下面是过程:
1、准备工作:确定各个机器的ip,关闭防火墙等等
2、配置lvs(这里的配置是在服务器,也就是安装apach的服务器上面,而不是负载均衡服务器上!!!!)
cd /etc/init.d/
vi realserver
SNS_VIP=192.168.75.100 /etc/rc.d/init.d/functions case "$1" in start) ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP /sbin/route add -host $SNS_VIP dev lo:0 echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce sysctl -p >/dev/null 2>&1 echo "RealServer Start OK" ;; stop) ifconfig lo:0 down route del $SNS_VIP >/dev/null 2>&1 echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce echo "RealServer Stoped" ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0
注意SNS_VIP需要根据你当前的几台机器的ip来设置
我的两台服务器ip为192.168.75.128和192.168.75.130
负载均衡服务器的ip为192.168.75.129
所以我设置VIP为192.168.75.100
这里的VIP就是我们最终需要进行访问的IP地址,而并非访问真实的IP地址
保存脚本文件后更改该文件权限:chmod 777 realserver
开启realserver服务:service realserver start
两台都一样这样配置完成之后
3、配置负载均衡服务器
yum install -y keepalived
cd /etc/keepalived
> keepalived.conf
vi keepalived.conf
global_defs { router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的 } vrrp_instance VI_1 { state MASTER #指定Keepalived的角色,MASTER为主,BACKUP为备 interface eth1 #你的网卡号码 virtual_router_id 51 #虚拟路由编号,主备要一致 priority 100 #定义优先级,数字越大,优先级越高,主DR必须大于备用DR advert_int 1 #检查间隔,默认为1s authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.75.100 #定义虚拟IP(VIP)为192.168.75.101,可多设,每行一个 } } # 定义对外提供服务的LVS的VIP以及port virtual_server 192.168.75.100 80 { delay_loop 6 # 设置健康检查时间,单位是秒 lb_algo wrr # 设置负载调度的算法为wlc lb_kind DR # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式 nat_mask 255.255.255.0 persistence_timeout 0 protocol TCP real_server 192.168.75.130 80 { # 指定real server1的IP地址 weight 3 # 配置节点权值,数字越大权重越高 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.75.128 80 { # 指定real server2的IP地址 weight 3 # 配置节点权值,数字越大权重越高 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }
其中需要修改的就是三个ip地址和
网卡号码
interface eth1这是个坑,很多人最后不成功就败在这里,并不是每个人的系统网卡都是eth1的,你需要百度一下查询本机网卡的命令,然后修改为你自己网卡的名字。
启动服务之后就行了:service keepalived start
这时你就已经实现了负载均衡的基本功能了,访问时注意打开两台服务器上的apach。还要注意的是访问的是你的虚拟IP,我这里是192.168.75.100,不要访问真实的IP。
如果没有成功:service keepalived status,查看情况,把出现的报错在网上搜索一下进行解决。这里就不一一列举错误了。或者使用ipvsadm命令查看连接情况。
那么这时肯定就会有人说,难道mysql的负载均衡就只要把端口改成3306就可以了吗?
讲道理呢,如果你只要实现的是负载均衡的话,那确实,改成3306,就可以了,只要装好mysql然后把两台mysql的密码一样,模拟两台主从就可以尝试着访问了。
也就是修改配置如下:
global_defs { router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的 } vrrp_instance VI_1 { state MASTER #指定Keepalived的角色,MASTER为主,BACKUP为备 interface eth1 #你的网卡号码 virtual_router_id 51 #虚拟路由编号,主备要一致 priority 100 #定义优先级,数字越大,优先级越高,主DR必须大于备用DR advert_int 1 #检查间隔,默认为1s authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.75.100 #定义虚拟IP(VIP)为192.168.75.101,可多设,每行一个 } } # 定义对外提供服务的LVS的VIP以及port virtual_server 192.168.75.100 3006 { delay_loop 6 # 设置健康检查时间,单位是秒 lb_algo wrr # 设置负载调度的算法为wlc lb_kind DR # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式 nat_mask 255.255.255.0 protocol TCP real_server 192.168.75.130 3306 { # 指定real server1的IP地址 weight 3 # 配置节点权值,数字越大权重越高 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 3306 } } real_server 192.168.75.128 3306 { # 指定real server2的IP地址 weight 3 # 配置节点权值,数字越大权重越高 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 3306 } } }
而且很多我也看到有博客写的也是这样的我也这样试过确实实现了:如下图,我用本地图形化界面进行访问尝试
我在128和130的mysql上面都建了一个数据库进行区别,访问同一个192.168.75.100就能访问到两个不同的数据库了,实现了负载均衡。
但是很多人到了这步之后就万事大吉了,都觉得实现了,就好了,作为程序员应该有边界情况的考虑习惯。如果你把某一台数据库的服务停止之后就会发现,不对了。
比如这里我把128的数据库服务停止之后,再次进行访问,130照常能访问,但是第二次访问到128的时候,出现了
很多人不以为然,但是这就出现问题了,负载均衡服务器一个重要的点就是,当有一台服务器无法访问的时候,应该把这个请求转移到其他的服务器上面去,这里128的服务器挂了,其实我们应该一直访问到130,而并非收到这样一个访问不到的请求。如果这样出现在现实之中,就会造成,sql执行失败,而并不会均衡到另一台上面去,这也就是我之前说的,mysql的检测问题了,也就是数据库负载均衡和普通的负载均衡的区别。
keepalived本身提供的检测方式有:
keepalived对后端realserver的健康检查方式主要有以下几种
-
TCP_CHECK:工作在第4层,keepalived向后端服务器发起一个tcp连接请求,如果后端服务器没有响应或超时,那么这个后端将从服务器池中移除。
-
HTTP_GET:工作在第5层,向指定的URL执行http请求,将得到的结果用md5加密并与指定的md5值比较看是否匹配,不匹配则从服务器池中移除;此外还可以指定http返回码来判断检测是否成功。HTTP_GET可以指定多个URL用于检测,这个一台服务器有多个虚拟主机的情况下比较好用。
-
SSL_GET:跟上面的HTTP_GET相似,不同的只是用SSL连接
-
MISC_CHECK:用脚本来检测,脚本如果带有参数,需将脚本和参数放入双引号内。脚本的返回值需为:
0) 检测成功
1) 检测失败,将从服务器池中移除
2-255)检测成功;如果有设置misc_dynamic,权重自动调整为 退出码-2,如退出码为200,权重自动调整为198=200-2。
-
SMTP_CHECK:用来检测邮件服务的smtp的
这几种方式能满足我们需求的只有MISC_CHECK方式
简单的说,我们需要写一个脚本去检测Msql的状态,如果mysql不能被访问,则从负载均衡服务器中把这个服务器的ip移除。
下面是修改keepalived的配置文件
! Configuration File for keepalived global_defs { #全局标识模块 router_id LVS_DEVEL } vrrp_instance VI_1 { state MASTER #本实例启动状态:MASTER/BACKUP interface eno1 #监控的网络接口 virtual_router_id 51 #vrrp实例(同一个组主备服务器设置一样) priority 100 #优先级高的为master,不能超过255。(BACKUP可设置为50) advert_int 1 #均衡器检测间隔1秒(服务器设置都一样) authentication { #验证类型及密码(服务器设置都一样) auth_type PASS #认证方式,PASS或AH auth_pass 123456 #认证密码 } virtual_ipaddress { #虚拟ip地址virtual_ipaddress,可以定义多个 192.168.75.100 } } virtual_server 192.168.75.100 3306 { #定义虚拟服务器,与上面的virtual_server一样 delay_loop 6 #健康检查时间间隔,6秒 lb_algo wrr #负载均衡调度算法:rr|wrr|lc|wlc|sh|dh|lblc lb_kind DR #负载均衡转发规则:NAT|DR|TUN nat_mask 255.255.255.0 persistence_timeout 0 #回话保持时间50秒,动态服务建议开启 protocol TCP #转发协议protocol,一般有tcp和udp两种 #后端真实服务器,有几台就设置几个 real_server 192.168.75.128 3306 { weight 1 #权重越大负载分越大,0表示失效 MISC_CHECK { #健康检查方式:HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK connect_timeout 60 nb_get_retry 3 delay_before_retry 3 connect_port 3306 misc_path "/etc/keepalived/mysql_check.sh 192.168.75.128" misc_timeout 60 misc_dynamic } } real_server 192.168.75.130 3306 { weight 1 MISC_CHECK { connect_timeout 60 nb_get_retry 3 delay_before_retry 3 connect_port 3306 misc_path "/etc/keepalived/mysql_check.sh 192.168.75.130" misc_timeout 60 misc_dynamic } } }
misc_path "/etc/keepalived/mysql_check.sh 192.168.75.128" 这个参数是你的脚本所在的位置,空格后面的ip为输入的参数
misc_timeout 这个是超时的时间,建议配置的时间长一点,有时候mysql状态返回的很慢。
然后是脚本的编写,这里是我从网上找的,然后修改了一下的脚本,只是简单的用ping命令检测了一下,但是实际检测应该需要比这个更加细致。比如检测数据库连接数等等。需要注意的是,因为检测使用了mysql的ping命令所以在负载均衡服务器上面需要安装一个mysql。能提供mysql命令运行即可。
下面是脚本:
#!/bin/bash MYSQL_PING=`/usr/local/mysql/bin/mysqladmin -u root -h $1 ping` MYSQL_OK="mysqld is alive" if [[ ${MYSQL_PING} == ${MYSQL_OK} ]]; then echo "yes" exit 0 else echo "no" exit 1 fi
其中我把mysql的密码配置在了/etc/my.cnf文件下面,如下所示,因为在命令中写密码会有警告
[mysqladmin]
password=******
需要注意的是,你需要在启动keepalived之前测试你的脚本是否真的正常,是否显示yes和no当数据库服务启动和关闭的时候(记得给脚本足够的权限,否则无法运行)
./mysql_check.sh 192.168.75.128
显示:yes
如果当数据库服务处于打开状态依旧无法访问则需要查看mysql是不是禁止了外部的访问等限制问题。
最后重启keepalived即可
service keepalived restart
总结和思考
1、根据实际情况去选择相应的架构实现相应的功能。
2、keepalived还有备份,各种不同的负载均衡策略,等等配置,需要进一步深入学习。
3、对于mysql的检测,有一些第三方的软件可以实现精细化的检测,从而更好的进行负载均衡的选择。
4、对于一主多从的情况,对于多态从服务器可以使用负载均衡,但是当写的能力也不够用的时候需要进一步升级架构,为数据库集群。可以使用mysql cluster等,然后再进行负载均衡。
5、总之这里做的只是实验,具体到实际情况之下可能有很多配置都需要进行改动,没有经过实际的项目测试,所以很多问题可能还没有遇到,需要经过实际项目的经验才能有更好的提升。
参考网站:
借助LVS+Keepalived实现负载均衡http://www.cnblogs.com/edisonchou/p/4281978.html(apach是安装这个流程走的)
LVS+Keepalived实现mysql的负载均衡http://www.cnblogs.com/tangyanbo/p/4305589.html(大致流程都是依照这个来做的,写的很棒)
Nginx/LVS/HAProxy负载均衡软件的优缺点详解http://www.ha97.com/5646.html(解释了各个优缺点,很详细)
Lvs之NAT、DR、TUN三种模式的应用配置案例 http://www.sxt.cn/info-3188-u-324.html
keepalived的健康检查方式 http://blog.chinaunix.net/uid-10480699-id-5179873.html
改良版本的使用keepalived构建高可用mysql-HAhttp://kongchen.github.io/keepalived-mysql-ha/(这个是把keepalived和mysql安装在同一台服务器上,利用keepalived本身去对mysql做健康检测)
国外的一个上述的配置实践https://www.atlantic.net/community/howto/multi-master-mysql-percona-keepalived/(这个脚本与我写的不同,可以做参考进行修改)