Percona Mysql Galera多讀寫叢集部署生產環境實記
一、部署MySQL:
yum install https://www.percona.com/redir/downloads/percona-release/redhat/latest/percona-release-0.1-6.noarch.rpm -y 安裝percona的倉庫檔案。
yum install Percona-XtraDB-Cluster-57 percona-toolkit -y 安裝資料庫
修改配置檔案:/etc/my.cnf
[mysqld]
datadir = /storage/DBdata #資料庫存放的目錄
pid-file = /usr/local/mysql/mysqld.pid
port = 3306
socket = /var/lib/mysql/mysql.sock
user = mysql
#####修改事務隔離級別####
transaction-isolation = READ-COMMITTED
default_storage_engine = InnoDB
default-time_zone = '+8:00' #修改mysql日誌中的時區。
log_timestamps=SYSTEM
#InnoDB
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
#name-resolve
skip-host-cache
explicit_defaults_for_timestamp = true
#character-set
character-set-server = utf8
collation-server = utf8_general_ci
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
max_connections = 5000 #允許的最大連線數
#fix up table open cache too small
table_open_cache = 1024
open_files_limit = 65535
ignore-db-dir=lost+found
#LOG
log-error=/var/log/mysqld.log
general_log_file=/var/log/mysql-general.log #除錯時開啟下面的general_log=ON,正常執行後需要關閉
general_log=OFF
slow_query_log=ON
long_query_time = 5
slow_query_log_file = /var/log/mysql-slow.log
log_queries_not_using_indexes=false
server-id = 1 #叢集中每個主機的ID需要不一樣。
log-bin = /usr/local/mysql/binlogs/mysql-bin #binlog的日誌,最好和資料庫目錄放在不同的物理磁碟中。日誌作用是用來做資料同步的。
expire_logs_days = 10 #儲存的時間,如果其它節點宕機10天以後啟動加入叢集將會做資料的完全同步。如果在宕機後的第九天加入叢集將會接著關機時的狀態進行資料同步。
skip-name-resolve
relay-log = mysqld-relay-bin
innodb_support_xa = 1
relay_log_purge = 0
innodb_print_all_deadlocks = on
sync_binlog=2
#slave-skip-errors = all
#優化配置
join_buffer_size = 2M
sort_buffer_size = 2M
key_buffer_size=512M
read_rnd_buffer_size=2M
query_cache_type=1
query_cache_size=6M
tmp_table_size = 512M
innodb_thread_concurrency=64
innodb_buffer_pool_size=10G
max_binlog_size = 1G
max_relay_log_size = 1G
innodb_lock_wait_timeout=120
#innodb_data_file_path = ibdata1:1G:autoextend
#審計日誌配置 審計的配置第一次需要註釋掉,啟動完以後進入到mysql裡面命令安裝外掛等操作
#audit_log_file='/var/log/mysql-audit.json'
#audit_log_format=JSON
#audit_log_policy=QUERIES
#audit_log_rotate_on_size=4096
#audit_log_rotations=7
#audit_log_include_commands='create,update,insert,drop,grant,delete,select' #審計日誌的sql命令型別。
#新增配置
innodb_log_file_size=20M
binlog_stmt_cache_size=1M
binlog_cache_size=1M
table_open_cache=5000
#Start For Mysql Zabbix plugin
binlog_stmt_cache_size=1M
binlog_cache_size=1M
#End For Mysql Zabbix plugin
log-queries-not-using-indexes = false
gtid_mode=ON
enforce_gtid_consistency=on
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
#galera config 叢集相關配置
wsrep_provider=/usr/lib64/libgalera_smm.so
wsrep_cluster_address=gcomm://192.168.2.181,192.168.2.183,192.168.2.185 #叢集中的主機,根據實際情況填寫。
wsrep_slave_threads=16
innodb_autoinc_lock_mode=2
wsrep_node_address=192.168.2.181 #本機用來做資料同步的IP地址,這裡的地址可以和用來做服務的地址在不同網段。
wsrep_sst_method=xtrabackup-v2 #同步方式
pxc_strict_mode=MASTER #同步模式
wsrep_cluster_name=mysql-cluster #叢集名稱
wsrep_sst_auth="sstuser:
[client]
socket = /var/lib/mysql/mysql.sock
port = 3306
配置完第一臺主機後需要使用service [email protected] start啟動第一臺主機。注意這個命令只在初始化叢集的時候使用,如果叢集已經啟動過以後請使用service mysql start命令正常啟動。包括叢集中所有主機宕機以後的恢復。
centos7以上的系統請使用systemctl start [email protected] 和systemctl start mysql命令。
啟動完成以後建立同步帳號:
CREATE USER 'sstuser'@'localhost' IDENTIFIED BY '
GRANT RELOAD, LOCK TABLES,REPLICATION CLIENT ON . TO'sstuser'@'localhost';
請注意資料庫目錄和binlog等目錄的許可權,一定要是mysql。修改許可權請使用chown mysql:mysql 目錄名 -R 命令修改。啟動具體報錯請檢視日誌檔案。
如果是從其它版本的資料庫中遷移過來的資料,請使用mysql_upgrade -u root -p命令對資料庫檔案進行更新。否則可能無法正常訪問資料表。
檢查日誌檔案以後全部正常,資料庫能正常操作訪問以後第一臺主機就啟動完成了。
接下來是加入新節點。
在其它主機上安裝好程式,建立好相關的檔案目錄把配置檔案/etc/my.cnf複製過去。修改配置檔案中的server-id、wsrep_node_address兩個引數。然後使用service mysql start 或systemctl start mysql命令啟動資料庫,新加入的節點將會自動從主資料庫中同步所有資料到新節點中。可以訪問主資料庫performance_schema.pxc_cluster_view表檢視叢集中節點的狀態。SYNCED表示可用,JOIN表示正在加入,DONOR表示正在同步。具體請檢視percona的官方文件。
新節點加入時請監控新節點的啟動日誌檔案,排查相關錯誤。
啟動同步節點報錯
WSREP_SST: [ERROR] xtrabackup_checkpoints missing, failed innobackupex/SST on donor
檢查主資料庫目錄下的innobackup.backup.log 日誌檔案檢視具體原因。
所有節點全部加入叢集以後,請把第一臺節點使用service
二、部署負載均衡服務haproxy和keepalive高可用
yum install haproxy keepalive -y 安裝程式包。這裡需要兩個主機,配置不用太高。最好是資料庫以外的主機來進行安裝部署。這裡需要規劃出一個浮動地址用於高可用。
配置vi /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 50000 #整個服務的最大連結數
user root
group root
daemon
#turn on stats unix socket 做zabbix監控時需要
stats socket /var/lib/haproxy/stats
defaults
mode http
log global
option tcplog
option dontlognull
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout server 60m #做資料庫需要配置1小時左右,60m可以是1h效果一樣
timeout client 60m #做資料庫需要配置1小時左右
timeout http-keep-alive 10s
timeout check 3s
listen stats #網頁監控相關配置
bind :9099
stats uri /nstatus
stats enable
stats realm HAPorxy\ Stats\ Page
stats auth monitor:Hawatch2.tz.Com
stats admin if TRUE
listen mysql-cluster #負載均衡的服務配置
bind 0.0.0.0:3306
mode tcp
fullconn 13500 #提供的最大後端總連結數
balance leastconn #負載均衡的模式,經過測試這個模式是最適合mysql服務的。最小連結數優先
option httpchk
option tcplog
server db01 192.168.2.181:3306 maxqueue 30 maxconn 4500 check port 9200 inter 1000 rise 3 fall 3
server db02 192.168.2.183:3306 maxqueue 30 maxconn 4500 check port 9200 inter 1000 rise 3 fall 3
server db03 192.168.2.185:3306 maxqueue 30 maxconn 4500 check port 9200 inter 1000 rise 3 fall 3
db01可以是任意內容,每行代表一個後端主機不能重複。db01.example.com:3306 主機域名或者IP地址埠。maxqueue 建立後端連線時的最大列隊,防止伺服器處理不過來後臺被宕機。maxconn 伺服器最大連結數,需要小於資料庫的真實連結數配置。check port 9200 檢查後端服務是否正常的埠。
通過以上配置後可以正常啟動haproxy服務了。service haproxy start 或systemctl start haproxy。然後開啟網頁後端進行檢視伺服器狀態。這時可能還無法正常提供服務,需要對mysql的後端做一些配置。
到後端的資料庫伺服器上安裝xinetd。
yum install xinetd -y
/etc/xinetd.d/mysqlchk #提供檢查埠的配置檔案。
/usr/bin/clustercheck #檢查結果的指令碼,需要修改這個指令碼中兩個引數。
MYSQL_USERNAME="${1-sstuser}"
MYSQL_PASSWORD="${[email protected]#%}" 檢查狀態的帳號密碼可以用資料庫同步的帳號密碼。
然後啟動xinetd服務,service xinetd start或者systemctl start xinetd。啟動成功後再檢視haproxy的監控頁面就會發現後端服務變成可用狀態了。
haproxy的日誌需要配置rsyslog服務。
vi /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
.info;mail.none;authpriv.none;cron.none;local2.none /var/log/messages
local2. /var/log/haproxy.log
上面的local2編號需要和haproxy配置檔案中的一樣。配置完以後重啟service rsyslog restart。然後在/var/log/haproxy.log中就有日誌檔案了。
把上面haproxy的複製一份到另外一臺主機上。配置rsyslog以後重啟rsyslog服務,再啟動haproxy就擁有了兩臺主機了。
配置keepalived實現高可用:
編輯vi /etc/keepalived/keepalived.conf 檔案。
global_defs {
router_id mysql
}
vrrp_script check_ha {
script "/opt/share/selfTools/check_haproxy" #用於檢測服務的指令碼。需要自己編寫,成功返回0失敗返回非0的值,目錄可以自己定義。
interval 2
}
vrrp_instance ha01 { #這個編號需要每個主機不一樣
state BACKUP #兩個都設定成BACKUP模式,可以避免頻繁切換引發應用不穩定。
interface eth0 #繫結的網絡卡名稱
virtual_router_id 22 #兩個主機需要一樣。
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_ha
}
virtual_ipaddress {
192.168.2.191/24 dev eth0 scope global #浮動地址配置
}
}
指令碼配置:/opt/share/selfTools/check_haproxy
#!/bin/bash
nc -z 127.0.0.1 3306 #檢查本機的haproxy服務埠是否存在
status=$?
nc -z 127.0.0.1 9099 #檢查haproxy的狀態監控埠是否存在
status=$(($?+$status))
exit $status #返回指令碼執行的退出值
這裡需要在主機上安裝nc。yum install nc -y
啟動keepalived,service keepalived start 。然後檢查浮動地址情況。把配置檔案複製一份到另外的主機上,修改vrrp_instance ha01的名稱。其它保持不變,啟動keepalived服務即可。
到這裡就算配置完成了,業務訪問浮動地址就能直接分配到後端的資料庫伺服器上。
三、監控服務
資料庫叢集監控,安裝percona-zabbix-templates-1.1.8-1.noarch 、php包。
複製userparameter_percona_mysql.conf檔案到/etc/zabbix/zabbix_agentd.d/目錄下。
編輯檔案vi /var/lib/zabbix/percona/scripts/ss_get_mysql_stats.php 填寫mysql的監控帳號和密碼然後儲存。
檢查zabbix.conf檔案中是否有Include=/etc/zabbix/zabbix_agentd.d/.conf這個配置。沒有請新增。
模版需要自己到zabbix監控裡面配置,我的模版無法把檔案上傳上來。
percona的監控指令碼還不能用於監控叢集狀態。需要自行編寫指令碼來監控。在zabbix的配置檔案中新增兩個內容。
UserParameter=Galera.discovery,/opt/share/shell/galera/galera_discovery.sh
UserParameter=Galera.[],/opt/share/shell/galera/galera_status.sh $1
指令碼/opt/share/shell/galera/galera_discovery.sh內容:
#!/bin/bash
sql="show status like 'wsrep%';"
galeras=(echo "set names utf8;$sql" |HOME=/var/lib/zabbix mysql -N | awk '{print $1}'
)
text=(wsrep_local_state_uuid wsrep_flow_control_interval wsrep_local_state_comment wsrep_incoming_addresses wsrep_ist_receive_status wsrep_evs_repl_latency wsrep_evs_state wsrep_gcomm_uuid wsrep_cluster_state_uuid wsrep_cluster_status wsrep_connected wsrep_provider_name wsrep_provider_vendor wsrep_provider_version wsrep_ready)
float=(wsrep_cert_interval wsrep_commit_window wsrep_commit_oool wsrep_commit_oooe wsrep_apply_window wsrep_apply_oool wsrep_apply_oooe wsrep_cert_deps_distance wsrep_flow_control_paused wsrep_local_recv_queue_avg wsrep_local_send_queue_avg)
printf '{"data":['
i=1
for option in ${galeras[@]}
do
if [[ echo "${text[@]}" | grep "\b$option\b"
]] ;then
printf '{"{#TEXT}":"'$option
elif [[ echo "${float[@]}" | grep "\b$option\b"
]] ;then
printf '{"{#FLOAT}":"'$option
else
printf '{"{#OTNAME}":"'$option
fi
if [ $i -lt ${#galeras[@]} ];then
printf '"},'
else
printf '"}]}\n'
fi
i=$(($i+1))
done
指令碼/opt/share/shell/galera/galera_status.sh內容:
#!/bin/bash
sql="show status like '$1';"
if [ -z $2 ];then
echo "set names utf8;$sql" |HOME=/opt/share/shell/galera mysql -N | awk '{print $2}'
else
echo "set names utf8;$sql" |HOME=/opt/share/shell/galera mysql -h$2 -N | awk '{print $2}'
fi
四、擴充套件解決方案
1、在使用HAproxy以後mysql中日誌與客戶端IP相關的資訊將全部變成haproxy伺服器的地址。
啟用haproxy的透傳功能,把客戶端IP通過haproxy傳給realserver。資料包到達realserver以後將無法直接把資料返回給客戶端的真實IP,這將無法建立tcp的連結。所以需要把資料包返回給haproxy伺服器。haproxy拿到資料包以後需要擷取到相關資料包傳給haproxy程序處理才能完成整個tcp的連結建立。具體看圖:
需要完成圖中的幾步才能完成整個建立過程。具體配置方法:
1)、配置haproxy。在配置的listen中加入source 0.0.0.0 usesrc clientip這樣的配置。
2)、配置資料包擷取:
配置/etc/sysctl.conf,新增 一下內容
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 0
執行命令,執行完以後還需要配置開啟自動執行。iptables相關規則可以儲存後執行載入,路由表需要每次開機都進行建立。
iptables -t mangle -N MYSQL #單獨在mangle表中建立一個名為MYSQL的連結串列
iptables -t mangle -A PREROUTING -m state --state RELATED,ESTABLISHED -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp -m socket -j MYSQL #從mangle表中的PREROUTING鏈中擷取資料包是tcp協議,並且為socket的資料包。轉發到MYSQL連結串列中。
iptables -t mangle -A MYSQL -j MARK --set-mark 1 #在MYSQL連結串列中把進來的資料包打上標籤為1
iptables -t mangle -A MYSQL -j ACCEPT #接受所有資料包通過。
ip rule add fwmark 1 lookup 3306 #經過上面的資料包標記,在系統核心中就能分辨相關的資料包內容。這裡新建一個路由表編號3306為資料包標記為1的路由。
ip route add local 0.0.0.0/0 dev lo table 3306 #在3306路由表中建立一條路由規則,把進入3306表中的資料包預設路由給本地環回口。這樣haproxy就能拿到相關的資料包進行處理了。
3)、以上兩步是在HAROXY的伺服器上配置。這步將在後端的真實伺服器上進行配置。
iptables -t mangle -N MYSQL #新增連結串列,意義同上
iptables -t mangle -A OUTPUT -p tcp --sport 3306 -j MYSQL #這裡需要從OUTPUT連結串列中擷取資料包,其它連結串列無效。具體原因請看下面的LINUX資料包轉發圖。獲取源埠為3306的資料包,因為是OUTPUT出方向所以是源埠。
iptables -t mangle -A MYSQL -j MARK --set-mark 1 #進行資料包標記。
iptables -t mangle -A MYSQL -j ACCEPT #接受所有資料包通過
ip rule add fwmark 1 table 3306 #功能同上,建立新的路由表。
ip route add default via 192.168.2.191 table 3306 #新增預設路由,下一跳給到HAPROXY。
這裡可以不進行資料包的擷取標記也可以讓業務正常,只需要新增一跳預設路由,ip route default via HAPROXY_IP。這樣就能實現,但是ssh等其它服務將不能正常連線。
4)、可以代替第三節。主要是如果直接更改就沒有對比了。下面的命令也是直接在資料庫伺服器上做的。
iptables -t mangle -A PREROUTING -m state --state RELATED,ESTABLISHED -j CONNMARK --restore-mark #已經建立的連結自動附上標記
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT # 已經有標記的資料包直接放行,不進入下面匹配。提高處理效率。
iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 3306 -m mac --mac-source 00:50:56:a0:13:a2 -j MARK --set-mark 1 #這裡的MAC地址是HAPROXY伺服器的網絡卡地址。
iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 3306 -m mac --mac-source 00:50:56:81:4F:08 -j MARK --set-mark 2 #我們有兩個haproxy所以要兩個標記
iptables -t mangle -A PREROUTING -j CONNMARK --save-mark #把這個做好標記的鏈路上所有資料包都儲存好標記。
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark #前面做的都是客戶端訪問到主機時資料包的入方向,這句如果不加將無法路由出去。OUTPUT鏈是把資料包按照入方向標記好的記錄,重新賦予相關的標記。讓路由可以正確拿到出去的資料包。
ip rule add fwmark 1 table 3301
ip route add default via 192.168.2.150 table 3301 #這兩條是對資料包進行路由,IP地址是haproxy的真實網絡卡地址。也就是上面mac地址為00:50:56:a0:13:a2主機IP地址,非浮動地址。
ip rule add fwmark 2 table 3302
ip route add default via 192.168.2.153 table 3302 #這兩條和上面功能一樣,IP地址是mac地址為00:50:56:81:4F:08的主機IP地址。
這裡不用填寫浮動地址,這樣不管浮動地址在哪裡。或者訪問任何一個主機都可以正常連線資料庫。
如果按照前面第三節的方法處理以後,客戶端無法直接連結資料庫、而且正常情況下也無法去訪問沒有浮動地址的那個伺服器。第四節的方法處理以後將和沒有使用叢集一樣,連結和訪問沒有任何差異。
2、haproxy伺服器的狀態監控。
在伺服器zabbix中配置兩項/etc/zabbix/zabbix_agentd.conf。
UserParameter=ha.discovery,/opt/share/shell/zabbix-script/haproxy/haproxy_discovery.sh
UserParameter=Haproxy.[*],/opt/share/shell/zabbix-script/haproxy/haproxy_get.sh $1
haproxy_discovery.sh:
#!/bin/bash
node=(echo "show stat" | socat /var/lib/haproxy/stats stdio | sed "s/#//g" | awk 'BEGIN {FS=","}{print $2}' |sed '/FRONTEND/d;/BACKEND/d;1d;$d'
)
options=(qcur qmax scur smax stot status)
printf '{"data":['
i=1
for name in ${node[@]}
do
n=1
for op in ${options[@]}
do
if [ $n -lt ${#options[@]} ];then
printf '{"{#NODE}":"'$name-$op
else
printf '{"{#TEXT}":"'$name-$op
fi
if [ $i -lt ${#node[@]} ] || [ $n -lt ${#options[@]} ];then
printf '"},'
else
printf '"}]}\n'
fi
n=$(($n+1))
done
i=$(($i+1))
done
haproxy_get.sh:
#!/bin/bash
cd dirname $0
values=(echo $1|awk 'BEGIN{FS="-"}{print $1" "$2}'
)
case ${values[1]} in
"qcur")
grep ${values[0]} status.txt | awk '{print $2}'
;;
"qmax")
grep ${values[0]} status.txt | awk '{print $3}'
;;
"scur")
grep ${values[0]} status.txt | awk '{print $4}'
;;
"smax")
grep ${values[0]} status.txt | awk '{print $5}'
;;
"stot")
grep ${values[0]} status.txt | awk '{print $6}'
;;
"status")
grep ${values[0]} status.txt | awk '{print $7}'
;;
esac
為減少對haproxy的衝擊。建立一個定時計劃任務,定期獲取狀態資料儲存到檔案中。
haproxy_status.sh:
#!/bin/bash
cd dirname $0
echo "show stat" | socat /var/lib/haproxy/stats stdio | sed "s/#//g" | awk 'BEGIN {FS=","}{print $2"\t"$3"\t"$4"\t"$5"\t"$6"\t"$8"\t"$18}' > status.txt
如果沒有socat命令需要使用yum安裝。/var/lib/haproxy/stats這個檔案需要有許可權訪問,用chmod 606來調整。
zabbix的除錯可以在zabbix-server伺服器上使用zabbix_get命令進行除錯。如:
zabbix_get -s 192.168.2.150 -k 'Haproxy.[db02-scur]' 其中的key是被監控主機自定義的欄位名稱。
同樣模版的建立,請大家自行處理。無法上傳模版檔案共享。
本文章只是提供一個拋磚引玉的作用,需要的基礎知識比較多,具體問題請自行解決。