MySQL的高可用方案有不少種,雙主、MHA、MMM等等,這裏只是寫下最簡單的雙主這種高可用方案。html
系統 | IP | 主機名 | 服務 |
---|---|---|---|
Centos 7.5 | 192.168.20.2 | mysql01 | MySQL+keepalived |
Centos 7.5 | 192.168.20.3 | mysql02 | MySQL+keepalived |
注:MySQL已部署完成,可參考博文Centos部署MySQL 5.7進行部署。mysql
#主機mysql01配置文件以下: [root@mysql01 ~]# cat /etc/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data port=3306 server_id=1 #server_id必須惟一 socket=/usr/local/mysql/mysql.sock log-error=/usr/local/mysql/data/mysqld.err binlog_format = mixed #指定二進制格式 log-bin=/usr/local/mysql/data/log_bin #指定二進制日誌文件 relay-log=/usr/local/mysql/data/relay-bin #指定中繼日誌 relay-log-index=relay-bin.index auto_increment_increment=2 auto_increment_offset=1 #主機mysql02配置文件以下: [root@mysql02 ~]# cat /etc/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data port=3306 server_id=2 socket=/usr/local/mysql/mysql.sock log-error=/usr/local/mysql/data/mysqld.err binlog_format = mixed log-bin=/usr/local/mysql/data/log_bin relay-log=/usr/local/mysql/data/relay-bin relay-log-index=relay-bin.index auto_increment_increment=2 auto_increment_offset=2
注:mysql01和mysql02只有server-id和auto_increment_offset不一樣算法
mysql中有自增加字段,在作數據庫的主主同步時須要設置自增加的兩個相關配置:auto_increment_offset和auto_increment_increment。 auto-increment-increment表示自增加字段每次遞增的量,其默認值是1。它的值應設爲整個結構中服務器的總數,我這裏用到兩臺服務器,因此值設爲2。 auto-increment-offset是用來設定數據庫中自動增加的起點(即初始值),由於這兩能服務器都設定了一次自動增加值2,因此它們的起點必須得不一樣,這樣才能避免兩臺服務器數據同步時出現主鍵衝突。sql
關於「binlog_format = mixed」配置項,是用來定義二進制日誌的格式的,有如下三個值可選,以下:數據庫
- STATEMENT:基於sql語句來記錄二進制日誌,好比有些sql語句可能會影響上百條數據的改動,那麼也只是記錄一條sql語句。優勢:能夠減小二進制日誌的大小,減小日誌寫入的I/O量。缺點:須要進行數據恢復時,某些自定義的存儲過程或函數可能會失效,數據可能沒法恢復。
- ROW:基於行來記錄二進制日誌,若是某一條SQL語句影響了多行數據,那麼將會記錄多條二進制日誌,優勢:能夠經過二進制日誌來精準的恢復數據。缺點:當發生變化的數據量較大時,會給磁盤I/O帶來必定的壓力。
- mixed:基於混合模式來記錄二進制日誌。MySQL自行判斷是基於行仍是基於sql語句來記錄日誌,建議採用這種格式,若是基於sql語句來記錄就能夠精準記錄數據的變化,那麼就會基於sql語句,若是sql語句中包含存儲過程或環境變量等,那麼就會基於行來記錄。
關於二進制日誌的更多介紹,能夠參考MySQL的官方文檔。vim
注:能夠在my.cnf文件中添加「binlog_do_db=數據庫名」配置項(能夠添加多個)來指定要同步的數據庫後端
[root@mysql01 ~]# firewall-cmd --add-port=3306/tcp --permanent [root@mysql01 ~]# firewall-cmd --reload
[root@mysql01 ~]# mysql -uroot -p123.com mysql> grant replication slave on *.* to rep@'192.168.20.%' identified by '123.com';
mysql> show master status\G *************************** 1. row *************************** File: log_bin.000001 #這個值會用到 Position: 609 #這個值會用到 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 1 row in set (0.00 sec)
#指定master地址 mysql> change master to master_host='192.168.20.2', -> master_user='rep', -> master_password='123.com', -> master_log_file='log_bin.000001', #必須和master上查看到的名字同樣 -> master_log_pos=609; #同上,這個值也是在master上查看到的 #啓動slave功能 mysql> start slave; #肯定配置成功 mysql> show slave status\G #查看slave狀態 *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.20.2 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: log_bin.000001 Read_Master_Log_Pos: 609 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 318 Relay_Master_Log_File: log_bin.000001 Slave_IO_Running: Yes # 這個值必須爲Yes Slave_SQL_Running: Yes # 這個值也必須爲Yes #只要上面兩個值爲yes,則表示主從沒有問題, #其中,IO線程是去master上面讀取二進制日誌到本地的中繼日誌中; SQL線程是將本地的中繼日誌中的內容轉換爲sql語句並執行。
#主機mysql02上操做以下: mysql> grant replication slave on *.* to rep@'192.168.20.%' identified by '123.com'; mysql> flush privileges; mysql> show master status\G #獲取所需的file和Position *************************** 1. row *************************** File: log_bin.000002 Position: 609 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 1 row in set (0.00 sec) #主機mysql01上操做以下: #指定mysql02爲master mysql> change master to master_host='192.168.20.3', -> master_user='rep', -> master_password='123.com', -> master_log_file='log_bin.000002', -> master_log_pos=609; mysql> start slave; #啓動slave mysql> show slave status\G #查看slave狀態 *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.20.3 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: log_bin.000002 Read_Master_Log_Pos: 609 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 318 Relay_Master_Log_File: log_bin.000002 #確保下面兩個值爲yes Slave_IO_Running: Yes Slave_SQL_Running: Yes
mysql> create database test; mysql> use test mysql> create table t1(id int,name varchar(4)); mysql> insert into t1 values(1,'a'),(2,'b'); #確認mysql01的數據 mysql> select * from t1; +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | +------+------+ 2 rows in set (0.00 sec)
#如下操做在主機mysql02上進行 mysql> select * from t1; #肯定數據已同步 +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | +------+------+ #插入數據測試 mysql> insert into t1 values(3,'c'),(4,'d'); mysql> select * from t1; #肯定最新數據 +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | +------+------+
#在mysql01上查詢,是否同步mysql02主機上的數據 mysql> select * from t1; +------+------+ | id | name | +------+------+ | 1 | a | | 2 | b | | 3 | c | | 4 | d | +------+------+ 4 rows in set (0.00 sec)
至此,如今任何一臺MySQL上更新數據都會同步到另外一臺MySQL,MySQL同步完成。bash
注:若主MySQL服務器已經存在,只是後期業務拓展才搭建從服務器,在配置數據庫同步前應先將MySQL服務器的要同步的數據庫拷貝到從服務器上(如先在主MySQL上備份數據庫,再用備份再從MySQL服務器上恢復)。服務器
兩個節點都須要執行如下命令,以便安裝keepalived。負載均衡
[root@mysql01 ~]# yum -y install keepalived
注:兩臺主機都須要執行如下命令,以便放行相關流量。224.0.0.18是keepalived的組播地址,使用的是vrrp協議。
[root@mysql02 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --in-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT [root@mysql02 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT [root@mysql02 ~]# firewall-cmd --reload
[root@mysql01 ~]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id mysql-01 #此處的值必須惟一 } vrrp_instance VI_1 { state BACKUP #指定角色爲backup,兩臺MySQL服務器的角色均爲backup,設置backup將根據優先級決定主從 interface ens33 #指定承載虛擬IP的網卡 virtual_router_id 51 #指定組,同一個集羣內的值必須一致。而且不可和局域網中的其餘組衝突 priority 100 #優先級範圍爲:0~100 advert_int 1 #發vrrp包的時間間隔,即多久進行一次master選舉(可認爲是健康檢查時間間隔) nopreempt #不搶佔,即容許一個priority比較低的節點做爲master, authentication { #認證區域 auth_type PASS auth_pass 1111 } virtual_ipaddress { #VIP區域,指定vip地址 192.168.20.20 } } virtual_server 192.168.20.20 3306 { #設置虛擬服務器,須要指定虛擬IP地址和服務端口,IP與端口之間用空格隔開 delay_loop 2 #設置運行狀況檢查時間,單位是秒 lb_algo rr #設置後端調度算法 lb_kind DR #設置lvs實現負載均衡的機制,有NAT、TUN、DR三個模式,DR模式效率最高 persistence_timeout 60 #會話保持時間,單位是秒 protocol TCP #指定轉發協議類型,有TCP和UDP兩種 real_server 192.168.20.2 3306 { #配置服務節點,這裏指定的也就是本機的真實IP weight 1 #設置權重 notify_down /etc/keepalived/bin/mysql.sh #檢測到real_server的MySQL服務宕機後執行的腳本。 TCP_CHECK { connect_port 3306 #健康檢查端口 connect_timeout 3 #鏈接超時時間 retry 3 #重試次數 delay_before_retry 3 #重連間隔時間 } } } #準備指定的腳本 [root@mysql01 keepalived]# pwd /etc/keepalived [root@mysql01 keepalived]# mkdir bin [root@mysql01 keepalived]# vim bin/mysql.sh #!/bin/bash pkill keepalived #中止keepalived服務 [root@mysql01 keepalived]# chmod +x bin/mysql.sh #賦予腳本執行權限 [root@mysql01 ~]# systemctl start keepalived #啓動keepalived服務 #肯定ens33網卡有虛擬Ip [root@mysql01 ~]# ip a show ens33 #必須使用ip a命令才能夠查看到,ifconfig命令查看不到 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:c0:39:80 brd ff:ff:ff:ff:ff:ff inet 192.168.20.2/24 brd 192.168.20.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.20.20/32 scope global ens33 #能夠看到指定的VIP已經綁定到ens33上 valid_lft forever preferred_lft forever inet6 fe80::659e:9312:318a:e52b/64 scope link noprefixroute valid_lft forever preferred_lft forever #將keepalived的配置文件發送到mysql02主機上 [root@mysql01 ~]# scp /etc/keepalived/keepalived.conf root@192.168.20.3:/etc/keepalived/
#修改msyql01發送來的配置文件 [root@mysql02 keepalived]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id mysql-02 #更改router_id,此處在熱備組中必需要惟一 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 90 #更改優先級 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.20.20 } } virtual_server 192.168.20.20 3306 { delay_loop 2 lb_algo rr lb_kind DR persistence_timeout 60 protocol TCP real_server 192.168.20.3 3306 { #更改成本機的IP地址及監聽端口 weight 1 notify_down /etc/keepalived/bin/mysql.sh TCP_CHECK { connect_port 3306 connect_timeout 3 retry 3 delay_before_retry 3 } } } #準備所需腳本 [root@mysql01 keepalived]# pwd /etc/keepalived [root@mysql02 keepalived]# mkdir bin [root@mysql02 keepalived]# vim bin/mysql.sh #!/bin/bash pkill keepalived [root@mysql02 keepalived]# chmod +x bin/mysql.sh #啓動keepalived [root@mysql02 ~]# systemctl start keepalived
至此,便可實現MySQL的雙主效果(只要VIP所在的節點,MySQL服務端口沒法鏈接,那麼VIP將切換至另外一臺節點,即便宕機的mysql服務器恢復,也不會對VIP進行搶佔)。雖然有兩臺MySQL數據庫,可是其使用keepalived提供的虛擬IP地址來對外提供服務,無論這個虛擬Ip地址落在哪臺服務器上,均可以保證數據的一致性,由於它們互爲主從,而且keepalived的狀態都爲backup,也設置了不搶佔(減小VIP的切換次數),這樣能夠大大的避免keepalived的腦裂問題。