天天看點

使用HAProxy實作MySQL多slave的讀負載均衡

HAProxy提供高可用性、負載均衡以及基于TCP和HTTP應用的代理,支援虛拟主機,它是免費、快速并且可靠的一種解決方案。而mysql一主多從是比較通用的架構,我們可以利用haproxy在tcp層對資料庫的讀請求進行代理,進而實作多個從庫讀的負載均衡。

目前公司的業務都是一主多從,想要把查詢分到多個從庫上,都是通過開發維護多個從庫的配置來實作,這樣比較麻煩,通過haproxy開發隻需要一個配置項,開發不用理會後端有多少從庫,而且可以把多個從庫都利用起來,同時背景db有故障haproxy可以自動摘除,不需要像原先那樣需要開發改資料庫配置。

環境說明:

haproxy: 10.32.1.64

salve1: 10.32.1.67

slave2: 10.32.1.73

一,安裝haproxy

大部分的linux系統都自帶有haproxy安裝包,我們以centos 6系統為例,直接安裝系統自己的包。

<code># yum install -y haproxy</code>

<code># haproxy -v</code>

<code>HA-Proxy version 1.5.4 2014</code><code>/09/02</code>

二,準備haproxy配置檔案

<code>cd</code> <code>/etc/haproxy</code>

<code>vim haproxy.cfg</code>

<code>global</code>

<code>        </code><code>log 127.0.0.1 local2</code>

<code>        </code><code>chroot </code><code>/var/lib/haproxy</code>

<code>        </code><code>pidfile </code><code>/var/run/haproxy</code><code>.pid</code>

<code>        </code><code>maxconn 4000</code>

<code>        </code><code>user haproxy</code>

<code>        </code><code>group haproxy</code>

<code>        </code><code>daemon</code>

<code>defaults</code>

<code>        </code><code>mode tcp</code>

<code>        </code><code>log global</code>

<code>        </code><code>option httplog</code>

<code>        </code><code>option dontlognull</code>

<code>        </code><code>retries 3</code>

<code>        </code><code>timeout http-request 10s</code>

<code>        </code><code>timeout queue 1m</code>

<code>        </code><code>timeout connect 10s</code>

<code>        </code><code>timeout client 1m</code>

<code>        </code><code>timeout server 1m</code>

<code>        </code><code>timeout http-keep-alive 10s</code>

<code>        </code><code>timeout check 10s</code>

<code>        </code><code>maxconn 3000</code>

<code>## 定義一個監控頁面,監聽在1080端口,并啟用了驗證機制</code>

<code>listen stats</code>

<code>        </code><code>mode http</code>

<code>        </code><code>bind 0.0.0.0:1080</code>

<code>        </code><code>stats </code><code>enable</code>

<code>        </code><code>stats hide-version</code>

<code>        </code><code>stats uri </code><code>/haproxyadmin</code><code>?stats</code>

<code>        </code><code>stats realm Haproxy\ Statistics</code>

<code>        </code><code>stats auth admin:admin</code>

<code>        </code><code>stats admin </code><code>if</code> <code>TRUE</code>

<code>frontend mysql</code>

<code>        </code><code>bind *:3306</code>

<code>        </code><code>#log global</code>

<code>        </code><code>option tcplog</code>

<code>        </code><code>default_backend mysqlservers</code>

<code>backend mysqlservers</code>

<code>        </code><code>balance leastconn</code>

<code>        </code><code>server dbsrv1 10.32.1.73:3306 check port 3306 rise 1 fall 2 maxconn 300</code>

<code>        </code><code>server dbsrv2 10.32.1.67:3306 check port 3306 rise 1 fall 2 maxconn 300</code>

可以通過下面的指令檢測配置檔案是否正确:

<code># haproxy -f /etc/haproxy/haproxy.cfg -c</code>

出現Configuration file is valid表示沒問題,如果配置檔案有誤的話檢測的時候會有提示,根據提示進行修改就可以了。

添加haproxy系統帳号:

# useradd haproxy

三:開啟haproxy日志

為haproxy設定單獨的日志目錄

# mkdir /var/log/haproxy

# chown haproxy:haproxy /var/log/haproxy

修改rsyslog.cfg檔案

# vim /etc/rsyslog.cnf 

    $ModLoad imudp  

    $UDPServerRun 514 

    将這兩行前的#去掉。

    在local7.*                                                /var/log/boot.log之後添加如下内容

    # Save haproxy log  

    local2.*                       /var/log/haproxy/haproxy.log

修改rsylog檔案

# vim /etc/sysconfig/rsyslog 

