搭建mysql負載均衡及高可用環境

目標:使用兩臺主機實現 Mysql 的負載均衡及冗餘,並作到雙主互備;
環境:rhel5.8,mysql-5.0.77,keepalived-1.2.7,haproxy-1.4.20;
說明:
keepalived 實現經過 vrrp協議,經過使一個虛擬IP地址(或稱浮動IP)在主備設備間的切換來達到主機冗餘;
而客戶機經過訪問這個虛擬IP 來獲取服務;
haproxy 是一款負載均衡軟件,用於將請求按策略轉發給不一樣主機,達到負載均衡的效果;
能夠實現網絡層或應用層上的判斷分配;

mysql 開啓二進制日誌,作到數據庫之間的雙向複製,保持數據一致性; 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/ #此實驗日誌文件夾
================================================= linux

[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
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 的數據庫的數據;

一、嘗試將 MASTER 的keepalived 停掉
二、down 掉 MASTER 的網卡
三、讓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

======================================================= redis

[mysql Manager Slave] sql

#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 shell

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 效果是同樣的;


這篇博客是我第一次寫,有些粗糙,可能有些地方註釋得還有錯誤,歡迎留言;
這社區裏還有不少比較好的相似文章,你們能夠參考着學習,這樣效率更好,謝謝;
======================================================= 數據庫

相關文章
相關標籤/搜索