首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL-Proxy 讀寫分離實戰:Lua 腳本路由、連線池管理與高可用架構

     編輯:MySQL 資料庫相關知識

架構原理

  • MySQL-Proxy 位於客戶端與後端叢集之間
  • 內嵌 Lua 引擎,攔截網路封包實現邏輯路由
  • 核心:連線池預先建立認證連線,查詢階段無需再次握手

讀寫分離 Lua 腳本核心邏輯

-- rw_split.lua 簡化版
function read_query(packet)
    -- 非事務 + SELECT → 從庫
    if proxy.connection.client.is_in_transaction == 0 and
       packet:byte() == proxy.COM_QUERY and
       packet:sub(2, 7):upper() == "SELECT" then
        
        local best_idx, best_conns = 0, -1
        for i, srv in ipairs(proxy.servers) do
            if srv.type == proxy.BACKEND_TYPE_RO and  -- 只讀節點
               srv.idling_connections > 0 then         -- 有閒置連線
                if best_conns == -1 or srv.connected_clients < best_conns then
                    best_conns = srv.connected_clients
                    best_idx = i
                end
            end
        end
        
        if best_idx > 0 then
            proxy.connection.backend_ndx = best_idx
            return proxy.PROXY_SEND_QUERY
        end
    end
    
    -- 其他:主庫(寫入、事務、DDL、非 SELECT)
    return proxy.PROXY_SEND_QUERY
end

關鍵配置參數

[mysql-proxy]
proxy-address = 0.0.0.0:3306
proxy-backend-addresses = 10.0.0.1:3306  # 主庫
proxy-read-only-backend-addresses = 10.0.0.2:3306,10.0.0.3:3306  -- 從庫
proxy-lua-script = /etc/mysql-proxy/rw_split.lua
proxy-connection-pool-size = 10          -- 每後端連線池大小
proxy-pool-no-change-user = true         -- 避免換用戶開銷
log-level = message
log-file = /var/log/mysql-proxy.log

連線池管理精髓

生產級替代方案對比

挑戰解決方案
MySQL 協議先握手再查詢啟動時預建立認證連線,查詢時直接複用
事務中途切換後端事務內強制主庫,is_in_transaction 標記
從庫延遲導致讀舊數據檢查 Seconds_Behind_Master,或強制關鍵讀走主庫
後端故障移除心跳檢測,標記 DOWN,現有連線完成後不再分派

ProxySQL 快速上手

-- 安裝
yum install proxysql2

-- 管理介面 (admin:admin)
mysql -u admin -padmin -h 127.0.0.1 -P 6032

-- 配置主從
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES 
(10, '10.0.0.1', 3306),  -- 寫入組
(20, '10.0.0.2', 3306), (20, '10.0.0.3', 3306);  -- 讀取組

-- 路由規則:非事務 SELECT 走讀取組
INSERT INTO mysql_query_rules (rule_id, match_pattern, destination_hostgroup, apply) 
VALUES (1, '^SELECT.*', 20, 1);

-- 事務強制寫入組
INSERT INTO mysql_query_rules (rule_id, match_pattern, destination_hostgroup, apply, flagIN) 
VALUES (2, '^BEGIN', 10, 1, 0), (3, '^START TRANSACTION', 10, 1, 0);

LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案優點缺點推薦場景
MySQL-Proxy + Lua靈活、可編程單點、Lua 效能、社區維護弱舊系統、簡單路由
ProxySQL高效能、多執行緒、規則引擎、Web UI學習曲線現代首選
MaxScale企業級、監控、防火牆、Binlog 路由商業授權大規模、合規要求
應用層路由無中間件、效能最好程式碼侵入、維護成本微服務、語言支援好
VIP + Keepalived簡單、透明無讀寫分離、故障切換慢單主單從