MySQL-HA Keepalived Master-Master半同步

最近在總結研究下之前項目涉及的高可用方案的東西,已經完成了WEB的HA,這裏開始準備總結下數據庫的,因此先以之前使用的MYSQL入手,MYSQL的高可用方案最流行的就是複製模式,主要有半同步和同步模式,性價比最高和應用最多的仍是半同步,本文總結和記錄下半同步的安裝和配置。html

二、方案

本案例先使用兩臺linux作雙機MASTER-MASTER高可用(後續能夠考慮加入只讀SLAVER,用於提升查詢性能),採用MYSQL5.6.x的半同步實現數據複製和同步,使用keepalived來監控MYSQL和提供VIP及浮動。前端

2.一、環境及軟件

操做系統:RedHat 6.3 mysql

Keepalived:keepalived-1.2.2.tar.gz linux

MYSQL:MySQL-server-5.6.10-1.el6.x86_64.rpm    MySQL-client-5.6.10-1.el6.x86_64.rpmsql

2.二、IP規劃

名稱 IP 備註
VIP 10.10.10.20 由KEEPALIVED產生的虛擬IP,也是前端客戶端使用的IP
MYSQL_DB_MASTER1 10.10.10.21 數據庫1服務器(默認主)
MYSQL_DB_MASTER2 10.10.10.22 數據庫2服務器

三、安裝設置MYSQL半同步

3.一、安裝MYSQL數據庫

這裏選擇的是使用社區版的MYSQL,請在www.mysql.com上下載對應操做系統的安裝文件,這裏根據官方的建議使用RPM包方式安裝。vim

安裝bash

若是是默認Redhat6.3安裝後,可能會有mysql-libs的衝突,請先卸載原有的mysql-libs相關包。服務器

# yum -y remove mysql-libs*網絡

# rpm -ivh MySQL-server-5.6.10-1.el6.x86_64.rpm

……

# rpm -ivh MySQL-client-5.6.10-1.el6.x86_64.rpm

……

默認安裝是在/usr下面,因此my.cnf是在/usr/my.cnf,這裏爲了習慣用法,拷貝到/etc/目錄下

# mv /usr/my.cnf /etc/

 

設置root用戶初始密碼

默認安裝完成後,mysql的root初始密碼保存在: ~/.mysql_secret

# cat ~/.mysql_secret

# The random password set for the root user at Tue Dec 17 19:31:29 2013 (local time): uQ8X91Ys

 

標準方式修改密碼

# mysqladmin -u root -p oldPassword password

# New password: 

# Confirm new password: 

# mysqladmin -u root -p password newPassword

 

SQL直接更新方式修改密碼

初始化root密碼常見問題及處理

error: 'Access denied for user 'root'@'localhost' (using password: NO)'

# /etc/init.d/mysql stop 

# mysqld_safe --user=mysql --skip-grant-tables --skip-networking & 

# mysql -u root mysql 

mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root'; 

mysql> FLUSH PRIVILEGES; 

mysql> quit 

# /etc/init.d/mysql restart 

# mysql -uroot -p 

Enter password: <輸入新設的密碼newpassword> 

mysql> 

 

設置網絡訪問權限

 MYSQL的用戶訪問策略是須要指定用戶從某IP能夠訪問那些權限。具體用法請參考grant命令。這裏爲了簡單起見,直接設置root用戶在整個局域內(10.10.10.*)均可以訪問數據庫。

 

# mysql -uroot -p

******

mysql> GRANT ALL PRIVILEGES ON *.* TO root@'10.10.10.%' IDENTIFIED BY 'password' WITH GRANT OPTION;

mysql>FLUSH PRIVILEGES;

 

這樣設置後,就能夠經過內網的其餘機器訪問數據庫了。

 

修改數據文件路徑

mysql安裝後,默認的數據存儲路徑在/var/lib/mysql下。這裏修改成/data/mysql

# service mysql stop

# mkdir /data/mysql

