haproxy实现mysql负载均衡

转:http://blog.chinaunix.net/uid-20785090-id-4617239.html

https://blog.csdn.net/tuolaji8/article/details/52870791

对于mysql的读请求可以通过LVS,F5或是HAProxy软件来转发到后台的多个Mysql服务器上,从而实现了扩展的目标.
本文的例子使用HAProxy转发请求到两台mysql从库上.

Mysql:mysql 5.5
HAProxy IP: 172.28.10.192
Mysql Slave1:172.28.10.145
Mysql Slave2:172.28.10.150

在172.28.10.192上编译和安装haproxy
[root@cscscslocalhost 1109]# tar -zvfx haproxy-1.4.21.tar.gz

[root@cscscslocalhost haproxy-1.4.21]#make TARGET=linux26 PERFIX=/usr/local/haproxy

[root@cscscslocalhost haproxy-1.4.21]# make install PREFIX=/usr/local/haproxy
install -d /usr/local/haproxy/sbin
install haproxy /usr/local/haproxy/sbin
install -d /usr/local/haproxy/share/man/man1
install -m 644 doc/haproxy.1 /usr/local/haproxy/share/man/man1
install -d /usr/local/haproxy/doc/haproxy
for x in configuration architecture haproxy-en haproxy-fr; do \
install -m 644 doc/$x.txt /usr/local/haproxy/doc/haproxy ; \

--查看haproxy版本,如有返回表示安装成功

[root@cscscslocalhost haproxy-1.4.21]# haproxy -v
HA-Proxy version 1.4.21 2012/05/21
Copyright 2000-2012 Willy Tarreau <w@1wt.eu>

[root@cscscslocalhost haproxy]# cd /usr/local/haproxy

--在haproxy安装目录中,新建conf和logs目录

[root@cscscslocalhost haproxy]# mkdir conf
[root@cscscslocalhost haproxy]# mkdir logs

[root@cscscslocalhost haproxy]# ls
conf  doc  logs  sbin  share

--编写haproxy的配置文件,在haproxy的软件包中examples中有例子,可以复制过来再修改.
值得注意的有轮询方式,转发方式,每服务器的权重等信息。

[root@cscscslocalhost haproxy]# vi /etc/haproxy.cfg

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        #log loghost    local0 info
        maxconn 4096
        chroot /usr/share/haproxy
        uid 99
        gid 99
        daemon
        #debug
        #quiet

defaults
        log     global
        mode    tcp
        option  httddplog
        option  dontlognull
        retries 3
        redispatch
        maxconn 2000
        contimeout      5000
        clitimeout      50000
        srvtimeout      50000

listen mysql_proxy
    bind 0.0.0.0:23306
    mode tcp
    balance roundrobin 
    server db1 172.28.10.145:3307 check inter 2000 rise 2 fall 5 weight 1
    server db2 172.28.10.150:3306 check inter 2000 rise 2 fall 5 weight 1

--新建对应的chroot目录,否则会报错,haproxy不能正常启动

[root@cscscslocalhost haproxy]# haproxy -f /etc/haproxy.cfg 
[ALERT] 314/142955 (12657) : [haproxy.main()] Cannot chroot(/usr/share/haproxy).
[root@cscscslocalhost haproxy]# mkdir /usr/share/haproxy

--启动haproxy,查看端口,确保启动成功.

[root@cscscslocalhost haproxy]# haproxy -f /etc/haproxy.cfg 
[root@cscscslocalhost haproxy]# netstat -nltp | grep haproxy
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name             
tcp        0      0 0.0.0.0:23306               0.0.0.0:*                   LISTEN      12674/haproxy

--修改日志的相关配置,让haproxy能够输出日志信息

[root@cscscslocalhost log]# vi /etc/syslog.conf 
local6.*   /var/log/haproxy.log

[root@cscscslocalhost haproxy]# vi /etc/sysconfig/syslog 
SYSLOGD_OPTIONS=" -r -m 0"

[root@cscscslocalhost haproxy]# service syslog restart
Shutting down kernel logger: [  OK  ]
Shutting down system logger: [  OK  ]
Starting system logger: [  OK  ]
Starting kernel logger: [  OK  ]

--到此haproxy已经能够正常的转发mysql请求到后端的真正mysql服务器上了。
[root@cscscslocalhost haproxy]# mysql -u root -p123456 --host=127.0.0.1 --port=23306
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
| sports_sso         |
| zabbix             |

--使用sysbecn来测试一下单台服务器的处理能力和haproxy进行负载均衡后的处理能力.

先测试单机的处理能力

[root@localhost ~]# /usr/local/bin/sysbench --test=oltp --mysql-user=root --mysql-password=123456  --mysql-db=db1 --mysql-host=172.28.10.150 --mysql-port=3306 --oltp-table-size=500  --oltp-read-only=true  --num-threads=32 run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

