1. 程式人生 > >MySQL主主模式+Keepalived高可用

MySQL主主模式+Keepalived高可用

今天閒來無事,打算搭建一個MySQL的高可用架構,採用的是MySQL的主主結構,再外加Keepalived,對外統一提供虛IP。先來說說背景吧,現在的專案為了高可用性,都是避免單節點的存在的,比如,我們的應用程式,都是部署多個節點,通過Nginx做負載均衡,某個節點出現問題,並不會影響整體應用。那麼資料庫層如何搭建高可用的架構呢?今天我們就來看看。 ## 整體架構 MySQL採用主主結構,我們使用兩臺機器就夠了,然後再這兩臺機器上再安裝Keepalived,使用vrrp技術,虛擬出一個IP。兩臺機器如下: * 192.168.73.141:MySQL(主1)、Keepalived(MASTER) * 192.168.73.142:MySQL(主2)、Keepalived(BACKUP) * 192.168.73.150:虛IP 整體架構圖如下: ![](https://img2020.cnblogs.com/blog/1191201/202010/1191201-20201028153944433-841492740.png) ## MySQL主主搭建 我們分別在兩臺機器上安裝MySQL,使用yum方式安裝,首先從MySQL官網下載rpm包,選擇對應的系統,在這裡,我們選擇CentOS7的prm包,`mysql80-community-release-el7-3.noarch.rpm`。然後將rpm檔案分別上傳到兩臺機器上,接下來我們就是用yum來安裝MySQL。 在192.168.73.141(主1)執行如下命令, ```shell # 使用yum安裝rpm包 yum install mysql80-community-release-el7-3.noarch.rpm # 安裝MySQL社群版 時間較長 耐心等待 yum install mysql-community-server #啟動MySQL服務 service mysqld start ``` 到這裡,MySQL就安裝完成,並且正常啟動了。然後,我們用root賬號登入MySQL,並建立一個可用的賬號。 ```shell # 從MySQL的日誌中 找到root賬號的臨時密碼 grep 'temporary password' /var/log/mysqld.log # 使用root賬號登入 輸入臨時密碼 登入成功 mysql -uroot -p # 修改root賬號的密碼 使用MYSQL_NATIVE_PASSWORD的加密方式 這種方式大多數客戶端都可以連線 ALTER USER 'root'@'localhost' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'MyNewPass4!'; # 建立MySQL賬號 CREATE USER 'USER'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'USER_PWD'; # 對USER賬號授權 GRANT ALL ON *.* TO 'USER'@'%'; # 重新整理許可權 FLUSH PRIVILEGES; ``` 好了,到這裡,在192.168.73.141上安裝MySQL成功,並且建立了USER賬戶,我們可以使用NAVICAT等客戶端連線。 **在192.168.73.142(主2)上也執行上面的命令**,這樣我們在兩臺機器上都安裝了MySQL。接下來,我們就要配置MySQL的主主結構了。 首先,我們修改192.168.73.141(主1)上的my.cnf檔案。 ```shell vim /etc/my.cnf datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid # 配置server-id 每個MySQL例項的server-id都不能相同 server-id=1 # MySQL的日誌檔案的名字 log-bin=mysql_master # 作為從庫時 更新操作是否寫入日誌 on:寫入 其他資料庫以此資料庫做主庫時才能進行同步 log-slave-updates=on # MySQL系統庫的資料不需要同步 我們這裡寫了3個 更加保險 # 同步資料時忽略一下資料庫 但是必須在使用use db的情況下才會忽略;如果沒有使用use db 比如create user 資料還是會同步的 replicate-ignore-db=information_schema replicate-ignore-db=mysql replicate-ignore-db=performance_schema replicate-ignore-db=sys # 使用萬用字元忽略MySQL系統庫的表 這樣在create user時也不會進行同步了 replicate_wild_ignore_table=information_schema.% replicate_wild_ignore_table=mysql.% replicate_wild_ignore_table=performance_schema.% replicate_wild_ignore_table=sys.% # MySQL系統庫的日誌不計入binlog 這樣更加保險了 binlog-ignore-db=information_schema binlog-ignore-db=mysql binlog-ignore-db=performance_schema binlog-ignore-db=sys ``` 在192.168.73.142(主2)上也修改my.cnf檔案,我們直接複製過去,只需要修改其中的兩個地方,如下: ```shell # 配置server-id=2 server-id=2 # MySQL的日誌檔案的名字 不改名字也可以 這裡主要為了區分 log-bin=mysql_slave ``` 配置檔案都已經修改好了,我們分別在192.168.73.141(主1)和192.168.73.142(主2)上重啟MySQL服務, ```shell service mysqld restart ``` 下面我們就要配置主從了,其實主主模式就是配置兩個主從,先配置192.168.73.141(主1)->192.168.73.142(主2)的主從,然後再反過來配置192.168.73.142(主2)->192.168.73.141(主1)的主從,這樣主主的模式就配置好了。 我們先來配置**192.168.73.141(主1)->192.168.73.142(主2)的主從** 先登入192.168.73.141(主1)的資料庫,並執行如下命令: ```shell # 建立備份的賬號 使用MYSQL_NATIVE_PASSWORD的方式加密 mysql> CREATE USER 'repl_master'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'password'; # 對repl_master授予備份的許可權 mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_master'@'%'; # 重新整理許可權 mysql> FLUSH PRIVILEGES; # 檢視MySQL主節點的狀態 mysql> SHOW MASTER STATUS; +-------------------+---------+--------------+---------------------------------------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+---------+--------------+---------------------------------------------+------------------+ | mysql_master.000001 | 516 | | information_schema,mysql,performance_schema,sys | | +-------------------+---------+--------------+---------------------------------------------+------------------+ 1 row in set ``` 我們要記住binlog檔案的名字,也就是mysql_master.000001,和位置,也就是516。 然後,我們再登入到192.168.73.142(主2)的資料庫,執行如下命令: ```shell mysql> CHANGE MASTER TO # MySQL主的IP -> MASTER_HOST='192.168.73.141', # MySQL主的埠 -> MASTER_PORT=3306 # MySQL主的備份賬號 -> MASTER_USER='repl_master', # MySQL主的備份賬號密碼 -> MASTER_PASSWORD='password', # 日誌檔案 通過show master status得到的 -> MASTER_LOG_FILE='mysql_master.000001', # 日誌檔案位置 通過show master status得到的 -> MASTER_LOG_POS=516; # 開啟從庫 mysql> START SLAVE; # 檢視從庫的狀態 mysql> SHOW SLAVE STATUS; ``` 這樣,**192.168.73.141(主1)->192.168.73.142(主2)的主從**就搭建好了。然後,我們再反過來,搭建**192.168.73.142(主2)->192.168.73.141(主1)的主從**。 先登入192.168.73.142(主2)的資料庫,執行如下命令: ```shell # 建立備份的賬號 使用MYSQL_NATIVE_PASSWORD的方式加密 mysql> CREATE USER 'repl_slave'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'password'; # 對repl_slave授予備份的許可權 mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_slave'@'%'; # 重新整理許可權 mysql> FLUSH PRIVILEGES; # 檢視MySQL主節點的狀態 mysql> SHOW MASTER STATUS; +-------------------+---------+--------------+---------------------------------------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-------------------+---------+--------------+---------------------------------------------+------------------+ | mysql_slave.000001 | 379 | | information_schema,mysql,performance_schema,sys | | +-------------------+---------+--------------+---------------------------------------------+------------------+ 1 row in set ``` 再登入到192.168.73.141(主1)的資料庫,執行如下命令: ```shell mysql> CHANGE MASTER TO # MySQL主的IP -> MASTER_HOST='192.168.73.142', # MySQL主的埠 -> MASTER_PORT=3306 # MySQL主的備份賬號 -> MASTER_USER='repl_slave', # MySQL主的備份賬號密碼 -> MASTER_PASSWORD='password', # 日誌檔案 通過show master status得到的 -> MASTER_LOG_FILE='mysql_slave.000001', # 日誌檔案位置 通過show master status得到的 -> MASTER_LOG_POS=379; # 開啟從庫 mysql> START SLAVE; # 檢視從庫的狀態 mysql> SHOW SLAVE STATUS; ``` 這樣,**192.168.73.142(主2)->192.168.73.141(主1)的主從**也搭建好了。我們可以使用navicat分別連線192.168.73.141(主1)和192.168.73.142(主2),並執行建表、插入語句,驗證一下主主同步是否成功,這裡就不給大家演示了。 ## Keepalived高可用 MySQL主主結構已經搭建好了,無論從哪個MySQL插入資料,都會同步到另外一個MySQL。雖然有了MySQL主主結構,但是不能保證高可用,比如,我們的應用程式連線的是192.168.73.141(主1),倘若192.168.73.141(主1)的MySQL掛掉了,我們的應用程式並不能自動的切換到192.168.73.142(主2),我們的應用程式也是不可用的狀態。要做到這一點,就要藉助於Keepalived。 Keepalived有兩個主要的功能: * 提供虛IP,實現雙機熱備 * 通過LVS,實現負載均衡 我們這裡使用Keepalived,只需要使用其中的一個功能,提供虛IP,實現雙機熱備。我們需要在192.168.73.141(主1)和192.168.73.142(主2)上都安裝Keepalived,執行命令如下: ```shell yum install keepalived ``` 我們直接使用yum進行安裝。安裝完之後,編輯keepalived的配置檔案,首先編輯192.168.73.141(主1)上的配置檔案,如下: ```shell vim /etc/keepalived/keepalived.conf # 全域性配置 不用動 只需註釋掉vrrp_strict global_defs { notification_email { [email protected] [email protected] [email protected] } notification_email_from [email protected] smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr #必須註釋掉 否則報錯 #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } # 檢查mysql服務是否存活的指令碼 vrrp_script chk_mysql { script "/usr/bin/killall -0 mysqld" } # vrrp配置虛IP vrrp_instance VI_1 { # 狀態:MASTER 另外一臺機器為BACKUP state MASTER # 繫結的網絡卡 interface ens33 # 虛擬路由id 兩臺機器需保持一致 virtual_router_id 51 # 優先順序 MASTER的值要大於BACKUP priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } # 虛擬IP地址 兩臺keepalived需要一致 virtual_ipaddress { 192.168.73.150 } # 檢查指令碼 vrrp_script的名字 track_script { chk_mysql } } ###後邊的virtual_server全部註釋掉 它是和LVS做負載均衡用的 這裡用不到 ### ``` 再編輯192.168.73.142(主2)上的配置檔案,只需要將state MASTER改為state BACKUP,如下: ```shell state BACKUP ``` 通過keepalived的配置,我們對外提供192.168.73.150的IP,這個IP實際指向是192.168.73.141(主1),因為它的state是MASTER。當keepalived檢測到192.168.73.141(主1)上的MySQL不可用時,會自動切換到192.168.73.142(主2)。對於外部使用者是無感知的,因為外部統一使用的是192.168.73.150。 我們再來看看檢測的指令碼`/usr/bin/killall -0 mysqld`,killall命令不是系統自帶的,需要安裝,我們還是使用yum來安裝,如下: ```shell # 先查詢一下killall yum search killall #找到了psmisc.x86_64 Loading mirror speeds from cached hostfile ===============Matched: killall ================================ psmisc.x86_64 : Utilities for managing processes on your system # 安裝psmisc yum install psmisc ``` 這樣我們就可以使用killall命令了。`killall -0 `並不是殺掉程序,而是檢查程序是否存在,如果存在則返回0,如果不存在則返回1。當返回1時,keepalived就會切換主備狀態。 好了,killall也介紹完了,我們在兩臺機器上啟動keepalived,如下: ```shell # 啟動keepalived service keepalived start ``` 然後,我們在192.168.73.141(主1)上檢視一下IP是否有192.168.73.150,如下: ```shell ip addr