SYSLOGD_OPTIONS=""  改為  SYSLOGD_OPTIONS="-r -m 2 -c 2" 

重新開機日志服務讓配置生效

#/etc/init.d/rsyslog  restart

四,啟動haproxy

<code># /etc/init.d/haproxy start</code>

<code># ps -ef | grep haproxy</code>

<code>haproxy  12648     1  0 02:34 ?        00:00:04 </code><code>/usr/sbin/haproxy</code> <code>-D -f </code><code>/etc/haproxy/haproxy</code><code>.cfg -p </code><code>/var/run/haproxy</code><code>.pid</code>

<code># netstat -tunlp | grep 12648</code>

<code>tcp        0      0 0.0.0.0:1080                0.0.0.0:*                   LISTEN      12648</code><code>/haproxy</code>       

<code>tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      12648</code><code>/haproxy</code>       

<code>udp        0      0 0.0.0.0:60182               0.0.0.0:*                               12648</code><code>/haproxy</code>

五,測試負載均衡

在slave1和slave2上分别給haproxy的ip授權:

<code>&gt; grant all privileges on *.* to [email protected] identified by </code><code>'123456'</code><code>;</code>

<code>&gt; flush privileges;</code>

為了友善測試,在slave1的test庫下面建一個t1表,要slave2的test庫下面建test1表。在test庫下執行show tables指令結果不一樣則表示負載均衡有效。

<code>&gt;use </code><code>test</code><code>;</code>

<code>Database changed</code>

<code>&gt;show tables;</code>

<code>+----------------+</code>

<code>| Tables_in_test |</code>

<code>| t1             |</code>

<code>| test1          |</code>

測試結果:

<a href="https://s5.51cto.com/wyfs02/M00/8D/AC/wKioL1imTM7TW7IuAABkTaNzUoM335.png-wh_500x0-wm_3-wmp_4-s_4195759617.png" target="_blank"></a>

多次查詢傳回的結果是t1和test1交替出現。說明查詢分别分發到了slave1和slave2上,進而實作了負載均衡。

六,通路haproxy監控頁面

<a href="https://s2.51cto.com/wyfs02/M01/8D/B0/wKiom1imYrLSJRpEAAG-J-o4CVg027.png-wh_500x0-wm_3-wmp_4-s_446413179.png" target="_blank"></a>

七,檢視日志

<code> </code><code># tail -f /var/log/haproxy/haproxy.log</code>

<code>Feb 17 17:06:58 localhost haproxy[12648]: 10.32.1.64:50626 [17</code><code>/Feb/2017</code><code>:17:06:58.959] mysql mysqlservers</code><code>/dbsrv1</code> <code>1</code><code>/0/30</code> <code>395 -- 0</code><code>/0/0/0/0</code> <code>0</code><code>/0</code>

<code>Feb 17 17:07:00 localhost haproxy[12648]: 10.32.1.64:50629 [17</code><code>/Feb/2017</code><code>:17:07:00.050] mysql mysqlservers</code><code>/dbsrv2</code> <code>1</code><code>/0/5</code> <code>392 -- 0</code><code>/0/0/0/0</code> <code>0</code><code>/0</code>

<code>Feb 17 17:07:01 localhost haproxy[12648]: 10.32.1.64:50632 [17</code><code>/Feb/2017</code><code>:17:07:01.252] mysql mysqlservers</code><code>/dbsrv1</code> <code>1</code><code>/0/12</code> <code>395 -- 0</code><code>/0/0/0/0</code> <code>0</code><code>/0</code>

<code>Feb 17 17:07:02 localhost haproxy[12648]: 10.32.1.64:50635 [17</code><code>/Feb/2017</code><code>:17:07:02.037] mysql mysqlservers</code><code>/dbsrv2</code> <code>1</code><code>/0/9</code> <code>392 -- 0</code><code>/0/0/0/0</code> <code>0</code><code>/0</code>

<code>Feb 17 18:41:17 localhost haproxy[12648]: 10.32.1.227:8398 [17</code><code>/Feb/2017</code><code>:18:41:17.489] stats stats/&lt;STATS&gt; 3</code><code>/0/0/0/4</code> <code>200 17398 - - LR-- 3</code><code>/3/0/0/0</code> <code>0</code><code>/0</code> <code>"GET /haproxyadmin?stats HTTP/1.1"</code>

<code>Feb 17 18:41:17 localhost haproxy[12648]: 10.32.1.227:8398 [17</code><code>/Feb/2017</code><code>:18:41:17.494] stats stats/&lt;NOSRV&gt; 89</code><code>/-1/-1/-1/89</code> <code>503 212 - - LR-- 2</code><code>/2/0/0/0</code> <code>0</code><code>/0</code> <code>"GET /favicon.ico HTTP/1.1"</code>