# cp -r /var/lib/mysql/* /data/mysql

# chown -R mysql:mysql /data/mysql

vi /etc/my.cnf

[mysqld]
datadir = /data/mysql
socket = /data/mysql/mysql.sock
# 順便配置下MYSQL使用mysql用戶啓動
user=mysql

 保存退出

 爲/data/mysql/mysql.sock創建指向/var/lib/mysql/mysql.sock的軟鏈接

# ln -s /data/mysql/mysql.sock /var/lib/mysql/mysql.sock

啓動MYSQL並測試

# service mysql start

# mysql -uroot -p

******

mysql>

最可能出現的問題(若是你是Redhat6.x或CentOS6.x):selinux 照成服務沒法正常啓動,報錯:

Starting MySQL. ERROR! The server quit without updating PID file (/data/mysql/xxxxx.pid).

驗證問題方法:

# setenforce 0

# service mysql start

Starting MySQL. SUCCESS! 

若是能正常啓動,解決問題,就肯定是selinux形成的問題了。

解決辦法1:直接禁用

vim /etc/selinux/config

修改:SELINUX=disabled

保存後,重啓操做系統生效

解決方案2:配置selinux支持mysql訪問相關端口和文件系統

本人比較懶,給個鏈接本身研究哈(或者google: selinux mysql):

https://blogs.oracle.com/jsmyth/entry/selinux_and_mysql

若是出現問題,通常解決問題的方式是查看MYSQL的日誌文件,通常提示會比較清楚,或者根據錯誤信息區GOOGLE均可以找到答案。日誌文件: ${datadir}/${hostname}.err, 本例中修改了數據目錄,因此日誌文件是:/data/mysql/acooly1.err

OK,本節安裝MYSQL完成,而後另一臺服務器的MYSQL安裝徹底相同(半同步的設置有小不一樣,那下面會說明)。請參照以上說明安裝另一臺MYSQL服務(MYSQL_DB_MASTER2)。

3.二、設置MYSQL雙向半同步

半同步複製及semi-sync replication,最開始是GOOGLE提出和實現,後來MYSQL在5.5後的版本中支持的複製功能。只要是經過相似「兩階段提交」的方式實現,只要有一臺備機成功同步數據,主服務器的事務就提交,不然等待10秒後,轉爲傳統的異步複製。

本方案中爲了實現故障轉移功能,在利用半同步複製能力的同時,對總體方案進行了調整以下:

  1. MYSQL_DB_MASTER1和MYSQL_DB_MASTER2互爲主備,即MYSQL_DB_MASTER1時MYSQL_DB_MASTER2的主,MYSQL_DB_MASTER2是MYSQL_DB_MASTER1的主,經過半同步實現雙向的同步複製(注意:這裏不會出現衝突,由於備機只會同步不是本機server_id的bin-log日誌,經過兩臺機器的server_id隔離須要同步的bin-log)
  2. 經過Keepalived實現MYSQL服務器的監控和VIP的浮動,保證同一時間只有一臺MYSQL服務器可用。
  3. 該方案中,能夠兼容後期的擴容,加入多臺SALVE與兩臺MASTER異步同步實現數據的只讀查詢,實現讀寫分離,提升總體性能。

配置/etc/my.cnf

分別修改/etc/my.cnf配置,打開bin-log功能和設置server_id

vi /etc/my.cnf

[mysqld]
# MYSQL_DB_MASTER1設置爲1,MYSQL_DB_MASTER2設置爲2
server_id=1
log_bin=mysql-bin

 安裝官方文檔說明,主(MYSQL_DB_MASTER1)須要設置rpl_semi_sync_master_enabled=1和rpl_semi_sync_master_timeout=1000,備(MYSQL_DB_MASTER2)須要設置rpl_semi_sync_slave_enabled=1,這裏由於是雙向同步,我都沒有設置,經測試,沒有設置也沒有關係(暫時沒有深究,後續在研究下)。