No DB drivers specified, using mysql
Running the test with following options:
Number of threads: 32

Doing OLTP test.
Running mixed OLTP test
Using Special distribution (12 iterations,  1 pct of values are returned in 75 pct cases)
Using "BEGIN" for starting transactions
Using auto_inc on the id column
Maximum number of requests for OLTP test is limited to 10000
Threads started!
Done.

OLTP test statistics:
    queries performed:
        read:                            612122
        write:                           120699
        other:                           53723
        total:                           786544
    transactions:                        10000  (56.75 per sec.)
    deadlocks:                           33723  (191.37 per sec.)
    read/write requests:                 732821 (4158.51 per sec.)
    other operations:                    53723  (304.86 per sec.)

Test execution summary:
    total time:                          176.2218s
    total number of events:              10000
    total time taken by event execution: 5632.1118
    per-request statistics:
         min:                                 12.98ms
         avg:                                563.21ms
         max:                              16905.54ms
         approx.  95 percentile:            2218.47ms 

测试haproxy转发后的处理能力.

[root@localhost ~]# /usr/local/bin/sysbench --test=oltp --mysql-user=root --mysql-password=123456  --mysql-db=db1 --mysql-host=172.28.10.192 --mysql-port=23306 --oltp-table-size=500  --oltp-read-only=true  --num-threads=32 run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

No DB drivers specified, using mysql
Running the test with following options:
Number of threads: 32

Doing OLTP test.
Running mixed OLTP test
Using Special distribution (12 iterations,  1 pct of values are returned in 75 pct cases)
Using "BEGIN" for starting transactions
Using auto_inc on the id column
Maximum number of requests for OLTP test is limited to 10000
Threads started!
Done.

OLTP test statistics:
    queries performed:
        read:                            225316
        write:                           63519
        other:                           26094
        total:                           314929
    transactions:                        10000  (210.44 per sec.)
    deadlocks:                           6094   (128.24 per sec.)
    read/write requests:                 288835 (6078.33 per sec.)
    other operations:                    26094  (549.13 per sec.)

Test execution summary:
    total time:                          47.5188s
    total number of events:              10000
    total time taken by event execution: 1512.8555
    per-request statistics:
         min:                                 16.23ms
         avg:                                151.29ms
         max:                               2262.30ms
         approx.  95 percentile:             465.13ms

Threads fairness:
    events (avg/stddev):           312.5000/78.56
    execution time (avg/stddev):   47.2767/0.18

通过结果对比测试,我们发现haproxy做前端的只读负载分发后,处理能力得到提高了.

root@test-VirtualBox:/usr/local/haproxy/conf# vim haproxy.cfg

global
    maxconn 51200
    chroot /usr/local/haproxy
    uid 99
    gid 99
    daemon
    #quiet
    nbproc 1
    pidfile /usr/local/haproxy/logs/haproxy.pid 
defaults
        mode http
        #retries 2
        option redispatch
        option abortonclose
        timeout connect 5000ms
        timeout client 30000ms
        timeout server 30000ms
        #timeout check 2000
        log 127.0.0.1 local0 err #[err warning info debug]
        balance roundrobin
# option httplog
# option httpclose
# option dontlognull
# option forwardfor 
listen admin_stats
        bind 0.0.0.0:8888
        option httplog
        stats refresh 30s
        stats uri /stats
        stats realm Haproxy Manager
        stats auth admin:admin
        #stats hide-version 
listen test1
        bind :12345
        mode tcp
        server t1 10.77.50.111:8088
        server t2 10.77.50.111:8099 
listen test2 
	bind :80
        option httpclose
        option forwardfor
        server s1 10.77.50.111:8088 check weight 1 minconn 1 maxconn 3 check inter 40000
        server s2 10.77.50.68:808 check weight 1 minconn 1 maxconn 3 check inter 40000
listen mysql_proxy
    bind 0.0.0.0:23306
    mode tcp
    balance roundrobin 
    server db1 10.77.50.111:3306 check inter 2000 rise 2 fall 5 weight 1
    server db2 10.77.50.232:3306 check inter 2000 rise 2 fall 5 weight 1

关于此两者,随便google一下都会有大量的文章,因此这里也不用介绍如何来进行安装和配置了。主要从一个整体方案的角度来描述什么要这样做,以及这样做所解决的问题。

所有的系统,都是先经历一个单台机器搞所有业务的时代,一个程序+一个mysql数据库,就可以满足开发及第一个版本上线的要求。随着,数据的增加以及业务的增长,这些应用就面临一个访问量的扩大以及扩展的问题。最简单的扩展就是水平扩展,原来由一个mysql增加为2个或多个,形成一个集群,这样最简单的能力就是提供更强的服务能力。如原来的访问量支持每秒1000,现在可以支持2000(理想值),相当于将服务能力分散到多个节点。这里面涉及到多个问题,首先就是数据的相互备份,然后就是如何分配计算能力,外部如何来访问等。本文引入HaProxy和KeepAlived主要处理的就是一个外部访问问题。