<code>Feb 17 18:41:19 localhost haproxy[12648]: 10.32.1.227:8399 [17</code><code>/Feb/2017</code><code>:18:41:17.489] stats stats/&lt;STATS&gt; 1568</code><code>/0/0/0/1569</code> <code>200 17399 - - LR-- 3</code><code>/3/0/0/0</code> <code>0</code><code>/0</code> <code>"GET /haproxyadmin?stats HTTP/1.1"</code>

<code>Feb 17 18:41:19 localhost haproxy[12648]: 10.32.1.227:8399 [17</code><code>/Feb/2017</code><code>:18:41:19.058] stats stats/&lt;NOSRV&gt; 68</code><code>/-1/-1/-1/68</code> <code>503 212 - - LR-- 2</code><code>/2/0/0/0</code> <code>0</code><code>/0</code> <code>"GET /favicon.ico HTTP/1.1"</code>

<code>Feb 17 18:41:19 localhost haproxy[12648]: 10.32.1.227:8400 [17</code><code>/Feb/2017</code><code>:18:41:17.489] stats stats/&lt;STATS&gt; 2331</code><code>/0/0/1/2333</code> <code>200 17402 - - LR-- 3</code><code>/3/0/0/0</code> <code>0</code><code>/0</code> <code>"GET /haproxyadmin?stats HTTP/1.1"</code>

<code>Feb 17 18:41:19 localhost haproxy[12648]: 10.32.1.227:8400 [17</code><code>/Feb/2017</code><code>:18:41:19.823] stats stats/&lt;NOSRV&gt; 60</code><code>/-1/-1/-1/60</code> <code>503 212 - - LR-- 2</code><code>/2/0/0/0</code> <code>0</code><code>/0</code> <code>"GET /favicon.ico HTTP/1.1"</code>

可以看到每一次請求都有記錄在日志檔案中。

八,failover測試

把slave1的mysql服務停掉模拟故障,我們先來看日志:

<code>Server mysqlservers</code><code>/dbsrv2</code> <code>is DOWN, reason: Layer4 connection problem, info: </code><code>"Connection refused"</code><code>, check duration: 4ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining </code><code>in</code> <code>queue.</code>

haproxy已經檢測到了slave1不可用,現在我們再來通過haproxy轉發查詢,可以看到haproxy把所有的請求都轉發到slave2了,監控界面也已經将slave标記為down了。

<a href="https://s1.51cto.com/wyfs02/M01/8D/B1/wKiom1imcgXSYg4eAABmXuHtb9s875.png-wh_500x0-wm_3-wmp_4-s_212838257.png" target="_blank"></a>

<a href="https://s4.51cto.com/wyfs02/M00/8D/B1/wKiom1imcq7w5Fy-AABqk77BMXU873.png-wh_500x0-wm_3-wmp_4-s_3238117568.png" target="_blank"></a>

在将slave1的mysql服務啟起來之後,slave1雙可以正常提供服務了:

<a href="https://s1.51cto.com/wyfs02/M02/8D/AE/wKioL1imdJfDNzeqAABl1Gi_DtI892.png-wh_500x0-wm_3-wmp_4-s_1516355396.png" target="_blank"></a>

注意:

1,如果日志裡面出現proxy proxy-mysql has no server available!這個的報錯時,可以先看一下後端的mysql服務是否正常,如果正常的話有可能是防火牆的規則有問題或者selinux沒有關閉導緻的。

2,生産環境如果出現從庫當機要判斷主從複制是否有誤,複制延遲大不大,确認沒問題再提供服務,不然要将有問題的從庫從配置檔案中摘除。

3,上面配置檔案haproxy對後端mysql的檢測隻是檢測端口是否在,也可以通過option  mysql-check user haproxy來檢測mysql是否可以正常連接配接,因為有遇到過mysqld程序還在,但是連不了的情況。此時需要對檢測使用者haproxy進行授權:

    USE mysql;

    INSERT INTO user (Host,User) values ('10.32.1.64&gt;','haproxy');

    FLUSH PRIVILEGES;

參考:

<a href="http://www.ttlsa.com/linux/haproxy-study-tutorial/" target="_blank">http://www.ttlsa.com/linux/haproxy-study-tutorial/</a>

<a href="http://www.haproxy.org/" target="_blank">http://www.haproxy.org/</a>

本文轉自 emma_cql 51CTO部落格,原文連結:http://blog.51cto.com/chenql/1898713