配置MYSQL_DB_MASTER1與MYSQL_DB_MASTER2的主備同步

在MYSQL_DB_MASTER1上操做配置MYSQL_DB_MASTER1爲MYSQL_DB_MASTER2的主。

# mysql -uroot -p Enter password: ...... -- 創建複製用戶replication,容許內網內其餘機器(訪問本機全部數據庫) mysql > grant replication slave on *.* to 'replication'@'10.10.10.%' identified by 'replication'; Query OK, 0 rows affected (0.00 sec) -- 查看master的bin-log狀態,用戶設置SLAVE同步的起點 mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000013 | 120 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.02 sec)

 這裏注意記錄下當前bin-log文件名稱:mysql-bin.000013和位置:120,備機設置的時候須要用到。

 在MYSQL_DB_MASTER2上操做配置

--設置SLAVE的MASTER和開始同步的文件位置 mysql> change master to master_host='10.10.10.21',master_user='replication',master_password='replication',master_log_file='mysql-bin.000003',master_log_pos=120; --啓動同步 mysql> start slave; mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.10.10.21 Master_User: replication Master_Port: 3306 Connect_Retry: 10 Master_Log_File: mysql-bin.000013 Read_Master_Log_Pos: 120 Relay_Log_File: acooly2-relay-bin.000020 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql-bin.000013 Slave_IO_Running: Yes Slave_SQL_Running: Yes …… 1 row in set (0.02 sec)

Slave_IO_Running: Yes和Slave_SQL_Running: Yes表示SLAVE已經正常啓動並監聽MASTER的數據發送事件,處理同步。

 配置MYSQL_DB_MASTER2與MYSQL_DB_MASTER1的主備同步

 全部配置操做與上一節,只是把主備關係交換。

OK

若是全部的配置成功,啓動MASTER1和MASTER2兩個數據庫,分別從兩端建立數據庫,表和更新表數據,另一邊都會實時同步。

四、Keepalived實現MYSQL的高可用

 前面已經完成MYSQL的雙向實時同步的配置,本節使用Keepalived實現MYSQL雙機的高可用,故障轉移。經過VIP實現同時只有一臺MYSQL提供服務。

4.一、配置KEEPALIVED

兩臺MYSQL服務器上的配置基本相同(除了keepalived.conf的個別配置外),具體操做配置以下:

安裝Keepalived請參考:Keepalived + LVS(DR) 高可用負載均衡集羣 的 3.三、Keepalived 安裝配置

設置keepalived的主配置文件/etc/keepalived/keepalived.conf實現本機的MYSQL的監控和VIP浮動。

 

global_defs {
        router_id Mysql-HA
}

# 定義MYSQL監控的腳本,每2秒監控一次,具體腳本請見下面
vrrp_script check_mysql {
  script "/opt/keepalived/keepalived_check_mysql.sh"
  interval 2
}

vrrp_sync_group VG1 {
        group {
                KEEPALIVED_MYSQL
        }
}

vrrp_instance KEEPALIVED_MYSQL {
        # 注意:兩臺MYSQL服務器都設置爲BACKUP
        state BACKUP
        interface eth0
        virtual_router_id 20
        # MASTER1設置爲100,則MASTER2設置爲稍低,如:90
        priority 100
        advert_int 1
        # 只有MASTER1設置不搶奪控制權
        nopreempt
        authentication {
                auth_type PASS
                auth_pass 111111
        }
        track_script {
          check_mysql
        }
        virtual_ipaddress {
                10.10.10.20
        }
}

 

 檢查本機MYSQL服務是否正常,若是MYSQL服務不可用,則中止KEEPALIVED服務,由備機的KEEPALIVED接管並提供VIP(指向備機)

#!/bin/bash

MYSQL=/usr/bin/mysql
MYSQL_HOST=localhost
MYSQL_USER=root
MYSQL_PASSWORD=1qaz@WSX
# 日誌文件
LOG_FILE=/opt/keepalived/check_mysql.log
# 檢查次數
CHECK_TIME=3

