目的
因為業務架構上需要實現讀寫分離,剛好前段時間美團點評開源了在360Atlas基礎上開發的讀寫分離中間件DBProxy,關於其介紹在官方文檔已經有很詳細的說明了,其特性主要有:讀寫分離、負載均衡、支持分表、IP過濾、sql語句黑名單、DBA平滑下線DB、從庫流量配置、動態加載配置項。本文大致簡單的介紹自己在使用中如何快速安裝和使用DBProxy。
環境
Ubuntu 16.04.1 LTS
注意:由於DBProxy在16.04上面會有報錯,因為在Ubuntu16.04上面libmysqlclient-dev源是MySQL5.7,詳細的問題可以看這篇文章。所以需要重新設置其源,若是16.04以下版本可以跳過此步。
add-apt-repository 'deb http://archive.ubuntu.com/ubuntu trusty universe'
源替換了之后,還需要把16.04的源先注視掉,不然還是會裝MySQL5.7。最后在update:
sudo apt-get update
安裝
① 安裝依賴包:
apt-get install libmysqlclient-dev libgcrypt11-dev pkg-config lua5.1-0 liblua5.1-0-dev libtool flex bison openssl libssl-dev libjemalloc1 libjemalloc-dev libevent-dev autoconf gettext libffi-dev
② 安裝 glib-2.42.0
wget http://ftp.gnome.org/pub/GNOME/sources/glib/2.42/glib-2.42.0.tar.xz
由於目前確認有效的glib2版本是2.42.0-1.el6,CentOS、Ubuntu和Debian默認源中的版本都不是2.42.0-1.el6,會導致make報錯,因此在上面增加對glib的下載編譯安裝。
解壓: xz -d glib-2.42.0.tar.xz tar xvf glib-2.42.0.tar 編譯: cd glib-2.42.0 autoreconf -ivf ./configure --prefix=/usr/local/glib-2.42 make make install
③ 安裝DBProxy
下載: git clone https://github.com/Meituan-Dianping/DBProxy.git 安裝: cd DBProxy/ sh autogen.sh
注意:
不使用默認的glib,使用上面新編譯的版本,變更glib編譯選項,替換原始的bootstrap.sh的內容:
vi bootstrap.sh +++++++++++++++++++++++++++ #!/bin/sh base=$(cd "$(dirname "$0")"; pwd) cd $base ./configure --prefix=/usr/local/mysql-proxy CFLAGS="-g -O0" \ GLIB_CFLAGS="-I/usr/local/glib-2.42/include/glib-2.0 -I/usr/local/glib-2.42/lib/glib-2.0/include" \ GLIB_LIBS="-L/usr/local/glib-2.42/lib -lglib-2.0" \ GMODULE_CFLAGS="-pthread -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include" \ GMODULE_LIBS="-L/usr/local/glib-2.42/lib -Wl,--export-dynamic -lgmodule-2.0 -pthread -lrt" \ GTHREAD_CFLAGS="-pthread -I/usr/local/glib-2.42/include/glib-2.0 -I/usr/local/glib-2.42/lib/glib-2.0/include" \ GTHREAD_LIBS="-L/usr/local/glib-2.42/lib -lgthread-2.0 -pthread -lrt" +++++++++++++++++++++++++++ sh bootstrap.sh make make install
成功編譯安裝完成之后,默認安裝路徑是:
/usr/local/mysql-proxy
④ 啟動DBProxy
創建配置文件目錄:
mkdir /usr/local/mysql-proxy/conf
初始化配置文件:建議配置文件和DBProxy實例名保持一致。
cp script/source.cnf.samples /usr/local/mysql-proxy/conf/source.cnf
腳本啟動:$install_path/mysql-proxyd $instance_name(實例名) start/restart/stop
root@dbtest:/usr/local/mysql-proxy# ./bin/mysql-proxyd source start OK: MySQL-Proxy of source is started root@dbtest:/usr/local/mysql-proxy# ps -ef | grep mysql root 23000 1 0 02:44 ? 00:00:00 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/source.cnf root 23001 23000 0 02:44 ? 00:00:00 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/source.cnf
到此安裝結束,接着介紹下配置文件。
配置文件
根據需要,把配置文件改名成proxy_test.cnf(/usr/local/mysql-proxy/conf),對應的實例名為proxy_test,具體的配置信息如下:
[mysql-proxy] #設置DBProxy進程的所屬用戶以及日志的所屬用戶等 該命令在非root用戶啟動時不生效,只有在root用戶下,配置存在的user時才會生效 #user=mysql #管理接口的用戶名 admin-username=guest #管理接口的密碼 admin-password=guest #dbproxy監聽的管理接口IP和端口 admin-address=0.0.0.0:3309 #用戶名與其對應的加密過的MySQL密碼,密碼使用PREFIX/bin目錄下的加密程序encrypt加密,將其替換為你的MySQL的用戶名和加密密碼! pwds=dxy_proxy:uK6+XM9x2YRDabHitUtqIK5KOLfO #dbproxy監聽的工作接口IP和端口 proxy-address=0.0.0.0:3308 #dbproxy后端連接的MySQL主庫的IP和端口 proxy-backend-addresses=192.168.200.202:3306 #dbproxy后端連接的MySQL從庫的IP和端口,@后面的數字代表權重,用來作負載均衡,若省略則默認為1,可設置多項,用逗號分隔 proxy-read-only-backend-addresses=192.168.200.132:3306@3 #在原有配置從庫的基礎上,可以對從庫指定tag名 #例如:proxy-read-only-backend-addresses=xx.xx.xx.xx:3306$tag_mt@10,xx.xx.xx.xx:3306 #實例名稱,用於同一台機器上多個dbproxy實例間的區分 instance=proxy_test #日志存放的路徑 log-path=/var/log/dbproxy_log/ #SQL日志的開關,可設置為OFF、ON、REALTIME,OFF代表不記錄SQL日志,ON代表記錄SQL日志,REALTIME代表記錄SQL日志且實時寫入磁盤,默認為OFF sql-log=REALTIME #日志級別,分為message、warning、critical、error、debug五個級別 log-level=message #工作線程數,對dbproxy的性能有很大影響,可根據情況適當設置,默認是1。DBProxy的線程分這幾類:日志等輔助功能的線程、主線程、工作線程。這個參數指的是工作線程數 event-threads=16 #設置dbproxy的運行方式,設為true時為守護進程方式,設為false時為前台方式,一般開發調試時設為false,線上運行時設為true daemon=true #設置dbproxy的運行方式,設為true時dbproxy會啟動兩個進程,一個為monitor,一個為worker,monitor在worker意外退出后會自動將其重啟,設為false時只有worker,沒有monitor,一般開發調試時設為false,線上運行時設為true keepalive=1 #分表設置,此例中person為庫名,mt為表名,id為分表字段,3為子表數量,可設置多項,以逗號分隔,若不分表則不需要設置該項 #tables = person.mt.id.3 #是否限制WHERE語句。ON: SELECT 后必須有WHERE 語句 select-where-limit=OFF #dbproxy前面掛接的LVS的物理網卡的IP(注意不是虛IP),若有LVS且設置了client-ips則此項必須設置,否則可以不設置 #lvs-ips = 192.168.1.1 #DBProxy最大連接數 max-connections=1000 #長等待的閾值,超過該值則認定為同步等待時間過長,打印warning(單位ms) long-wait-time=500 #慢查詢閾值,查詢執行時間超過該閾值則認為是慢查詢(單位ms) long-query-time=3000 #0:不統計,1:僅統計總體的響應時間,其中包括慢查詢,2:進行直方圖統計;默認為1。 query-response-time-stats=2 #SQL日志文件最大大小,單位為字節,默認為1G sql-log-file-size=1073741824 #保留的最大SQL日志文件個數,默認為0,不保留歷史文件,僅保留當前文件 sql-log-file-num=50 #后台MySQL版本號,默認為5.5 mysql-version=5.6 #DBProxy 客戶端連接的 timeout,如果連接到 DBProxy 的連接空閑超過此值,DBProxy 會關閉此連接(單位ms) wait-timeout=86400 #DBProxy 連接池中連接的空閑時間 db-connection-idle-timeout=3600 #連接池中連接的生存周期 db-connection-max-age=7200 #后台MySQL最大連接數,默認為0,表示不限制 backend-max-thread-running=0 #指定當 backend 的 thread running 數超過 backend-max-thread-running時,新來連接等待的時間(單位ms) thread-running-sleep-delay=10 #SQL過濾統計緩存的SQL模板數,默認為0 #lastest-query-num=10000 #設置某類語句記入黑名單時,要滿足的查詢的執行時間,超過此值的查詢會被做為放到黑名單的候選(單位ms) #query-filter-time-threshold=10000 #設置某類語句記入黑名單時,要滿足的查詢的執行頻率,超過此值的查詢會被做為放到黑名單的候選,當同時滿足時間和頻率都超過指定值時,此類查詢會被放入黑名單 #query-filter-frequent-threshold=10.000000 #SQL過濾頻率統計時間窗口內的最小執行次數,根據頻率和該參數計算時間窗口 #access-num-per-time-window=10 #手動過濾SQL是否生效,默認為OFF #manual-filter-flag=OFF #自動過濾SQL是否生效,默認為OFF #auto-filter-flag=OFF #Shutdown DBProxy時,空閑事務的等待時間, 單位是s shutdown-timeout=600 #設置SQL的類型: client: 客戶端的SQL日志、連接、關閉信息; backend: 后台MySQL執行的語句及其狀態;all: client + backend sql-log-mode=backend #設置trace的DBProxy模塊,設置后模塊的運行情況會打印到admin日志中 log-trace-modules=0 #設置proxy用戶白名單,只能從本參數指定的主機進行訪問DBProxy,為空時不對用戶限制 user-hosts= #移除backend時最長等待時間。在刪除過程中,如果當前待刪除的庫正在事務中,則可以設置等待時間,沒有設置等待時間,則參考該值,單位是s。 remove-backend-timeout=1024 #percentile統計功能的開關 ON:打開 OFF:關閉,默認OFF #percentile-switch=OFF #設置百分占比,默認95 #percentile=95 #配置監控backends的用戶信息 #backend-monitor-pwds= #日志緩沖大小(日志條數),默認500 #sql-log-buffer-size= #設置check state線程查詢backend的信息的時間間隔,默認為4s check-state-interval=4 #設置check state線程查詢backend的信息時的連接超時,默認為1s check-state-conn-timeout=1
具體的參數說明可以見官網。按照配置文件進行相關的設置,如日志目錄、非root用戶開啟DBProxy等。相關操作如下:
1:創建啟動用戶 useradd dbproxy 2:創建日志目錄 mkdir /var/log/dbproxy_log/ 3:修改相應目錄文件權限 cd /usr/local/ chown -R dbproxy.dbproxy mysql-proxy/ cd /var/log/ chown -R dbproxy.dbproxy dbproxy_log/ 4:啟動 root@dbtest:/usr/local/mysql-proxy# ./bin/mysql-proxyd proxy_test start 2017-04-12 11:35:46.762: (message)mysql-proxy-cli.c:795(main_cmdline)running as user: dbproxy (1001/1001) OK: MySQL-Proxy of proxy_test is started
root@dbtest:/usr/local/mysql-proxy# ps -ef | grep mysql
dbproxy 25254 1 0 12:35 ? 00:00:00 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/proxy_test.cnf
dbproxy 25255 25254 0 12:35 ? 00:00:00 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/proxy_test.cnf
到此DBProxy已經正式啟動了,后面就需要對其進行管理,在配置文件中設置了管理用戶和proxy用戶的賬號、密碼已經主從的相關信息,當然里面大部分信息都可以在管理接口進行set的動態修改設置。
DBProxy管理操作
admin接口(3309),proxy接口(3308)管理
1)admin 用戶,通過admin接口訪問
在配置文件里配置了管理接口的地址、端口和用戶、密碼。登入:
mysql -uguest -pguest -P3309 -h127.0.0.1
和登陸mysql一樣的命令,但是在命令行只能執行特定的命令,通過下面的命令來查看可以執行的操作。
select * from help;
通過下面的命令查看用戶信息,包括admin和proxy用戶:
guest@127.0.0.1 : (none) 12:53:17>select * from pwds; +-----------+------------------------------+-------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------+----------+-------+ | % | | | | proxy | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | | guest | uqmOY9A= | | | admin | +-----------+------------------------------+-------+----------+-------+
字段名稱 | 含義 |
---|---|
username | 用戶名 |
password | 密碼(encrypted_pwd) |
hosts | 用戶對應的白名單ip |
backends | proxy用戶名下綁定的bakcend(以tag名的形式標記) |
type | 類型信息。proxy:proxy端口的用戶 admin:admin 端口的用戶 |
不能添加、刪除admin用戶,只能修改admin用戶的用戶名、密碼和訪問IP。
① 修改用戶名和密碼:alter admin user $user:$pwd
guest@127.0.0.1 : (none) 12:55:32>alter admin user zjy:zjy; Empty set (0.00 sec) guest@127.0.0.1 : (none) 01:01:15>^DBye root@dbtest:~# mysql -uguest -pguest -P3309 -h127.0.0.1 Warning: Using a password on the command line interface can be insecure. ERROR 1045 (28000): unknown user root@dbtest:~# mysql -uzjy -pzjy -P3309 -h127.0.0.1 Warning: Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.0.99-agent-admin Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. zjy@127.0.0.1 : (none) 01:03:31>select * from pwds; +-----------+------------------------------+-------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------+----------+-------+ | % | | | | proxy | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | | zjy | p7aS | | | admin | +-----------+------------------------------+-------+----------+-------+ 3 rows in set (0.00 sec)
② 限制訪問IP。設置連接admin端口的ip白名單,從而加強對admin賬號的安全管理,限制部分ip對admin端口的登錄請求,即只有在白名單內的ip才能夠允許連接admin端口(不設置時,默認不限制),
添加白名單:alter admin user hosts $ip,$ip ,多個用逗號分隔。
mysql> add admin user hosts 192.168.200.64,192.168.200.25; Empty set (0.03 sec) mysql> select * from pwds; +-----------+------------------------------+-------------------------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------------------------------+----------+-------+ | % | | | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | 192.168.200.25,192.168.200.64 | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-------------------------------+----------+-------+ 4 rows in set (0.00 sec) mysql> ^DBye # mysql -uguest -pguest -P3309 -h127.0.0.1 #限制IP,連不上了 Warning: Using a password on the command line interface can be insecure. ERROR 1045 (28000): unpermitted host 從200.64上連接: #在白名單里,可以連接 $ mysql -uguest -pguest -P3309 -h192.168.200.24 Warning: Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.0.99-agent-admin ...
刪除白名單:remove admin user hosts $ip,$ip
guest@192.168.200.24 : (none) 12:28:54>remove admin user hosts 192.168.200.64; Empty set (0.00 sec) guest@192.168.200.24 : (none) 12:31:13>select * from pwds; +-----------+------------------------------+----------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+----------------+----------+-------+ | % | | | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | 192.168.200.25 | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+----------------+----------+-------+ 4 rows in set (0.00 sec) guest@192.168.200.24 : (none) 12:31:15>^DBye $ mysql -uguest -pguest -P3309 -h192.168.200.24 #不在白名單 Warning: Using a password on the command line interface can be insecure. ERROR 1045 (28000): unpermitted host
③ 保存修改到配置文件。要是通過管理接口進行的一些修改,僅在當時是有效,若DBProxy重啟之后則會丟失配置,通過 save config來持久到配置文件。
mysql> save config; Empty set (0.01 sec)
2)Proxy 用戶,通過proxy接口訪問
能添加、刪除proxy用戶和訪問IP,不能修改proxy用戶的用戶名、密碼。
這里結合程序一起說明:比如有2套程序需要訪問數據庫sbtest,程序所在IP:192.168.200.64和192.168.200.25;DBproxy所在IP:192.168.200.24,后端數據庫所在IP(配置文件里已經設置):192.168.200.202(M),192.168.200.132(S)。
① 添加和刪除proxy用戶:add pwd $user:$pwd
#明文密碼 mysql> add pwd sbtest:sbtest; Empty set (0.00 sec) #加密密碼 先獲取加密密碼: :/usr/local/mysql-proxy/bin# ./encrypt sbtest rr6fdddI 再添加賬號: mysql> add enpwd sbtest:rr6fdddI; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+-------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------+----------+-------+ | % | | | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-------+----------+-------+
② 限制訪問IP,允許200.64/25訪問DBPrxoy。這里比較特別,在用戶的白名單的上一層還有一個系統白名單,即username是%,大致的驗證流程如下:
大致的意思是設置了系統白名單則需要首先通過系統白名單驗證,要是也設置了用戶白名單則再通過用戶白名單驗證,若均沒有設置白名單則直接訪問不需要驗證(默認)。所以我們這里系統白名單沒有設置,只需要設置用戶白名單即可。既然系統白名單有設置,為了安全還是設置一下,大致流程如下:
系統白名單設置:
添加:add user hosts %@host[|host];
mysql> add user hosts %@192.168.200.%|192.168.201.%; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+-----------------------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-----------------------------+----------+-------+ | % | | 192.168.200.%|192.168.201.% | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-----------------------------+----------+-------+
系統白名單設置了允許200和201網段的IP訪問,其他IP訪問不了。
刪除指定的白名單:remove user hosts %@192.168.201.%;
刪除所有白名單:remove user host %;
#刪除指定的白名單 mysql> remove user hosts %@192.168.201.%; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+---------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+---------------+----------+-------+ | % | | 192.168.200.% | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+---------------+----------+-------+ 4 rows in set (0.00 sec) #刪除所有白名單 mysql> remove user hosts %; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+-------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------+----------+-------+ | % | | | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-------+----------+-------+ 4 rows in set (0.00 sec)
當添加完系統白名單之后,若用戶白名單沒設置,只要是200和201網段的都可以用賬號訪問。好像還是不太安全,后面繼續用戶白名單設置。
mysql> select * from pwds; +-----------+------------------------------+-----------------------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-----------------------------+----------+-------+ | % | | 192.168.200.%|192.168.201.% | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | 192.168.200.% | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-----------------------------+----------+-------+ 通過非200和201網段訪問: $ mysql -usbtest -psbtest -P3308 -h192.168.200.24 Warning: Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied(host is forbidden) for user 'sbtest'@'192.168.204.187' (using password: YES)
用戶白名單設置:根據上面的條件設置具體的白名單
添加:add user hosts $user@host[|host];
mysql> add user hosts sbtest@192.168.200.64|192.168.200.25; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+-------------------------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------------------------------+----------+-------+ | % | | 192.168.200.%|192.168.201.% | | proxy | | sbtest | rr6fdddI | 192.168.200.25|192.168.200.64 | | proxy | | guest | uqmOY9A= | 192.168.200.% | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-------------------------------+----------+-------+
若在非上面指定的白名單(IP)中執行則報錯:
$mysql -usbtest -psbtest -P3308 -h192.168.200.24 Warning: Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied(host is forbidden) for user 'sbtest'@'192.168.200.55' (using password: YES)
刪除用戶白名單:remove user hosts $user@$host|$host
mysql> remove user hosts sbtest@192.168.200.25|192.168.200.64; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+-----------------------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-----------------------------+----------+-------+ | % | | 192.168.200.%|192.168.201.% | | proxy | | sbtest | rr6fdddI | | | proxy | | guest | uqmOY9A= | 192.168.200.% | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-----------------------------+----------+-------+ 4 rows in set (0.00 sec)
若系統白名單設置不允許200網段登陸,則直接不會走到驗證用戶白名單這不,直接退出。
mysql> remove user hosts %@192.168.200.%; Empty set (0.00 sec) mysql> select * from pwds; +-----------+------------------------------+-------------------------------+----------+-------+ | username | password | hosts | backends | type | +-----------+------------------------------+-------------------------------+----------+-------+ | % | | 192.168.201.% | | proxy | | sbtest | rr6fdddI | 192.168.200.25|192.168.200.64 | | proxy | | guest | uqmOY9A= | 192.168.200.% | | admin | | dxy_proxy | uK6+XM9x2YRDabHitUtqIK5KOLfO | | | proxy | +-----------+------------------------------+-------------------------------+----------+-------+ 4 rows in set (0.00 sec)
#系統白名單只允許201網段訪問。即使用戶白名單允許200網段訪問也不行: $mysql -usbtest -psbtest -P3308 -h192.168.200.24 Warning: Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied(host is forbidden) for user 'sbtest'@'192.168.200.64' (using password: YES)
③ 權限相關,proxy用戶必須在后端數據庫里存在並且保持一致的密碼。
通過上面設置了白名單,加強了數據庫的安全,這里還有另一個需要注意的:訪問的賬號(sbtest)需要在后端數據庫(MS)里面存在並且密碼和DBproxy設置的一樣,而且擁有相應的權限,否則報錯:
$mysql -usbtest -psbtest -P3308 -h192.168.200.24 #可以訪問DBproxy... sbtest@192.168.200.24 : (none) 02:45:29>show databases; #不能執行命令,因為后端數據庫沒有賬號或則密碼錯誤。 ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 431 Current database: *** NONE *** ERROR 1105 (07000): Internal Error: I have no server backend, closing connection
把上面的配置持久化到配置文件(save config)
user-hosts=%@192.168.200.%|192.168.201.%,sbtest@192.168.200.25|192.168.200.64 admin-user-hosts=192.168.200.%
backends管理
DBProxy啟動之前需要在配置文件中配置backend信息。backend按照讀寫分類,可分為讀寫backend庫(可以讀寫操作)和只讀backend庫(僅可以讀操作),其中在配置文件中讀寫backend庫是必須配置的。連接DBProxy的客戶端所發送的sql語句,根據DBProxy內部的策略,會將sql語句發送至特定的backend庫執行。具體的說明可以看文檔。
配置文件參數:
proxy-backend-addresses:配置主庫IP:Port
proxy-read-only-backend-addresses:配置從庫IP:Port@權重,多個,號分隔。
select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 3 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+
要是配置文件里沒有配置,也可以到admin接口里進行設置:
添加一個主庫:add master $ip:$port
添加一個從庫:add slave $ip:$port
guest@127.0.0.1 : (none) 04:31:55>select * from backends; Empty set (0.00 sec) guest@127.0.0.1 : (none) 04:31:57>add master 192.168.200.202:3306; Empty set (0.00 sec) guest@127.0.0.1 : (none) 04:32:00>add slave 192.168.200.132:3306; Empty set (0.00 sec) guest@127.0.0.1 : (none) 04:32:13>select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 1 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ 2 rows in set (0.00 sec) guest@127.0.0.1 : (none) 04:32:18>
當已經存在一個主庫,再添加一個主庫會報錯:
guest@127.0.0.1 : (none) 04:32:18>add master 192.168.200.202:3306; ERROR 1105 (07000): there is already one RW backend
DBProxy只允許一主一從或一主多從,不能多主。
刪除backends:remove backend $backend_ndx [timeout $int]
timeout的意義是:在刪除過程中,如果當前待刪除的庫正在事務中,則可以設置等待時間,沒有設置等待時間,則參考系統全局的remove-backend-timeout的值。若當前backend中有連接在事務中,則等待該事務完成,若超過等待時間,該事務仍舊沒有執行完,則強制對backend進行刪除。
guest@127.0.0.1 : (none) 04:34:24>select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 1 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ 2 rows in set (0.00 sec) guest@127.0.0.1 : (none) 04:36:02>remove backend 2; Empty set (0.00 sec) guest@127.0.0.1 : (none) 04:36:42>remove backend 1 timeout 100; Empty set (0.00 sec) guest@127.0.0.1 : (none) 04:36:48>select * from backends; Empty set (0.00 sec)
字段名稱 | 含義 |
---|---|
backend_ndx | 每個backend的索引值,該值是動態變化的,從1開始依次排序,主庫序號靠前 |
address | backend的主機ip和port |
hostname | 顯示ip地址對應的主機名稱 |
state | 顯示backend的狀態。狀態有:UP/DOWN/REMOVING/OFFLINE/OFFLING |
type | 代表backend的類型。類型有:rw:主庫,可進行讀寫操作 ro:從庫,只可進行讀取操作 |
weight | 代表從庫的權重。主庫權重為0,代表其沒有權重屬性;從庫的權重最小值為1 |
tag | backend的標簽名 |
threads_running | 當前backend上正在運行的並發線程數 |
這里說明一下state和weight的意義,tag的說明可以看文檔,這里不做說明。
state:proxy根據其狀態進行讀寫策略,當狀態是down或則是offline的時候,表示已經不可用,讀寫都不會分配過來,會分流到其他的從庫或則主庫。即:當一主一從,從down了,之后的讀寫都會分到主上去。直到state正常之后就會自動分流回來。這個可以通過sql日志(日志目錄下的sql目錄中)看到。如:
這里有個不足是DBProxy不關心主從復制的可靠性和穩定性,若從延遲大,讀的操作還是會到延遲的從上去,不會自動的下線從庫。這里需要DBA自己介入,通過判斷延遲的閾值去admin接口執行set offline來手動更新state字段,使延遲大的從先下線。
set offline $backend_ndx [timeout $int];set online $backend_ndx;timeout的意義和上面的一致。
mysql> select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 1 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ 2 rows in set (0.00 sec) mysql> set offline 2; Empty set (0.00 sec) 通過查看日志(/var/log/dbproxy_log/sql),看到這時的讀都去了主庫。 mysql> select * from backends; +-------------+----------------------+----------+---------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+---------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | offline | ro | 1 | NULL | 0 | +-------------+----------------------+----------+---------+------+--------+------+-----------------+ 2 rows in set (0.00 sec) mysql> set online 2; Empty set (0.00 sec) mysql> select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 1 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ 2 rows in set (0.00 sec) 通過查看日志(/var/log/dbproxy_log/sql),看到這時的讀都去了從庫。
若把主庫set offline,讀不受影響;寫不能執行。要是有多個從,可以通過weight實現負載均衡:alter slave weight $backend_index $weight
mysql> select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 1 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ 2 rows in set (0.00 sec) mysql> alter slave weight 2 100; Empty set (0.00 sec) mysql> select * from backends; +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | backend_ndx | address | hostname | state | type | weight | tag | threads_running | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ | 1 | 192.168.200.202:3306 | | up | rw | 0 | NULL | 0 | | 2 | 192.168.200.132:3306 | | up | ro | 100 | NULL | 0 | +-------------+----------------------+----------+-------+------+--------+------+-----------------+ 2 rows in set (0.00 sec)
權重越大,其被讀的幾率就越大,要是某一個從庫性能比較好,權重可以設置的大一點。這里補充一下,通過上面的sql日志的截圖,為什么寫一次之后馬上讀取卻還是在主上呢?這個是由於DBProxy的限制造成的:update、insert、delete、replace之后,下一條 sql有可能 去讀 affected row 的行數。有的select 語句帶有特殊函數的,為了隨后的sql 查上次語句的某些狀態,這種可能需要上下文信息的,DBProxy暫時未把后台連接放回連接池。所以第一個讀會使用上次操作的后台連接,以后就走從庫了。
平滑關閉DBProxy
支持DBProxy立即關閉和平滑關閉。立即關閉是指立即結束DBProxy進程;平滑關閉是指若有正在執行的事務,等待shutdown-timeout時間,如果仍有執行的事務,則直接結束DBProxy進程。
shutdown [NORMAL|IMMEDIATE]; #NORMAL:平滑下線 IMMEDIATE:立即下線
mysql> shutdown normal; Empty set (0.01 sec)
介紹到這里,大致已經能讓基本的讀寫分離功能用起來了,DBProxy里還有很多其他功能,包括為SLAVE打TAG、指定從指定從庫上讀取,指定到主上讀等等。這里暫時沒用到就不介紹了,所有的內容在手冊里有了詳盡的介紹,有興趣的可以去查看。再看文檔都時候遇到過一些問題,這里感謝DBProxy開發同學<紫氣東來>的解惑。
DBProxy性能測試
在上DBProxy中間件的時候必須還要做個測試,因為用DBProxy進行數據庫操作畢竟多了一層訪問,不知道性能上有多大的折損。這里通過sysbench進行相關的測試來大致了解一下大概能有多大的差別。關於sysbench的安裝和使用可以看sysbench 安裝、使用和測試,也可以參考使用sysbench對mysql壓力測試。
1)安裝,用最新版的sysbench,其他版也沒問題。
1:安裝依賴包 apt-get install make automake libtool pkg-config libaio-dev vim-common libmysqlclient-dev 2:下載 git clone https://github.com/akopytov/sysbench.git 3:安裝 cd sysbench sh autogen.sh ./configure --prefix=/usr/local/sysbench-1.1 make make install
2)使用,最新版1.1的使用方法和0.4.12,甚至是0.5都有了差別,可以通過help來調整
dxy@redis2:/usr/local/sysbench-1.1$ ./bin/sysbench --version sysbench 1.1.0-6bb15d7 dxy@redis2:/usr/local/sysbench-1.1$ ./bin/sysbench cpu help sysbench 1.1.0-6bb15d7 (using bundled LuaJIT 2.1.0-beta2) cpu options: --cpu-max-prime=N upper limit for primes generator [10000] dxy@redis2:/usr/local/sysbench-1.1$ ./bin/sysbench ./share/sysbench/oltp_read_write.lua help sysbench 1.1.0-6bb15d7 (using bundled LuaJIT 2.1.0-beta2) oltp_read_write.lua options: --distinct_ranges=N Number of SELECT DISTINCT queries per transaction [1] --sum_ranges=N Number of SELECT SUM() queries per transaction [1] --skip_trx[=on|off] Don't start explicit transactions and execute all queries in the AUTOCOMMIT mode [off] --secondary[=on|off] Use a secondary index in place of the PRIMARY KEY [off] --create_secondary[=on|off] Create a secondary index in addition to the PRIMARY KEY [on] --index_updates=N Number of UPDATE index queries per transaction [1] --range_size=N Range size for range SELECT queries [100] --auto_inc[=on|off] Use AUTO_INCREMENT column as Primary Key (for MySQL), or its alternatives in other DBMS. When disabled, use client-generated IDs [on] --delete_inserts=N Number of DELETE/INSERT combination per transaction [1] --tables=N Number of tables [1] --mysql_storage_engine=STRING Storage engine, if MySQL is used [innodb] --non_index_updates=N Number of UPDATE non-index queries per transaction [1] --table_size=N Number of rows per table [10000] --pgsql_variant=STRING Use this PostgreSQL variant when running with the PostgreSQL driver. The only currently supported variant is 'redshift'. When enabled, create_secondary is automatically disabled, and delete_inserts is set to 0 --simple_ranges=N Number of simple range SELECT queries per transaction [1] --order_ranges=N Number of SELECT ORDER BY queries per transaction [1] --range_selects[=on|off] Enable/disable all range SELECT queries [on] --point_selects=N Number of point SELECT queries per transaction [10]
3)測試,這里測試選擇通過select、insert、update和混合模式進行測試說明,自帶的lua腳本有:
$ ls -lh /usr/local/sysbench-1.1/share/sysbench/ total 64K -rwxr-xr-x 1 root root 1.5K 4月 12 17:35 bulk_insert.lua -rw-r--r-- 1 root root 14K 4月 12 17:35 oltp_common.lua -rwxr-xr-x 1 root root 1.1K 4月 12 17:35 oltp_delete.lua #刪 -rwxr-xr-x 1 root root 2.0K 4月 12 17:35 oltp_insert.lua #寫 -rwxr-xr-x 1 root root 1.3K 4月 12 17:35 oltp_point_select.lua -rwxr-xr-x 1 root root 1.7K 4月 12 17:35 oltp_read_only.lua #只讀 -rwxr-xr-x 1 root root 1.8K 4月 12 17:35 oltp_read_write.lua #讀寫 -rwxr-xr-x 1 root root 1.1K 4月 12 17:35 oltp_update_index.lua #更新索引字段 -rwxr-xr-x 1 root root 1.2K 4月 12 17:35 oltp_update_non_index.lua #更新非索引字段 -rwxr-xr-x 1 root root 1.5K 4月 12 17:35 oltp_write_only.lua #只寫 -rwxr-xr-x 1 root root 1.9K 4月 12 17:35 select_random_points.lua -rwxr-xr-x 1 root root 2.1K 4月 12 17:35 select_random_ranges.lua drwxr-xr-x 4 root root 4.0K 4月 12 17:35 tests
進入執行文件目錄 cd /usr/local/sysbench-1.1
①:讀寫混合(oltp_read_write.lua)
直連數據庫:
./bin/sysbench --test=./share/sysbench/oltp_read_write.lua --mysql-host=192.168.200.202 --mysql-port=3306 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=4 --tables=3 --table-size=500000 prepare/run/cleanup
代理連數據庫
./bin/sysbench --test=./share/sysbench/oltp_read_write.lua --mysql-host=192.168.200.24 --mysql-port=3308 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=4 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 prepare/run/cleanup
這里需要注意:因為DBProxy的限制,如不支持prepare,需要添加--skip-trx=on --db-ps-mode=disable--skip-trx=on --db-ps-mode=disable;由於不加事務出現的重復key的幾率比較大,所以需要跳過錯誤:--mysql-ignore-errors=1062。
測試的線程:1、4、8、16、32、64、128
把上面數據以折線圖的形式表現:
TPS:
QPS:
②:只讀(oltp_read_only.lua)
直連數據庫:
./bin/sysbench --test=./share/sysbench/oltp_read_only.lua --mysql-host=192.168.200.202 --mysql-port=3306 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=1 --tables=3 --table-size=500000 run
代理連數據庫
./bin/sysbench --test=./share/sysbench/oltp_read_only.lua --mysql-host=192.168.200.24 --mysql-port=3308 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=1 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 run
測試的線程:1、4、8、16、32、64、128
把上面數據以折線圖的形式表現:
TPS:
QPS:
③:只寫入(oltp_insert.lua)
直連數據庫:
./bin/sysbench --test=./share/sysbench/oltp_insert.lua --mysql-host=192.168.200.202 --mysql-port=3306 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=1 --tables=3 --table-size=500000 run
代理連數據庫
./bin/sysbench --test=./share/sysbench/oltp_insert.lua --mysql-host=192.168.200.24 --mysql-port=3308 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=1 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 run
測試的線程:1、4、8、16、32、64、128
把上面數據以折線圖的形式表現:
QPS:
④:只更新(oltp_update_index.lua)
直連數據庫:
./bin/sysbench --test=./share/sysbench/oltp_update_index.lua --mysql-host=192.168.200.202 --mysql-port=3306 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=1 --tables=3 --table-size=500000 run
代理連數據庫
./bin/sysbench --test=./share/sysbench/oltp_update_index.lua --mysql-host=192.168.200.24 --mysql-port=3308 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=300 --threads=1 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 run
測試的線程:1、4、8、16、32、64、128
把上面數據以折線圖的形式表現:
QPS:
測試小結:
在讀寫混合的模式下:代理的TPS是直連的TPS的65%~80%,線程越少差距越大;代理的QPS是直連的QPS的60%~75%,線程越少差距越大。
在純讀模式下:和讀寫混合模式表現相近。
在寫和更新模式下:因為代理也只訪問主,它們的差距就是網絡開銷上,代理需要二次訪問,不需要輪訓。代理的QPS是直連QPS的65%~90%。
當sysbench的並發測試線程較少時,代理和直連DB的QPS差距較大。這主要是因為當sysbench並發線程少時,DBProxy的性能沒有得到充分的發揮,sysbench只有很少的線程向DBProxy發送請求,此時網絡延遲對QPS和TPS的影響是最主要的。 當sysbench的並發測試線程較大時,此時DBProxy的性能就得到了充分的發揮, 此時QPS和TPS的對比是代理與直連DB性能對比的真實的反應,網絡延遲對QPS的影響作用就顯得很小了。
由此看來利用DBProxy轉發SQL請求帶來的性能下降雖有下降,通過Open-Falcon對數據庫指標的監控,這個性能下降是完全可以接受的。另外DBProxy屬於CPU密集型任務,相對於磁盤IO和內存占用率而言,其對CPU消耗顯得最為明顯,所以建議在部署的時候需要優先考慮服務器的CPU性能。
總結
通過上面的一些基本介紹,大致了解了DBProxy讀寫分離功能的使用,和直連DB數據庫對比的性能情況。關於DBproxy的其他功能內容在手冊里有了詳盡的介紹,需要的話可以去查看。
這里還有2個問題:一個問題是在讀寫分離上面,要是從庫延遲超過閾值,導致讀寫分離不可用,則需要自己編寫腳本去連接admin接口控制問題從庫的下線。另一個問題是即使數據庫有MHA保證,但是DBProxy是一個單點,所以需要保證DBProxy的高可用,這2個問題后面會繼續研究,以及會再看另一個中間件proxysql來和DBProxy進行對比選型。
補充:
補上檢測MySQL從庫延遲進行下線和不延遲進行上線操作的判斷,賬號密碼通過讀配置文件,通過讀取admin接口進行操作,配置文件(proxy_db.txt)的格式是:
DBProxy實例名,DBProxy IP,DBProxy Admin User,DBProxy Admin Password,從實例的用戶,從實例的用戶,從實例的密碼
如:
masterdata_proxy,192.168.200.24,3309,guest,guest,test,test
DBProxy Admin接口進行下線和上線的python腳本(check_set_repl.py):具體的參數可以自行按照需要修改。
#!/bin/env python # -*- encoding: utf-8 -*- from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage from email.Utils import COMMASPACE, formatdate import MySQLdb import fileinput import smtplib import mimetypes import email.MIMEMultipart import email.MIMEText import email.MIMEBase def send_mail(to, subject, text, from_mail, server="localhost"): message = MIMEMultipart() message['From'] = from_mail message['To'] = COMMASPACE.join(to) message['Date'] = formatdate(localtime=True) message['Subject'] = subject message.attach(MIMEText(text,_charset='utf-8')) smtp = smtplib.SMTP(server) smtp.sendmail(from_mail, to, message.as_string()) smtp.close() class DBProxyInfo(): def __init__(self,host,port,user,password,slave_user,slave_password): self.host = host self.port = port self.user = user self.password = password self.slave_user = slave_user self.slave_password = slave_password def backends_info(self): try: m = MySQLdb.connect(host=self.host,user=self.user,passwd=self.password,port=self.port) query = "SELECT * FROM backends" cursor = m.cursor() cursor.execute(query) Str_string = cursor.fetchall() cursor.close() m.close() return Str_string except Exception, e: print e sys.exit() def repl_info(self,slave_host,slave_port): try: m = MySQLdb.connect(host=slave_host,user=self.slave_user,passwd=self.slave_password,port=slave_port) query = "SHOW SLAVE STATUS" cursor = m.cursor() cursor.execute(query) Str_string = cursor.fetchone() cursor.close() m.close() return Str_string except Exception, e: print e sys.exit() def set_offline(self,backend_ndx): try: m = MySQLdb.connect(host=self.host,user=self.user,passwd=self.password,port=self.port) query = "SET offline %s" %backend_ndx cursor = m.cursor() cursor.execute(query) Str_string = cursor.fetchone() cursor.close() m.close() return Str_string except Exception, e: print e sys.exit() def set_online(self,backend_ndx): try: m = MySQLdb.connect(host=self.host,user=self.user,passwd=self.password,port=self.port) query = "SET online %s" %backend_ndx cursor = m.cursor() cursor.execute(query) Str_string = cursor.fetchone() cursor.close() m.close() return Str_string except Exception, e: print e sys.exit() if __name__ == '__main__': db_list= [] for line in fileinput.input(): db_list.append(line.strip()) for db_info in db_list: instance_name,host,port,user,password,salve_user,slave_password = db_info.split(',') conn = DBProxyInfo(host,int(port),user,password,salve_user,slave_password) backends_info = conn.backends_info() for backend_ndx,address,hostname,state,type,weight,tag,threads_running in backends_info: if type == 'ro': salve_host,slave_port = address.split(':') repl_info = conn.repl_info(salve_host,int(slave_port)) Slave_IO_Running = repl_info[10] Slave_SQL_Running = repl_info[11] Seconds_Behind_Master = repl_info[32] if Slave_IO_Running != 'Yes' or Slave_SQL_Running != 'Yes' or Seconds_Behind_Master >= 60: if state == 'up': conn.set_offline(self,backend_ndx) subject = "%s's slave is offline " %instance_name message = " %s's slave Warning:\n Slave_IO_Running:%s \n Slave_SQL_Running:%s \n Seconds_Behind_Master:%s" %(address,Slave_IO_Running,Slave_SQL_Running,Seconds_Behind_Master) mail_list = ['zjy@xxx.com'] send_mail(mail_list, subject.encode("utf8"), message, "check_set_rep@ls.xxx.net", server="192.168.200.xxx") else: pass elif Slave_IO_Running == 'Yes' and Slave_SQL_Running == 'Yes' and Seconds_Behind_Master < 60 and state != 'up': conn.set_online(backend_ndx) subject = "%s's slave is online " %instance_name message = " %s's slave OK " %(address) mail_list = ['zjy@dxyer.com'] send_mail(mail_list, subject.encode("utf8"), message, "check_set_rep@ls.xxx.net", server="192.168.200.xxx") else: pass
運行方式:可以放到系統的crontab里定時檢測。
python check_set_repl.py proxy_db.txt
參考文檔