mysql-故障轉移+負載均衡群集
mysql-故障轉移+負載均衡
環境:centOS6.5-64bit,mysql-server版本或5.x以上版本;
mysql企業版本檔案太大,資源裡就不上傳了。可自行去官網下載,不一定非要企業版,只要是5.x以上版本就可以了
也可到官方網站下載最新版本。
說明:
keepalived 實現通過 vrrp協議,通過使一個虛擬IP地址(或稱浮動IP)在主備裝置間的切換來達到主機冗餘;
而客戶機通過訪問這個虛擬IP 來獲取服務;
haproxy 是一款負載均衡軟體,用於將請求按策略轉發給不同主機,達到負載均衡的效果;
可以實現網路層或應用層上的判斷分配;
mysql 開啟二進位制日誌,做到資料庫之間的雙向複製,保持資料一致性;
#提醒一下,實際生產環境沒人會這樣搭建的,僅通過這個實驗來理解這些概念,希望閱者能有所獲;
server1_ip=222.31.102.19
server2_ip=222.31.102.20
server_vip=222.31.102.30
================================================
#此處關閉了防火牆,開啟則另配置相應規則
service iptables stop
chkconfig iptables off
ls /opt/soft/ #提取準備軟體到此處
haproxy-1.4.20.tar.gz keepalived-1.2.7.tar.gz
mkdir /opt/keepalived
mkdir /opt/scripts/ #此實驗用到指令碼目錄
mkdir /opt/log/ #此實驗日誌資料夾
=================================================
[install_mysql]
#在兩臺主機上安裝 mysql ,此處使用 rpm 包安裝,yum環境可以搭本地源;
yum install -y mysql-server
service mysqld start
2.3.1 Mysql安裝步驟
1. 檢視系統中是否已經安裝了MySql
rpm -qa | grep -i mysql
2. 如已經有mysql相關安裝,將其解除安裝
rpm –e –nodeps xxx(1中顯示的mysql相關安裝)
3. 檢視mysql服務
chkconfig --list | grep -i mysql
4. 刪除mysql服務
如有mysql服務,將其刪除
chkconfig --del mysql
5. 清除mysql資料夾
whereis mysql
將顯示的資料夾刪除
rm –rf xxxx
6. 安裝mysql
1. 解壓MySql安裝包
unzip xxxx
2. 安裝MySql
rpm –ivh MySQL- server*.rpm
rpm –ivh MySQL- client*.rpm
7. 啟動mysql服務
1. servicemysql start
8. 首次進入mysql,修改密碼
1. 檢視初始密碼
cat ~/.mysql_secret
2. 登陸mysql
mysql –uroot –pxxxx
3. 修改密碼
set password for'root'@'localhost'=password('newpasswd');
4. 重新整理許可權
flush privileges;
9. 建立資料庫,使用者、授權…
1. 如果有資料要匯入到資料庫發現匯入的資料有遺漏現象請修改mysql配置檔案max_allowed_packet的值,windows系統下配置檔案為my.ini,linux系統下為my.cnf,在配置檔案找到[mysqld] 節點並在其下面插入一條max_allowed_packet=20M(可以適當修改)
=======================================================
[create_mysql_test_table]
#分別建立一張相同名稱和欄位的表,插入不同的值,方便中途測試 ha 和輪詢是否成功;
#還有分別建立一個相同的使用者
#server1
mysql
>use test;
>create table mywait(name char(9),phonechar(14));
>insert into mywait(name,phone)values('wait',15000000000);
#server2
>use test;
>create table mywait(name char(9),phonechar(14));
>insert into mywait(name,phone)values('chen',15611111111);
[new_mysql_test_user]
>mysql
>grant all on test.* to test@'%'identified by '123456';
>flush privileges;
=======================================================
#從客戶機上測試一下;
mysql -utest -p123456 -h 222.31.102.19 -e"select * from test.mywait;"
mysql -utest -p123456 -h 222.31.102.20 -e"select * from test.mywait;"
#至此,mysql 基礎環境搭建完成;
=======================================================
[install_keepalived]
yum install -y libnl-devel #解決依賴關係
yum install -y openssl-devel
tar xf /opt/soft/keepalived-1.2.7.tar.gz -C/opt/soft
cd /opt/soft/keepalived-1.2.7/
#with-kernel 指定核心版本時,根據本機情況使用TAB鍵補全
./configure --prefix=/opt/keepalived--with-kernel-dir=/usr/src/kernels/2.6.18-308.el5-i686/
make && make install
[keepalived_config]
#因為沒有安裝在 / 目錄下,所以這些啟動和配置檔案都需要再 copy 一下;
cp /opt/keepalived/sbin/keepalived/usr/sbin/
cp/opt/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
cp /opt/keepalived/etc/sysconfig/keepalived/etc/sysconfig/
mkdir /etc/keepalived
cp /opt/keepalived/etc/keepalived/keepalived.conf/etc/keepalived/
#設定開機啟動
[root@stb keepalived-1.2.12]# chkconfig--add keepalived
[root@stb keepalived-1.2.12]# chkconfigkeepalived --list
keepalived 0:關閉 1:關閉 2:關閉 3:關閉 4:關閉 5:關閉 6:關閉
[root@stb keepalived-1.2.12]# chkconfig keepalivedon
[root@stb keepalived-1.2.12]# chkconfigkeepalived --list
keepalived 0:關閉 1:關閉 2:啟用 3:啟用 4:啟用 5:啟用 6:關閉
[root@stb keepalived-1.2.12]#
=======================================================
vim /etc/keepalived/keepalived.conf#keepalived 主配檔案
! Configuration File for keepalived
#簡單的頭部,這裡主要可以做郵件通知報警等的設定,此處就暫不配置了;
global_defs {
notificationd LVS_DEVEL
}
#預先定義一個指令碼,方便後面呼叫,也可以定義多個,方便選擇;
vrrp_script mysql_chk {
script "/opt/scripts/mysql_chke.sh"
interval 2 #指令碼迴圈執行間隔
weight 2 #指令碼的結果導致優先順序變更,成功+2
}
#VRRP虛擬路由冗餘協議配置
vrrp_instance VI_1 { #VI_1 是自定義的名稱;
state MASTER #表明這是一臺主裝置,備用裝置為 BACKUP
interface eth1 #指定VIP需要繫結的物理網絡卡
virtual_router_id 11 #VRID虛擬路由標識,也叫做分組名稱,該組內的裝置需要相同
priority 150 #定義這臺裝置的優先順序1-254;
advert_int 1 #生存檢測時的組播資訊傳送間隔,組內一致
authentication { #設定驗證資訊,組內一致
auth_type PASS #有PASS 和 AH 兩種,常用 PASS
auth_pass 111 #密碼
}
virtual_ipaddress { #指定VIP地址,組內一致,可以設定多個IP
222.31.102.30/24
}
track_script { #使用在這個域中使用預先定義的指令碼
mysql_chk
}
#此部分所載入的指令碼為外部指令碼,不需要預先定義;
#也可不新增,此實驗在後半部分安裝haproxy後,才有新增;
notify_master /opt/scripts/start_haproxy.sh #表示當切換到master狀態時,要執行的指令碼
notify_fault /opt/scripts/stop_keepalived.sh #故障時執行的指令碼
notify_stop /opt/scripts/stop_haproxy.sh #keepalived停止執行前執行的指令碼
}
#keepalived 主和備的配置檔案基本相同;只需要修改:
state BACKUP #修改為備份裝置
priority 100 #優先順序要比主低
#其它地方根據實際情況也可以做調整;
=======================================================
#新建剛才配置keepalived 時所定義的指令碼,用於在mysql死亡後結束 keepalived
[root@stb scripts]#
[root@stb scripts]# vim mysql_chke.sh
[root@stb scripts]# cat/opt/scripts/mysql_chke.sh
#!/bin/bash
#mysql_chke.sh
#
a=`ps -C mysqld --no-header | wc -l`
if [ $a -eq 0 ];then
sleep 3
/sbin/service keepalived stop
echo "`date +%c` stop keepalived" >>/opt/log/stop_keepalived.log
fi
service keepalived start
[root@stb scripts]# service keepalivedstart #在兩臺裝置上面啟動
#開始測試
ip address
#檢視主裝置 11 上是否有生成 vip 地址;
#注意事項,keepalived 生成的 VIP 對 ifconfig 命令不可見,所以需要使用ip addr命令;
[root@stb ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP>mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:b8:94:34 brd ff:ff:ff:ff:ff:ff
inet 222.31.102.19/24 brd 222.31.102.255 scope global eth1
inet 222.31.102.30/24 scope global secondary eth1
inet6 2002:de1f:667a:b:20c:29ff:feb8:9434/64 scope global dynamic
valid_lft 2591775sec preferred_lft 604575sec
inet6 fec0::b:20c:29ff:feb8:9434/64 scope site dynamic
valid_lft 2591775sec preferred_lft 604575sec
inet6 fe80::20c:29ff:feb8:9434/64 scope link
valid_lft forever preferred_lft forever
[root@stb ~]#
mysql -utest -p123456 -h 222.31.102.30 -e"select * from test.mywait;"
#正常情況是隻能查詢到 MASTER 的資料庫的資料;
1、嘗試將 MASTER 的keepalived 停掉
2、down 掉 MASTER 的網絡卡
3、讓mysql 啟動不了,比如先註釋掉mysql這個使用者,後killallmysqld ,
檢視mysql_chke 指令碼是否會把 keepalived 結束掉;
#這個時後 vip 地址會移動到 Slave 主機上; HA 搭建的是否成功體現於查詢所獲取值的變化;
#當將 MASTER 恢復後,VIP 又會回到 11 的裝置上;
#至此 keepalived 為 mysql 做HA 模式成功;
========================================================================
二、
[install_haproxy]
#用於將請求分別輪詢到222.31.102.19 222.31.102.20
tar xf /opt/soft/haproxy-1.4.20.tar.gz -C/opt/soft/
cd /opt/soft/haproxy-1.4.20/
make TARGET=linux26 PREFIX=/opt/haproxyinstall
mkdir /opt/haproxy/conf
mkdir /opt/haproxy/logs
touch /opt/haproxy/conf/haproxy.cfg
========================================================================
[mysql_config]
#修改 mysql 監聽,使 mysql 避開222.31.102.30,因為 haproxy 也要監聽 30:3306 這個IP地址和埠;
vim /etc/my.cnf
#server1
[mysqld]
bind-address=222.31.102.19 #mysql 的監聽,新增這一句就好了
#server2
[mysqld]
bind-address=222.31.102.20
#重啟mysql
service mysqld restart
#到現在已經不能通過222.31.102.30 訪問資料庫了,接下來配置 haproxy
========================================================================
[config_haproxy]
#主備伺服器的主配檔案一致;
[root@stb scripts]# cat/opt/haproxy/conf/haproxy.cfg
global #全域性系統配置
log 127.0.0.1 local0 info #定義日誌級別[errwarning info debug]
#local0 是日誌裝置,必須為24種標準syslog裝置之一;
maxconn 4096 #最大連結數
uid 0 #執行該程式的使用者,此處沒有其它使用者了,就用的root
gid 0
daemon #以後臺形式執行
nbproc 1 #程序數量
defaults #預設配置
mode tcp #所處理的類別 http |tcp | health
option redispatch #serverId對應的伺服器掛掉後,強制定向到其他健康的伺服器
retries 3 #三次連線失敗則伺服器不用
timeout connect 5000 #連線超時
timeout client 50000 #客戶端超時
timeout server 50000 #伺服器超時
timeout check 2000 #心跳檢測超時
listen proxy
bind 222.31.102.30:3306 #監聽地址
mode tcp
balance roundrobin #定義負載方式,此處為輪詢
log 127.0.0.1 local0 info #定義日誌型別
#rise 3三次正確表示伺服器可用,fall 3表示3次失敗表示伺服器不可用
server db1 222.31.102.19:3306 check inter 1200 rise 2 fall 3 weight 1
server db2 222.31.102.20:3306 check inter 1200 rise 2 fall 3 weight 1
#伺服器狀態監控配置,可以通過定義的地址檢視叢集狀態;
listen haproxy_stats
log 127.0.0.1 local0 info
mode http
bind 222.31.102.30:8888
option httplog
stats uri /status
stats realm Haproxy Manager
stats auth admin:admin #設定監控地址的帳號與密碼
#在keepalived 主配檔案中新增剛才在其末端說明的外部定義指令碼
[root@stb scripts]#
#啟動服務
/opt/haproxy/sbin/haproxy -f/opt/haproxy/conf/haproxy.cfg
#說明事項,keepalived 的服務主備裝置上都可以同時執行,實則只有獲得VIP的伺服器才有效;
#但是 haproxy 啟動的時候需要監聽 VIP地址,所以第一次備用裝置是手動起不了服務的;
#需要在 keepalived 的notify_master配置項中設定指令碼,當此裝置獲得VIP地址後才啟動 haproxy;
#有個問題在這裡,我們只設定了當keepalived停止服務時,才結束 haproxy ,沒有設定移交VIP時是否結束;
#其實這也不用擔心,因為主機上已經沒有VIP地址了,即便是監聽也無效果,並無干擾;
========================================================================
##開始測試
#檢測監聽
netstat -tunlp | grep ha
netstat -tunlp | grep 3306
# master 裝置上才會有兩個程式監聽不同地址的3306;
#暫未配置 mysql 互為主備就是為了方便這一階段的排錯,這樣能更準確的測試;
mysql -utest -p123456 -h 222.31.102.30 -e"select * from test.mywait;"
#返回值應該是在 server1server2 之間徘徊;
sed -i 's/^mysql.*$/#&/'/etc/passwd #註釋掉mysql的使用者
service mysqld stop
#這個時候 mysql 服務已經啟動不起了,mysql_chke.sh指令碼會把 keepalived 停止掉;
keepalived 停止前,又會把 haproxy 殺死;當備份的裝置獲得vip 後,則會通過start_haproxy.sh 指令碼將 haproxy 啟動起來;
於是並不會因為伺服器當機或mysql故障,影響我們客戶端對 30 的查詢操作,實驗完成一半了;
#但是測試時,在VIP地址切換過程中,客戶端會有那麼2-3秒不能訪問到資料庫,這個暫時忽略不計;
sed 's/^#//' /etc/passwd #測試完後,記得恢復mysql使用者哦;
#恢復mysql 後,啟動主裝置的mysqld keepalived ,然後使用 ip a 檢視VIP 地址是否有返回來;
#在其中一臺裝置上 killallhaproxy ,之後檢視叢集狀態;
http://222.31.102.30:8888/status
#檢視後再將 haproxy 啟動
#至此,已經完成 負載均衡 + 高可用 兩部分,負載方式為輪詢
========================================================================
##三個指令碼,很簡單,就不再介紹了哈;主要是做日誌和結束服務;
[root@stb scripts]# cat start_haproxy.sh
#!/bin/bash
#start_haproxy.sh
sleep 5
get=`ip addr |grep 222.31.102.30 |wc -l`
echo $get >>/opt/log/start_haproxy.log
if [ $get -eq 1 ]
then
echo "`date +%c` success to get vip" >>/opt/log/start_haproxy.log
/opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg
else
echo "`date +%c` can not get vip" >>/opt/log/start_haproxy.log
fi
[root@stb scripts]#
[root@stb scripts]# cat stop_haproxy.sh
#!/bin/bash
#stop_haproxy.sh
pid=`pidof haproxy`
echo "`date +%c` stop haproxy">> /opt/log/stop_haproxy.log
kill -9 $pid
[root@stb scripts]#
[root@stb scripts]# cat stop_keepalived.sh
#!/bin/bash
#stop_keepalived.sh
pid=`pidof keepalived`
if [ $pid == "" ]
then
echo "`date +%c` no keepalived process id" >> /opt/log/stop_keepalived.log
else
echo "`date +%c` will stop keepalived " >> /opt/log/stop_keepalived.log
/etc/init.d/keepalived stop
fi
[root@stb scripts]#
=======================================================
[mysql Manager Slave]
#mysql 主備配置;兩臺裝置上新增使用者哦;
root#mysql
create database db1;
GRANT REPLICATION SLAVE ON *.* TO'test1'@'%' IDENTIFIED BY '123456';
#此處注意哦,Slave 許可權必須的,我最初使用 all 許可權,結果主備始終不同步,改成 Slave 就OK了;
flush privileges;
show grants for test1@'%';
==================================================================
#server1 的 mysql 配置 #server_id=1 #伺服器標識,唯一 #log_bin=mysqlbinlog #啟用二進位制日誌 #log_bin_index=mysqlbinlog-index #日誌索引檔案 #log_slave_updates=1 #讓從伺服器把自身複製的事件和記錄都寫到自己的二進位制日誌裡 #relay_log=relay-log #中繼日誌位置;存放slave端獲取到master端的二進位制檔案資訊 #replicate_do_db=db1 ##指定需要同步的資料庫 [root@stb scripts]# cat /usr/my.cnf # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html [mysqld] # Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M bind-address=222.31.102.19 #fyy-cust server_id=1 #伺服器標識,唯一 log_bin=mysqlbinlog #啟用二進位制日誌 log_bin_index=mysqlbinlog-index #日誌索引檔案 log_slave_updates=1 #讓從伺服器把自身複製的事件和記錄都寫到自己的二進位制日誌裡 relay_log=relay-log #中繼日誌位置;存放slave端獲取到master端的二進位制檔案資訊 #replicate_do_db=db1 ##指定需要同步的資料庫 master-host=222.31.102.20 master-user=test1 master-password=123456 master-port=3306 master-connect-retry=60 replicate-do-db=test binlog-ignore-db=mysql # Remove leading # to turn on a very important data integrity option: logging # changes to the binary log between backups. # log_bin # These are commonly set, remove the # and set as required. # basedir = ..... # datadir = ..... # port = ..... # server_id = ..... # socket = ..... # Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [root@stb scripts]# |
#server2 的 mysql 配置
server_id=2 log_bin=mysqlbinlog log_bin_index=mysqlbinlog-index log_slave_updates=1 relay_log=relay-log replicate_do_db=db1 |
#分別重啟兩服務
service mysqld restart
mysql> show master status; #檢視mysql 的當前二進位制日誌檔案
+--------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB |Binlog_Ignore_DB |
+--------------------+----------+--------------+------------------+
| mysqlbinlog.000001 | 98 | | |
+--------------------+----------+--------------+------------------+
1 row in set (0.28 sec)
#分別連線對方 mysql 日誌,開始備份;記得替換Master_Host 和日誌名及MASTER_LOG_POS;
>CHANGE MASTER TOMASTER_HOST='222.31.102.20',master_port=3306,MASTER_USER='test1',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysqlbinlog.000001',MASTER_LOG_POS=98;
>START SLAVE; #開始同步
mysql> SHOW SLAVE STATUS\G #檢視mysql同步狀態
*************************** 1. row***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 222.31.102.19
Master_User: mywait
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysqlbinlog.000001
Read_Master_Log_Pos: 98
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 237
Relay_Master_Log_File: mysqlbinlog.000001
Slave_IO_Running: Yes #表明獲取對方日誌檔案的連線成功;
Slave_SQL_Running: Yes #將獲取到的日誌轉成sql語句回寫本地資料庫成功;
Replicate_Do_DB: db1
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 237
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
#主要就是看Slave_IO_Running,Slave_SQL_Running
#這裡錯誤的話,多數情況是Slave_IO_Running 的問題,防火牆,使用者許可權,日誌是否有啟用等都需要判斷;
=====================================================================
=====================================================================
#至此 mysql 雙主互備搭建完成,我們的全部實驗規劃也全部完成;
#進入全面測試階段;
#在 server1 的DB1裡新建一張表,並賦值
>use db1;
>create table mywait(name char(9),phonechar(14));
>insert into mywait(name,phone)values('wait',15888888888);
#新建一個具有 db1 許可權的使用者
grant all on db1.* to test2@'%' identifiedby '123456';
>flush privileges;
#切換到 test 庫,在mywait 表中插入一條資料;
use test;
insert into mywait(name,phone) values('test',15002839961);
#在 server2做驗證;
>use db1;
>show tables;
>select * from mywait;
#此時資料與 server1 的會資料一致,表示mysql同步成功;
select user,host,password from mysql.user;
#在 server1 建立的使用者也會被server2 所同步;
#select * from test.mywait
#可以看到 server1上的 test 庫並沒有被同步;
#客戶機上測試
mysql -utest2 -p123456 -h 222.31.102.30 -e"select * from db1.mywait;"
#完畢;
=======================================================
#存在的問題;
在做mysql_chke 指令碼時,本打算使用檢查程序的形式判斷服務是否啟動;
`ps -C mysqld --no-header | wc -l`
當檢查mysql 程序不存在的時候,先試著啟動一次mysqld ,然後再檢測,如果還是啟動不了服務,再結束 keepalived ;
但是在使用 /etc/rc.d/init.d/mysqld start 啟動後,出現一些問題;
比如mysql 配置檔案錯誤或是登出使用者等,mysql服務已然起不來了,雖然手動起不來服務;
但使用 ps -C mysqld 還是可以檢查出一條mysqld 的程序來,這是什麼情況沒弄明白,希望能得到指點;
可優化項,haproxy 的功能很多,可以做成基於權重的分配方式,或是根據訪問地址的,甚至可以使用 cookie 做判斷;
大家都可以多測試一下;
有些地方是需要在兩臺伺服器上同時配置的,大家看的時候多留意一下,測試過程中多看日誌是最好的排錯方式;