目標:使用兩台主機實現 Mysql 的負載均衡及冗余,並做到雙主互備;
環境:rhel5.8,mysql-5.0.77,keepalived-1.2.7,haproxy-1.4.20;
說明:
keepalived 實現通過 vrrp協議,通過使一個虛擬IP地址(或稱浮動IP)在主備設備間的切換來達到主機冗余;
而客戶機通過訪問這個虛擬IP 來獲取服務;
haproxy 是一款負載均衡軟件,用於將請求按策略轉發給不同主機,達到負載均衡的效果;
可以實現網絡層或應用層上的判斷分配;
mysql 開啟二進制日志,做到數據庫之間的雙向復制,保持數據一致性;
#提醒一下,實際生產環境沒人會這樣搭建的,僅通過這個實驗來理解這些概念,希望閱者能有所獲;
server1_ip=192.168.5.11
server2_ip=192.168.5.12
server_vip=192.168.5.111
================================================
#此處關閉了防火牆,開啟則另配置相應規則
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 ======================================================= [create_mysql_test_table] #分別創建一張相同名稱和字段的表,插入不同的值,方便中途測試 ha 和輪詢是否成功; #還有分別創建一個相同的用戶 #server1 mysql >use test; >create table mywait(name char(9),phone char(14)); >insert into mywait(name,phone) values('wait',15000000000); #server2 >use test; >create table mywait(name char(9),phone char(14)); >insert into mywait(name,phone) values('chen',15611111111); [new_mysql_test_user] >mysql >grant all on test.* to diaosi@'%' identified by '123456'; >flush privileges; ======================================================= #從客戶機上測試一下; mysql -udiaosi -p123456 -h 192.168.5.11 -e "select * from test.mywait;" mysql -udiaosi -p123456 -h 192.168.5.12 -e "select * from test.mywait;" #至此,mysql 基礎環境搭建完成; ======================================================= [install_keepalived] yum install -y libnl-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/ chkconfig keepalived on #設置開機啟動 ======================================================= vim /etc/keepalived/keepalived.conf #keepalived 主配文件 #以下的配置適合 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 eth0 #指定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 192.168.5.111/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
#!/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 fi
service keepalived start #在兩台設備上面啟動
#開始測試
ip address
#查看主設備 11 上是否有生成 vip 地址;
#注意事項,keepalived 生成的 VIP 對 ifconfig 命令不可見,所以需要使用 ip 命令;
mysql -udiaosi -p123456 -h 192.168.5.111 -e "select * from test.mywait;"
#正常情況是只能查詢到 MASTER 的數據庫的數據;
1、嘗試將 MASTER 的keepalived 停掉
2、down 掉 MASTER 的網卡
3、讓mysql 啟動不了,比如先注釋掉mysql這個用戶,後killall mysqld ,
查看mysql_chke 腳本是否會把 keepalived 結束掉;
#這個時後 vip 地址會移動到 Slave 主機上; HA 搭建的是否成功體現於查詢所獲取值的變化;
#當將 MASTER 恢復後,VIP 又會回到 11 的設備上;
#至此 keepalived 為 mysql 做HA 模式成功;
========================================================================
[install_haproxy]
#用於將請求分別輪詢到 192.168.5.11 192.168.5.12
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/haproxy install
mkdir /opt/haproxy/conf
mkdir /opt/haproxy/logs
touch /opt/haproxy/conf/haproxy.cfg
========================================================================
[mysql_config]
#修改 mysql 監聽,使 mysql 避開 192.168.5.111,因為 haproxy 也要監聽 111:3306 這個IP地址和端口;
vim /etc/my.cnf
#server1
[mysqld]
bind-address=192.168.5.11 #mysql 的監聽,添加這一句就好了
#server2
[mysqld]
bind-address=192.168.5.12
#重啟mysql
service mysqld restart
#到現在已經不能通過 192.168.5.111 訪問數據庫了,接下來配置 haproxy
========================================================================
[config_haproxy]
#主備服務器的主配文件一致;
vim /opt/haproxy/conf/haproxy.cfg
global #全局系統配置 log 127.0.0.1 local0 info #定義日志級別[err warning 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 192.168.5.111:3306 #監聽地址 mode tcp balance roundrobin #定義負載方式,此處為輪詢 log 127.0.0.1 local0 info #定義日志類型 #rise 3三次正確表示服務器可用,fall 3表示3次失敗表示服務器不可用 server db1 192.168.5.11:3306 check inter 1200 rise 2 fall 3 weight 1 server db2 192.168.5.12:3306 check inter 1200 rise 2 fall 3 weight 1 #服務器狀態監控配置,可以通過定義的地址查看集群狀態; listen haproxy_stats log 127.0.0.1 local0 info mode http bind 192.168.5.111:8888 option httplog stats uri /status stats realm Haproxy Manager stats auth admin:admin #設置監控地址的帳號與密碼
#在keepalived 主配文件中添加剛才在其末端說明的外部定義腳本
#啟動服務
/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 -udiaosi -p123456 -h 192.168.5.111 -e "select * from test.mywait;"
#返回值應該是在 server1 server2 之間徘徊;
sed -i 's/^mysql.*$/#&/' /etc/passwd #注釋掉mysql的用戶
service mysqld stop
#這個時候 mysql 服務已經啟動不起了,mysql_chke.sh 腳本會把 keepalived 停止掉;
keepalived 停止前,又會把 haproxy 殺死;當備份的設備獲得 vip 後,則會通過start_haproxy.sh 腳本將 haproxy 啟動起來;
於是並不會因為服務器當機或mysql故障,影響我們客戶端對 111 的查詢操作,實驗完成一半了;
#但是測試時,在VIP地址切換過程中,客戶端會有那麼2-3秒不能訪問到數據庫,這個暫時忽略不計;
sed 's/^#//' /etc/passwd #測試完後,記得恢復mysql用戶哦;
#恢復mysql 後,啟動主設備的 mysqld keepalived ,然後使用 ip a 查看VIP 地址是否有返回來;
#在其中一台設備上 killall haproxy ,之後查看集群狀態;
http://192.168.5.111:8888/status
#查看後再將 haproxy 啟動
#至此,已經完成 負載均衡 + 高可用 兩部分,負載方式為輪詢
========================================================================
##三個腳本,很簡單,就不再介紹了哈;主要是做日志和結束服務;
#!/bin/bash #start_haproxy.sh sleep 5 get=`ip addr |grep 192.168.5.111 |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
#!/bin/bash #stop_haproxy.sh pid=`pidof haproxy` echo "`date +%c` stop haproxy" >> /opt/log/stop_haproxy.log kill -9 $pid
#!/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
=======================================================
[mysql Manager Slave] #mysql 主備配置;兩台設備上添加用戶哦; root#mysql create database db1; GRANT REPLICATION SLAVE ON *.* TO 'diaosi1'@'%' IDENTIFIED BY '123456'; #此處注意哦,Slave 權限必須的,我最初使用 all 權限,結果主備始終不同步,改成 Slave 就OK了; flush privileges; show grants for diaosi1@'%'; ================================================================== #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 ##指定需要同步的數據庫 #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 TO MASTER_HOST='192.168.5.12',master_port=3306,MASTER_USER='diaosi1',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: 192.168.5.11
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),phone char(14));
>insert into mywait(name,phone) values('wait',15888888888);
#新建一個具有 db1 權限的用戶
grant all on db1.* to diaosi2@'%' identified by '123456';
>flush privileges;
#切換到 test 庫,在mywait 表中插入一條數據;
use test;
insert into mywait(name,phone) values ('diaosi',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 -udiaosi2 -p123456 -h 192.168.5.111 -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 做判斷;
大家都可以多測試一下;
有些地方是需要在兩台服務器上同時配置的,大家看的時候多留意一下,測試過程中多看日志是最好的排錯方式;
#ip a | ip addr | ip address 效果是一樣的;