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,接管服务,恢复原来状态

示例网络架构

keepalived主从模式搭建 keepalived mysql主从_TCP

第一组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