天天看點

Keepalived+HA

關于MySQL-HA,目前有多種解決方案,比如heartbeat、drbd、mmm、共享存儲,但是它們各有優缺點。heartbeat、drbd配置較為複雜,需要自己寫腳本才能實作MySQL自動切換,對于不會腳本語言的人來說,這無疑是一種腦裂問題;對于mmm,生産環境中很少有人用,且mmm

關于MySQL-HA,目前有多種解決方案,比如heartbeat、drbd、mmm、共享存儲,但是它們各有優缺點。heartbeat、drbd配置較為複雜,需要自己寫腳本才能實作MySQL自動切換,對于不會腳本語言的人來說,這無疑是一種腦裂問題;對于mmm,生産環境中很少有人用,且mmm 管理端需要單獨運作一台伺服器上,要是想實作高可用,就得對mmm管理端做HA,這樣無疑又增加了硬體開支;對于共享存儲,個人覺得MySQL資料還是放在本地較為安全,儲存設備畢竟存在單點隐患。使用MySQL雙master+keepalived是一種非常好的解決方案,在MySQL-HA環境中,MySQL互為主從關系,這樣就保證了兩台MySQL資料的一緻性,然後用keepalived實作虛拟IP,通過keepalived自帶的服務監控功能來實作MySQL故障時自動切換。

  下面,我把即将上線的一個生産環境中的架構與大家分享一下,看一下這個架構中,MySQL-HA是如何實作的,環境拓撲如下

  1. MySQL-VIP:192.168.1.200    
  2. MySQL-master1:192.168.1.201    
  3. MySQL-master2:192.168.1.202    
  4. OS版本:CentOS 5.4    
  5. MySQL版本:5.0.89    
  6. Keepalived版本:1.1.20  

  一、MySQL master-master配置

  1、修改MySQL配置檔案

  兩台MySQL均如要開啟binlog日志功能,開啟方法:在MySQL配置檔案[MySQLd]段中加上log-bin=MySQL-bin選項

  兩台MySQL的server-ID不能一樣,預設情況下兩台MySQL的serverID都是1,需将其中一台修改為2即可

  2、将192.168.1.201設為192.168.1.202的主伺服器

  在192.168.1.201上建立授權使用者

  1. MySQL> grant replication slave on *.* to 'replication'@'%' identified by 'replication';    
  2. Query OK, 0 rows affected (0.00 sec)    
  3. MySQL> show master status;    
  4. +------------------+----------+--------------+------------------+    
  5. | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |    
  6. +------------------+----------+--------------+------------------+    
  7. | MySQL-bin.000003 |      374 |              |                  |     
  8. +------------------+----------+--------------+------------------+    
  9. 1 row in set (0.00 sec)  

  在192.168.1.202上将192.168.1.201設為自己的主伺服器

  1. MySQL> change master to master_host='192.168.1.201',master_user='replication',master_password='replication',master_log_file='MySQL-bin.000003',master_log_pos=374;    
  2. Query OK, 0 rows affected (0.05 sec)    
  3. MySQL> start slave;    
  4. Query OK, 0 rows affected (0.00 sec)    
  5. MySQL> show slave status/G    
  6. *************************** 1. row ***************************    
  7.              Slave_IO_State: Waiting for master to send event    
  8.                 Master_Host: 192.168.1.201    
  9.                 Master_User: replication    
  10.                 Master_Port: 3306    
  11.               Connect_Retry: 60    
  12.             Master_Log_File: MySQL-bin.000003    
  13.         Read_Master_Log_Pos: 374    
  14.              Relay_Log_File: MySQL-master2-relay-bin.000002    
  15.               Relay_Log_Pos: 235    
  16.       Relay_Master_Log_File: MySQL-bin.000003    
  17.            Slave_IO_Running: Yes    
  18.           Slave_SQL_Running: Yes    
  19.             Replicate_Do_DB:     
  20.         Replicate_Ignore_DB:     
  21.          Replicate_Do_Table:     
  22.      Replicate_Ignore_Table:     
  23.     Replicate_Wild_Do_Table:     
  24. Replicate_Wild_Ignore_Table:     
  25.                  Last_Errno: 0    
  26.                  Last_Error:     
  27.                Skip_Counter: 0    
  28.         Exec_Master_Log_Pos: 374    
  29.             Relay_Log_Space: 235    
  30.             Until_Condition: None    
  31.              Until_Log_File:     
  32.               Until_Log_Pos: 0    
  33.          Master_SSL_Allowed: No    
  34.          Master_SSL_CA_File:     
  35.          Master_SSL_CA_Path:     
  36.             Master_SSL_Cert:     
  37.           Master_SSL_Cipher:     
  38.              Master_SSL_Key:     
  39.       Seconds_Behind_Master: 0    
  40. 1 row in set (0.00 sec)  

  3、将192.168.1.202設為192.168.1.201的主伺服器

  在192.168.1.202上建立授權使用者

  1. MySQL> grant replication slave on *.* to 'replication'@'%' identified by 'replication';    
  2. Query OK, 0 rows affected (0.00 sec)    
  3. MySQL> show master status;    
  4. +------------------+----------+--------------+------------------+    
  5. | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |    
  6. +------------------+----------+--------------+------------------+    
  7. | MySQL-bin.000003 |      374 |              |                  |     
  8. +------------------+----------+--------------+------------------+    
  9. 1 row in set (0.00 sec)  

  在192.168.1.201上,将192.168.1.202設為自己的主伺服器

  1. MySQL> change master to master_host='192.168.1.202',master_user='replication',master_password='replication',master_log_file='MySQL-bin.000003',master_log_pos=374;    
  2. Query OK, 0 rows affected (0.05 sec)    
  3. MySQL> start slave;    
  4. Query OK, 0 rows affected (0.00 sec)    
  5. MySQL> show slave status/G    
  6. *************************** 1. row ***************************    
  7.              Slave_IO_State: Waiting for master to send event    
  8.                 Master_Host: 192.168.1.202    
  9.                 Master_User: replication    
  10.                 Master_Port: 3306    
  11.               Connect_Retry: 60    
  12.             Master_Log_File: MySQL-bin.000003    
  13.         Read_Master_Log_Pos: 374    
  14.              Relay_Log_File: MySQL-master1-relay-bin.000002    
  15.               Relay_Log_Pos: 235    
  16.       Relay_Master_Log_File: MySQL-bin.000003    
  17.            Slave_IO_Running: Yes    
  18.           Slave_SQL_Running: Yes    
  19.             Replicate_Do_DB:     
  20.         Replicate_Ignore_DB:     
  21.          Replicate_Do_Table:     
  22.      Replicate_Ignore_Table:     
  23.     Replicate_Wild_Do_Table:     
  24. Replicate_Wild_Ignore_Table:     
  25.                  Last_Errno: 0    
  26.                  Last_Error:     
  27.                Skip_Counter: 0    
  28.         Exec_Master_Log_Pos: 374    
  29.             Relay_Log_Space: 235    
  30.             Until_Condition: None    
  31.              Until_Log_File:     
  32.               Until_Log_Pos: 0    
  33.          Master_SSL_Allowed: No   
  34.          Master_SSL_CA_File:     
  35.          Master_SSL_CA_Path:     
  36.             Master_SSL_Cert:     
  37.           Master_SSL_Cipher:     
  38.              Master_SSL_Key:     
  39.       Seconds_Behind_Master: 0    
  40. 1 row in set (0.00 sec)  

  4、MySQL同步測試

  如上述均正确配置,現在任何一台MySQL上更新資料都會同步到另一台MySQL,MySQL同步在此不再示範