在后面的介绍当中,假定有2个mysql,分别为mysqlA和mysqlB.

haproxy请求分发

可以理解为通过nginx来作后端的负载均衡,HaProxy可以通过监听一个统一的端口对外提供能力,然后内部进行分发。除支持http7层处理外,还顺便为mysql支持4层转发。(更高级的可以考虑采用lvs) 在这里,将两个mysql分别配置在backend当中,并且通过option mysql-check进行相应服务的检查。

程序进行访问时,就不再访问具体的mysql机器,而是访问这个HaProxy所在的机器。这里就提到需要一个额外的机器来提供服务,但是由于只为HaProxy使用,其根据很低,一个最低配机器即可,费用不大。同时,相应的端口也填写HaProxy所暴露的端口即可。对外即认为也只仍然只有一个mysql,即对外是透明的。

HaProxy在进行处理时,将自己根据相应的策略进行转发,最简单的策略就是轮询(ribbon),当然其它加权或者是随机等,需要具体进行配置。同时,根据设定的具体时间间隔,对后端服务进行有效性检测,当mysqlA或B不能工作时,将自动从可用列表中移除。

在加上HaProxy之后,负载的问题被解决,但另一个问题又来了,即服务单点的问题。如果一旦这个HaProxy机器挂掉(或网络原因)。虽然,mysql服务器没挂,但整个服务也是不可用了。前端程序不会自动退回到去访问原始的mysql(甚至由于防火墙的问题,它也不能访问)。这时候就要用到另一个东西,保证HaProxy不会成为单点,即KeepAlived。

KeepAlived高可用

保证服务不会单点的作法就是加机器,但加机器就会出现多个ip,如何保证前端程序使用单个ip又能保证后端的实际处理机器为多台,这就是KeepAlived的作用。

我们为了保证HaProxy的高可用,已经又加了一个机器,即为HaProxyA和HaProxyB(相当于原来的2个mysql机器,又加了2台HaProxy机器)。

通过KeepAlived,我们可以创造出第3个IP,由ip3来对外提供服务,但是与HaProxy的转发性质不同,这里的ip3实际上就是HaProxyA和HaProxyB的一个同名映射。可以理解为HaProxyA和HaProxyB都在争抢这个ip,哪个争抢到了,就由哪个来提供服务。可以理解为在一定的时间内,保证以下关系

IP3<=>IP1
IP2 wait IP3

因为KeepAlived不提供任何处理能力,实际上最终的处理能落在能够处理信息的程序上。因此,我们需要将KeepAlived和HaProxy部署在一起,即KeepAlived负责抢ip,接收前端的请求,在接收到了请求之后,由系统自动将请求分发到同一个机器上的HaProxy上进行处理。即一个机器有2个IP,ip1负责接收请求,ip2负责实际的信息处理(比喻而已,就是如何监听请求和端口处理程序)

在前面的处理模型当中,因为KeepAlived不处理请求,因此如果它所在机器上的HaProxy如果不可用,实际上这个模型也是有问题的。因此KeepAlived又要来监听自己机器上的HaProxy是否有效。在配置中,通过track_script指令可以达到这个效果,与HaProxy的工作模式差不多,它可以定时执行监控脚本来查看HaProxy是否可用。如果不可用,有2种处理办法,一种就是强行再启动HaProxy,另一种就是取消自己的抢占ip位(如将自己给kill掉),将相应的ip3的位置给让出来。这样IP2就能自动与IP3进行绑定(比喻),即由IP2来提供处理能力了。

在KeepAlived的配置之上,在单个时刻只有1台机器在进行工作,另一个机器在进行准备,可以理解为这里的服务能力只有1半。好在KeepAlived和HaProxy所占用资源都较小,费用不高。

最终部署模型

  1. MysqlA(ip5)和MysqlB(ip6)水平扩展,通过双主进行数据通信,并且同时提供服务能力
  2. 通过HaProxyA(ip3)和HaProxyB(ip4)提供mysql的负载能力,将请求路由到指定的mysql服务器,同时监控后端的mysql数据库可用性
  3. 将KeepAlivedA和KeepAlivedB分别和HaProxyA和HaProxyB部署在一起,同时绑定VIP ip1,对外提供访问ip,同时监控本机的HaProxy的可用性

通过以上的部署,一个最前端的数据访问可能是以下的访问路径

IP1=>IP3->IP5 IP1=>IP3->IP6 IP1=>IP4->IP5 IP1=>IP4->IP6

注:本文假定mysql为双主部署,而不是主备,主要考虑不要浪费资源,并且没有额外的备份,主要是简化模型

    A+
发布日期:2015年09月17日  所属分类:未分类

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: