LVS全称Linux Virtual
Server,是基于网络层的负载均衡软件。由中国人开发,2.6版本后已进入linux内核。
keepalived是基于lvs的一个负载均衡管理软件。
本示例利用keepalived实现mysql
M-S-M-S集群的主从读写分离和故障自动切换(因应用的需要,不实现数据库的负载均衡)
数据库集群分为功能独立的2组,一组为常规mysql主从互备(mysql-sql),一组为添加handler
socket插件的mysql主从互备(mysql-nosql)
mysql主从互备可实现应用的读写分离,mysql主从互备可参考另一片博文
容灾策略:
1.一个keepalived挂机后可实现备机接管,实现虚拟ip的高科用,避免单点问题
2.数据库主从互备保障数据安全
3.mysql主(读)服务器挂机,由从服务器接管服务,服务ip地址不变,读写在同一台从服务器上
4.mysql从(写)服务器挂机,由主服务器接管服务,服务ip地址不变,读写在同一台主服务器上
4.挂机服务器重启后自动加入集群和服务虚拟ip,接管服务,恢复原来状态
示例网络架构
第一组mysql-sql,读写分离
VIP虚拟负载ip 10.10.10.240 读操作虚拟ip
VIP虚拟负载ip 10.10.10.241 写操作虚拟ip
mysql master server1 10.10.10.242 读服务器
mysql slave server1 10.10.10.243 写服务器
第二组mysql-nosql,读写分离
VIP虚拟负载ip 10.10.10.244 读操作虚拟ip
VIP虚拟负载ip 10.10.10.245 写操作虚拟ip
mysql master server2 10.10.10.246 读服务器
mysql slave server2 10.10.10.247 写服务器
2台keepalived服务器,解决单点问题,实现高可用
master keepalived 10.10.10.201
backup keepalived 10.10.10.202
每个keepalived服务器配置4组realserver实例,每组实例realserver只配一组mysql服务器,每2个realserver实现读写分离的vip互备,屏蔽负载均衡的功能。
1.两台keepalived服务器服务器查看内核是否支持lvs
modprobe -l | grep ipvs
如果有如下结果,说明内核支持,否则只能升级或编译内核了
kernel/net/netfilter/ipvs/ip_vs.ko
kernel/net/netfilter/ipvs/ip_vs_rr.ko
kernel/net/netfilter/ipvs/ip_vs_wrr.ko
kernel/net/netfilter/ipvs/ip_vs_lc.ko
kernel/net/netfilter/ipvs/ip_vs_wlc.ko
kernel/net/netfilter/ipvs/ip_vs_lblc.ko
kernel/net/netfilter/ipvs/ip_vs_lblcr.ko
kernel/net/netfilter/ipvs/ip_vs_dh.ko
kernel/net/netfilter/ipvs/ip_vs_sh.ko
kernel/net/netfilter/ipvs/ip_vs_sed.ko
kernel/net/netfilter/ipvs/ip_vs_nq.ko
kernel/net/netfilter/ipvs/ip_vs_ftp.ko
2.两台keepalived服务器分别安装keepalived
http://www.keepalived.org/software/keepalived-1.2.2.tar.gz
tar zxf keepalived-1.2.2.tar.gz
cd keepalived
./configure --prefix=/usr
make && make
install
3.两台keepalived服务器分别配置内核网络参数,开启ip转发
nano /etc/sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p
4.master keepalived(10.10.10.201)的keepalived配置
nano /etc/keepalived/keepalived.conf
global_defs {
router_idLVS_MYSQL_1
}
vrrp_instance VI_1 {
stateMASTER#负载均衡主服务
interface
bond0 #网卡做了bond
virtual_router_id 51
priority101#数越大优先级越高
advert_int
1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.10.10.240 #第一组mysql-sql的读操作VIP
10.10.10.241 #第一组mysql-sql的写操作VIP
10.10.10.244 #第二组mysql-nosql的读操作VIP
10.10.10.245 #第二组mysql-nosql的写操作VIP
}
}
virtual_server 10.10.10.240 3306 {
#第一组mysql-sql的配置,读操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.243 3306 #mysql
slave备机(写机),当所有real_server挂了之后添加切换
real_server
10.10.10.242 3306 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
virtual_server 10.10.10.241 3306 {
#第一组mysql-sql的配置,写操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.242 3306 #mysql
master主机(读机),当所有real_server挂了之后切换
real_server
10.10.10.243 3306 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
virtual_server 10.10.10.244 9998 {
#第二组mysql-nosql的配置,读操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.247 9998 #mysql
slave备机(写机),当所有real_server挂了之后切换
real_server
10.10.10.246 9998 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
virtual_server 10.10.10.245 9999 {
#第二组mysql-nosql的配置,写操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.246 9999 #mysql
master主机(读机),当所有real_server挂了之后切换
real_server
10.10.10.247 9999 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
5.backup keepalived(10.10.10.202)的keepalived配置
nano /etc/keepalived/keepalived.conf
global_defs {
router_idLVS_MYSQL_2
}
vrrp_instance VI_1 {
stateBACKUP#负载均衡主服务
interface
bond0 #网卡做了bond
virtual_router_id 51
priority80#数越大优先级越高
advert_int
1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.10.10.240 #第一组mysql-sql的读操作VIP
10.10.10.241 #第一组mysql-sql的写操作VIP
10.10.10.244 #第二组mysql-nosql的读操作VIP
10.10.10.245 #第二组mysql-nosql的写操作VIP
}
}
virtual_server 10.10.10.240 3306 {
#第一组mysql-sql的配置,读操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.243 3306 #mysql
slave备机(写机),当所有real_server挂了之后添加切换
real_server
10.10.10.242 3306 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
virtual_server 10.10.10.241 3306 {
#第一组mysql-sql的配置,写操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.242 3306 #mysql
master主机(读机),当所有real_server挂了之后切换
real_server
10.10.10.243 3306 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
virtual_server 10.10.10.244 9998 {
#第二组mysql-nosql的配置,读操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.247 9998 #mysql
slave备机(写机),当所有real_server挂了之后切换
real_server
10.10.10.246 9998 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
virtual_server 10.10.10.245 9999 {
#第二组mysql-nosql的配置,写操作
delay_loop
6
lb_algo wrr
#lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh
lb_kind DR
#负载均衡转发规则NAT|DR|RUN
#nat_mask
255.255.255.0
persistence_timeout 50
protocol
TCP
sorry_server
10.10.10.246 9999 #mysql
master主机(读机),当所有real_server挂了之后切换
real_server
10.10.10.247 9999 {
weight 3
notify_down "/etc/init.d/mysql.server restart" #检测到此realserver服务down后执行的自定义脚本,可以是mysql主从切换脚本
TCP_CHECK {
connect_timeout 1
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
对比下keepalived的master和backup配置,只有标红的3处不同
6.建立2组4台realserver的内核和网络配置脚本
第一组2台mysql-sql服务器的脚本
nano /bin/realserver.sh
#!/bin/bash
# description: Config realserver lo and apply
noarp
#Written by :NetSeek http://www.linuxtone.org
SNS_VIP1=10.10.10.240
SNS_VIP2=10.10.10.241
. /etc/rc.d/init.d/functions
case "$1" in
start)
ifconfig lo:0 $SNS_VIP1 netmask 255.255.255.255 broadcast
$SNS_VIP1
ifconfig lo:1 $SNS_VIP2 netmask 255.255.255.255 broadcast
$SNS_VIP2
/sbin/route add -host $SNS_VIP1 dev lo:0
/sbin/route add -host $SNS_VIP2 dev lo:1
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
ifconfig lo:1 down
route del $SNS_VIP1 >/dev/null
2>&1
route del $SNS_VIP2 >/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
第二组2台mysql-nosql服务器的脚本
nano /bin/realserver.sh
#!/bin/bash
# description: Config realserver lo and apply
noarp
#Written by :NetSeek http://www.linuxtone.org
SNS_VIP1=10.10.10.244
SNS_VIP2=10.10.10.245
. /etc/rc.d/init.d/functions
case "$1" in
start)
ifconfig lo:0 $SNS_VIP1 netmask 255.255.255.255 broadcast
$SNS_VIP1
ifconfig lo:1 $SNS_VIP2 netmask 255.255.255.255 broadcast
$SNS_VIP2
/sbin/route add -host $SNS_VIP1 dev lo:0
/sbin/route add -host $SNS_VIP2 dev lo:1
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
ifconfig lo:1 down
route del $SNS_VIP1 >/dev/null
2>&1
route del $SNS_VIP2 >/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
4台mysql分别执行
chmod +x /bin/realserver.sh
/bin/realserver.sh start
7.启动两个keepalived,即可实现mysql的主从自动切换
/etc/init.d/keepalived start
启动脚本如下
#! /bin/sh
#
# keepalived LVS cluster
monitor daemon.
#
# Written by Andres Salomon
#
### BEGIN INIT INFO
#
Provides: keepalived
#
Required-Start: $syslog $network
#
Required-Stop: $syslog $network
#
Default-Start: 2 3 4 5
#
Default-Stop: 0 1 6
# Short-Description: Starts keepalived
#
Description: Starts keepalived lvs loadbalancer
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/sbin/keepalived
NAME=keepalived
DESC=keepalived
CONFIG=/etc/keepalived/keepalived.conf
TMPFILES="/tmp/.vrrp /tmp/.healthcheckers"
#includes lsb functions
. /lib/lsb/init-functions
set -e
test -f $CONFIG || exit 0
test -f $DAEMON || exit 0
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
for file in $TMPFILES
do
test -e $file && test ! -L $file
&& rm $file
done
if start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid
\
--exec $DAEMON; then
log_end_msg 0
else
log_end_msg 1
fi
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
if start-stop-daemon --oknodo --stop --quiet --pidfile
/var/run/$NAME.pid \
--exec $DAEMON; then
log_end_msg 0
else
log_end_msg 1
fi
;;
reload|force-reload)
log_action_begin_msg "Reloading $DESC
configuration..."
if start-stop-daemon --stop --quiet --signal 1 --pidfile
\
/var/run/$NAME.pid --exec $DAEMON; then
log_end_msg 0
else
log_action_end_msg 1
fi
;;
restart)
log_action_begin_msg "Restarting $DESC" "$NAME"
start-stop-daemon --stop --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON
sleep 1
if start-stop-daemon --start --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON; then
log_end_msg 0
else
log_end_msg 1
fi
;;
*)
echo "Usage: /etc/init.d/$NAME
{start|stop|restart|reload|force-reload}"
>&2
exit 1
;;
esac
exit 0
8.数据库应用访问2组mysql服务时请使用vip访问,即10.10.10.240\241\244\245
另,java如使用连接池访问mysql,因mysql的自动切换,mac地址变化,可能造成链接失败,主要看连接池程序的健壮性如何了
9.lvs原理
realserver里配置的虚ip月keepalived里配置的虚ip保持一致,虚ip一定要被绑定到lo上。这是由lvs/dr模式的处理方式决定的。(使用VS/DR方法:调度器和服务
器组都必须在物理上有一个网卡通过不分断的局域网相连,如通过交换机或者高速的HUB相连。VIP地址为调度器和服务器组共享,调度器配置的VIP地址是
对外可见的,用于接收虚拟服务的请求报文;所有的服务器把VIP地址配置在各自的Non-ARP网络设备上,它对外面是不可见的,只是用于处理目标地址为
VIP的网络请求。在VS/DR中,调度器根据各个服务器的负载情况,动态地选择一台服务器,不修改也不封装IP报文,而是将数据帧的MAC地址改为选出
服务器的MAC地址,再将修改后的数据帧在与服务器组的局域网上发送。因为数据帧的MAC地址是选出的服务器,所以服务器肯定可以收到这个数据帧,从中可
以获得该IP报文。当服务器发现报文的目标地址VIP是在本地的网络设备上,服务器处理这个报文,然后根据路由表将响应报文直接返回给客户。
)
10.参考
http://database.51cto.com/art/201012/237204.htm
http://hi.baidu.com/dkf198314/blog/item/1ca20a36fae3165c241f14df.html
http://www.keepalived.org/sery-lvs-cluster.pdf