二、keepalived安裝及配置

  1、192.168.1.201伺服器上keepalived安裝及配置

  安裝keepalived

  1. #tar zxvf keepalived-1.1.20.tar.gz    
  2. #cd keepalived-1.1.20    
  3. #./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/kernels/2.6.18-164.el5-i686    
  4. #make && make install  

  配置keepalived

  我們自己在建立一個配置檔案,預設情況下keepalived啟動時會去/etc/keepalived目錄下找配置檔案

  1. #mkdir /etc/keepalived    
  2. #vi /etc/keepalived/keepalived.conf    
  3. ! Configuration File for keepalived    
  4. global_defs {    
  5.      notification_email {    
  6.      [email protected]    
  7.      }    
  8.      notification_email_from [email protected]    
  9.      smtp_server 127.0.0.1    
  10.      smtp_connect_timeout 30    
  11.      router_id MySQL-ha    
  12.      }    
  13. vrrp_instance VI_1 {    
  14.      state BACKUP   #兩台配置此處均是BACKUP    
  15.      interface eth0    
  16.      virtual_router_id 51    
  17.      priority 100   #優先級,另一台改為90    
  18.      advert_int 1    
  19.      nopreempt  #不搶占,隻在優先級高的機器上設定即可,優先級低的機器不設定    
  20.      authentication {    
  21.      auth_type PASS    
  22.      auth_pass 1111    
  23.      }    
  24.      virtual_ipaddress {    
  25.      192.168.1.200    
  26.      }    
  27.      }    
  28. virtual_server 192.168.1.200 3306 {    
  29.      delay_loop 2   #每個2秒檢查一次real_server狀态    
  30.      lb_algo wrr   #LVS算法    
  31.      lb_kind DR    #LVS模式    
  32.      persistence_timeout 60   #會話保持時間    
  33.      protocol TCP    
  34.      real_server 192.168.1.201 3306 {    
  35.      weight 3    
  36.      notify_down /usr/local/MySQL/bin/MySQL.sh  #檢測到服務down後執行的腳本    
  37.      TCP_CHECK {    
  38.      connect_timeout 10    #連接配接逾時時間    
  39.      nb_get_retry 3       #重連次數    
  40.      delay_before_retry 3   #重連間隔時間    
  41.      connect_port 3306   #健康檢查端口    
  42.      }    
  43.      }  

  編寫檢測服務down後所要執行的腳本

  1. #vi /usr/local/MySQL/bin/MySQL.sh    
  2. #!/bin/sh    
  3. pkill keepalived    
  4. #chmod +x /usr/local/MySQL/bin/MySQL.sh  

  注:此腳本是上面配置檔案notify_down選項所用到的,keepalived使用notify_down選項來檢查real_server的服務狀态,當發現real_server服務故障時,便觸發此腳本;我們可以看到,腳本就一個指令,通過pkill keepalived強制殺死keepalived程序,進而實作了MySQL故障自動轉移。另外,我們不用擔心兩個MySQL會同時提供資料更新操作,因為每台MySQL上的keepalived的配置裡面隻有本機MySQL的IP+VIP,而不是兩台MySQL的IP+VIP

  啟動keepalived

  1. #/usr/local/keepalived/sbin/keepalived –D    
  2. #ps -aux | grep keepalived  

  測試

  找一台區域網路PC,然後去ping MySQL的VIP,這時候MySQL的VIP是可以ping的通的

  停止MySQL服務,看keepalived健康檢查程式是否會觸發我們編寫的腳本

  2、192.168.1.202上keepalived安裝及配置

  安裝keepalived

  1. #tar zxvf keepalived-1.1.20.tar.gz    
  2. #cd keepalived-1.1.20    
  3. #./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/kernels/2.6.18-164.el5-i686    
  4. #make && make install  

  配置keepalived

  這台配置和上面基本一樣,但有三個地方不同:優先級為90、無搶占設定、real_server為本機IP

  1. #mkdir /etc/keepalived    
  2. #vi /etc/keepalived/keepalived.conf    
  3. ! Configuration File for keepalived    
  4. global_defs {    
  5.      notification_email {    
  6.      [email protected]    
  7.      }    
  8.      notification_email_from [email protected]    
  9.      smtp_server 127.0.0.1    
  10.      smtp_connect_timeout 30    
  11.      router_id MySQL-ha    
  12.      }    
  13. vrrp_instance VI_1 {    
  14.      state BACKUP    
  15.      interface eth0    
  16.      virtual_router_id 51    
  17.      priority 90    
  18.      advert_int 1    
  19.      authentication {    
  20.      auth_type PASS    
  21.      auth_pass 1111    
  22.      }    
  23.      virtual_ipaddress {    
  24.      192.168.1.200    
  25.      }    
  26.      }    
  27. virtual_server 192.168.1.200 3306 {    
  28.      delay_loop 2    
  29.      lb_algo wrr    
  30.      lb_kind DR    
  31.      persistence_timeout 60    
  32.      protocol TCP    
  33.      real_server 192.168.1.202 3306 {    
  34.      weight 3    
  35.      notify_down /usr/local/MySQL/bin/MySQL.sh    
  36.      TCP_CHECK {    
  37.      connect_timeout 10    
  38.      nb_get_retry 3    
  39.      delay_before_retry 3    
  40.      connect_port 3306    
  41.      }    
  42.      }   

  編寫檢測服務down後所要執行的腳本

  1. #vi /usr/local/MySQL/bin/MySQL.sh    
  2. #!/bin/sh    
  3. pkill keepalived    
  4. #chmod +x /usr/local/MySQL/bin/MySQL.sh    
  5. 啟動keepalived    
  6. #/usr/local/keepalived/sbin/keepalived –D    
  7. #ps -aux | grep keepalived 

  測試

  ●停止MySQL服務,看keepalived健康檢查程式是否會觸發我們編寫的腳本

  三、測試

  ● MySQL遠端登入測試

  我們找一台安裝有MySQL用戶端的windows,然後登入VIP,看是否能登入,在登入之兩台MySQL伺服器都要授權允許從遠端登入

  1. MySQL> grant all privileges on *.* to 'root'@'%' identified by '123456';    
  2. Query OK, 0 rows affected (0.00 sec)    
  3. MySQL> flush privileges;    
  4. Query OK, 0 rows affected (0.00 sec)   

  使用用戶端登入VIP測試

  1. C:/MySQL/bin>MySQL.exe -uroot -p123456 -h192.168.1.200 -P3306    
  2. Welcome to the MySQL monitor.  Commands end with ; or /g.    
  3. Your MySQL connection id is 224    
  4. Server version: 5.0.89-log Source distribution    
  5. Type 'help;' or '/h' for help. Type '/c' to clear the current input statement.    
  6. MySQL>   

  ● keepalived故障轉移測試

  ※在windows用戶端一直去ping VIP,然後關閉192.168.1.201上的keepalived,正常情況下VIP就會切換到192.168.1.202上面去

  ※開啟192.168.1.201上的keepalived,關閉192.168.1.202上的keepalived,看是否能自動切換,正常情況下VIP又會屬于192.168.1.201

  注:keepalived切換速度還是非常塊的,整個切換過程隻需1-3秒

  ● MySQL故障轉移測試

  ※在192.168.1.201上關閉MySQL服務,看VIP是否會切換到192.168.1.202上

  ※開啟192.168.1.201上的MySQL和keepalived,然後關閉192.168.1.202上的MySQL,看VIP是否會切換到192.168.1.201上

  下面是用windows用戶端連接配接的MySQL的VIP,在切換時我執行了一個MySQL查詢指令,從執行show databases到顯示出結果時間為3-5秒(大家可以看到上面有個錯誤提示,不過不用擔心,因為我們的keepalived切換大概為3秒左右,這3秒左右VIP是誰都不屬于的)

  1. MySQL> show databases;    
  2. ERROR 2006 (HY000): MySQL server has gone away    
  3. No connection. Trying to reconnect...    
  4. Connection id:    592    
  5. Current database: *** NONE ***    
  6. +--------------------+    
  7. | Database           |    
  8. +--------------------+    
  9. | information_schema |    
  10. | MySQL              |    
  11. | test               |    
  12. +--------------------+    
  13. 3 rows in set (9.01 sec)   

  後話:世間萬事萬物,都不具備絕對的完美,就像上面的MySQL-HA一樣,keepalived隻能做到對3306的健康檢查,但是做不到比如像MySQL複制中的slave-SQL、slave-IO程序的檢查。是以要想做到一些細緻的健康檢查,還得需要借助額外的監控工具,比如nagios,然後用nagios實作短信、郵件報警,進而能夠有效地解決問題。