1. 程式人生 > >mysql-故障轉移+負載均衡群集

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 做判斷;

大家都可以多測試一下;

有些地方是需要在兩臺伺服器上同時配置的,大家看的時候多留意一下,測試過程中多看日誌是最好的排錯方式;