mysql-proxy主從服務架構下讀寫分離和負載均衡實現及原理

EmiN27 8年前發布 | 8K 次閱讀 MySQL 數據庫服務器

來自: http://blog.csdn.net//clh604/article/details/8906022


系統環境 ubuntu

假設已經配置好mysql的主從架構

主服務器:192.168.3.189

從服務器:192.168.3.104


我們的目的就是實現讀取操作由192.168.3.104服務器響應,寫的操作由192.168.3.189響應

首先安裝mysql-proxy

1、從mysql官網上下載最新版的mysql-proxy:http://dev.mysql.com/downloads/mysql-proxy/

2、在本地的/opt/software/ (你可以換成自己的目錄)解壓下載的壓縮文件

解壓后能看到 bin、lib、include、libexc、share幾個文件夾

并把bin目錄添加到系統環境變量中去(在/etc/profile 文件最后添加:export PATH=$PATH:/opt/software/mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit/bin)

然后source /etc/profile 讓剛才設置的環境變量生效

3、在命令行下輸入mysql-proxy --help 能看到幫助信息說明安裝成功了

4、啟動mysql-proxy服務

mysql-proxy --keepalive --proxy-read-only-backend-addresses=192.168.3.104:3306 --proxy-backend-addresses=192.168.3.189:3306  --proxy-lua-script=/opt/software/mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit/share/doc/mysql-proxy/rw-splitting.lua --log-file=/opt/software/mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit/var/mysql-proxy.log

--keepalive   網上解釋說有時候mysql-porxy會崩潰,這個參數能讓mysql-proxy崩潰后自動重啟

--proxy-read-only-backend-addresses    配置只讀服務器

--proxy-backend-addresses    配置可讀可寫服務器(主服務器master)

--proxy-lua-script    配置讀寫分離的lua腳本,這個腳本就在mysql-proxy解壓后的share目錄里面

--log-file    日志文件


這樣mysql-proxy就啟動了,如果想讓mysql-proxy在后臺運行只需要添加--daemon 參數就行了,連接mysql-proxy的命令是

mysql -h192.168.3.189 -P4040 -utest -p123456


那么mysql-proxy是如何進行讀寫分離的呢,關鍵就在讀寫分離的lua腳本rw-splitting.lua

為了解釋讀寫分離的原理,打開rw-splitting.lua腳本,該腳本中有幾個關鍵的地方,我們分別來看


1、配置

if not proxy.global.config.rwsplit then
    proxy.global.config.rwsplit = {
        min_idle_connections = 1,--設置每個服務器所擁有的最大連接池數量(我也不知道為啥命名為min),實際的最大連接數會比這個值大1,也就是在這個配置條件下,實際上每個服務器所能擁有的最大連接數是2
        max_idle_connections = 1,--這個配置有啥做用還不知道

        is_debug = true--開啟調試模式
    }
end

2、connect_server()  每次客戶端連接myql-proxy的時候都會運行一次這個函數,然后返回一個mysql連接給客戶端

首先明確一件是mysql-proxy所擁有最大的連接數是確定的,假設有n臺服務器,min_idle_connections=2,那么所擁有的最大連接數量就是:n*(2+1)

函數首先會判斷主服務器連接數是否達到最大值,如果沒有,就創建一個連接主服務器的連接,并返回;

如果主服務器連接數已滿,遍歷每個從服務器,看從服務器連接是否達到最大值,如果沒有,就創建一個,并返回;

如果所有服務器連接數都達到最大值,就返回主服務器創建的第一個連接


3、read_query() 每次客戶端做sql查詢的時候都會調用這個函數,這個函數把sql傳到某個服務器,得到結果后返回給客戶端

那么如何做讀寫分離呢?在函數內有這么一個判斷

if stmt.token_name == "TK_SQL_SELECT" then

這個語句的作用就是判斷sql語句是不是以SELECT開始的,也就是判斷是否是查詢,如果是查詢的話,接下來會有這么個語句

local backend_ndx = lb.idle_ro()
lb.idle_ro() 是通過 local lb = require("proxy.balance") 引入的balance.lua文件

function idle_ro() 
    local max_conns = -1
    local max_conns_ndx = 0

    for i = 1, #proxy.global.backends do
        local s = proxy.global.backends[i]
        local conns = s.pool.users[proxy.connection.client.username]
        -- pick a slave which has some idling connections
        if s.type == proxy.BACKEND_TYPE_RO and 
           s.state ~= proxy.BACKEND_STATE_DOWN and 
           conns.cur_idle_connections > 0 then
            if max_conns == -1 or 
               s.connected_clients < max_conns then
                max_conns = s.connected_clients
                max_conns_ndx = i
            end
        end
    end

    return max_conns_ndx
end

這個函數的作用就是選擇使用哪個讀服務器,并返回服務器的index:max_conns_ndx

如何選擇服務器呢? 它通過循環遍歷所有服務器,然后選出一個客戶端連接(s.connected_clients)最少的服務器,這樣在一定程度上實現負載均衡




 本文由用戶 EmiN27 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!