#mysql is working MYSQL_OK is 1 , mysql down MYSQL_OK is 0
MYSQL_OK=1


function check_mysql_helth (){
  $MYSQL -h $MYSQL_HOST -u $MYSQL_USER -p${MYSQL_PASSWORD} -e "show status;" >/dev/null 2>&1
  if [ $? = 0 ] ;then
    MYSQL_OK=1
  else
    MYSQL_OK=0
  fi
  return $MYSQL_OK
}

while [ $CHECK_TIME -ne 0 ]
do
  let "CHECK_TIME -= 1"
  check_mysql_helth
  if [ $MYSQL_OK = 1 ] ; then
    CHECK_TIME=0
    #echo `date --date=today +"%Y-%M-%d %H:%m:%S"` -  [INFO] - mysql available: success[$MYSQL_OK] >> $LOG_FILE
    exit 0
  fi
  if [ $MYSQL_OK -eq 0 ] && [ $CHECK_TIME -eq 0 ]
  then
    /etc/init.d/keepalived stop
    echo `date --date=today +"%Y-%M-%d %H:%m:%S"` -  [INFO] - mysql invaild. keepalived stop. >> $LOG_FILE
    exit 1
  fi
  sleep 1
done

 

4.二、驗證故障轉移

配置完成後,分別啓動兩臺服務器的mysql和keepalived服務

分別啓動MYSQL_DB_MASTER1和MYSQL_DB_MASTER2

# service mysql start

Starting MySQL.......... SUCCESS!

# service keepalived start

Starting keepalived:                                       [  OK  ]

 

在MYSQL_DB_MASTER1查看VIP

# ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 

……

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

    link/ether 00:50:56:3b:be:91 brd ff:ff:ff:ff:ff:ff

    inet 10.10.10.21/24 brd 10.10.10.255 scope global eth0

    inet 10.10.10.20/32 scope global eth0

    inet6 fe80::250:56ff:fe3b:be91/64 scope link 

       valid_lft forever preferred_lft forever

中止MYSQL_DB_MASTER1的MYSQL服務,查看VIP

# service mysql stop

Shutting down MySQL..... SUCCESS! 

# service keepalived status

keepalived is stopped

# ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 

……

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

    link/ether 00:0c:29:37:87:e4 brd ff:ff:ff:ff:ff:ff

    inet 10.10.10.21/24 brd 10.10.10.255 scope global eth0

    inet6 fe80::20c:29ff:fe37:87e4/64 scope link 

       valid_lft forever preferred_lft forever

 沒有VIP(10.10.10.20)了

 

 在MYSQL_DB_MASTER2上查看VIP

# ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 

……

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000

    link/ether 00:50:56:3b:be:91 brd ff:ff:ff:ff:ff:ff

    inet 10.10.10.22/24 brd 10.10.10.255 scope global eth0

    inet 10.10.10.20/32 scope global eth0

    inet6 fe80::250:56ff:fe3b:be91/64 scope link 

       valid_lft forever preferred_lft forever

 能夠看到VIP已經切換到MYSQL_DB_MASTER2

 

重新啓動MYSQL_DB_MASTER1的MYSQL服務和KEEPALIVED服務,可是這個時候是不會重新浮動到MASTER1的,由於咱們配置KEEPALIVED的時候都是配置的BACKUP,並且MASTER1配置了不搶佔。這餘咱們設計是相符的。(只有等MASTER2出現故障的狀況才重新有MASTER1接管)

 

OK,本次記錄到此,後續完善加入多個異步同步的SLAVE。

 

五、參考資料

http://dev.mysql.com/doc/

http://bbs.chinaunix.net/thread-1824528-1-1.html

http://blog.csdn.net/haier_jiang/article/details/8449013

http://www.9ai9.net/?p=131

相關文章
相關標籤/搜索