今天閒來無事,打算搭建一個MySQL的高可用架構,採用的是MySQL的主主結構,再外加Keepalived,對外統一提供虛IP。先來講說背景吧,如今的項目爲了高可用性,都是避免單節點的存在的,好比,咱們的應用程序,都是部署多個節點,經過Nginx作負載均衡,某個節點出現問題,並不會影響總體應用。那麼數據庫層如何搭建高可用的架構呢?今天咱們就來看看。mysql
總體架構
MySQL採用主主結構,咱們使用兩臺機器就夠了,而後再這兩臺機器上再安裝Keepalived,使用vrrp技術,虛擬出一個IP。兩臺機器以下:sql
- 192.168.73.141:MySQL(主1)、Keepalived(MASTER)
- 192.168.73.142:MySQL(主2)、Keepalived(BACKUP)
- 192.168.73.150:虛IP
總體架構圖以下:shell
MySQL主主搭建
咱們分別在兩臺機器上安裝MySQL,使用yum方式安裝,首先從MySQL官網下載rpm包,選擇對應的系統,在這裏,咱們選擇CentOS7的prm包,mysql80-community-release-el7-3.noarch.rpm
。而後將rpm文件分別上傳到兩臺機器上,接下來咱們就是用yum來安裝MySQL。數據庫
在192.168.73.141(主1)執行以下命令,vim
# 使用yum安裝rpm包 yum install mysql80-community-release-el7-3.noarch.rpm # 安裝MySQL社區版 時間較長 耐心等待 yum install mysql-community-server #啓動MySQL服務 service mysqld start
到這裏,MySQL就安裝完成,而且正常啓動了。而後,咱們用root帳號登陸MySQL,並建立一個可用的帳號。架構
# 從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的主主結構了。socket
首先,咱們修改192.168.73.141(主1)上的my.cnf文件。oop
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文件,咱們直接複製過去,只須要修改其中的兩個地方,以下:加密
# 配置server-id=2 server-id=2 # MySQL的日誌文件的名字 不更名字也能夠 這裏主要爲了區分 log-bin=mysql_slave
配置文件都已經修改好了,咱們分別在192.168.73.141(主1)和192.168.73.142(主2)上重啓MySQL服務,
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)的數據庫,並執行以下命令:
# 建立備份的帳號 使用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)的數據庫,執行以下命令:
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)的數據庫,執行以下命令:
# 建立備份的帳號 使用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)的數據庫,執行以下命令:
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,執行命令以下:
yum install keepalived
咱們直接使用yum進行安裝。安裝完以後,編輯keepalived的配置文件,首先編輯192.168.73.141(主1)上的配置文件,以下:
vim /etc/keepalived/keepalived.conf # 全局配置 不用動 只需註釋掉vrrp_strict global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc 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,以下:
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來安裝,以下:
# 先查詢一下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,以下:
# 啓動keepalived service keepalived start
而後,咱們在192.168.73.141(主1)上查看一下IP是否有192.168.73.150,以下:
ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:57:8c:cd brd ff:ff:ff:ff:ff:ff inet 192.168.73.141/24 brd 192.168.73.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.73.150/32 scope global ens33 # 咱們看到了192.168.73.150 valid_lft forever preferred_lft forever inet6 fe80::720b:92b0:7f78:57ed/64 scope link noprefixroute valid_lft forever preferred_lft forever
到這裏,keepalived的配置就完成了,咱們經過navicat鏈接192.168.73.150,能夠正常的鏈接數據庫,實際上它鏈接的是192.168.73.141的數據庫,咱們操做數據庫也是正常的。
而後,咱們停掉192.168.73.141(主1)上的MySQL服務,
service mysqld stop # 再用 ip addr查看一下 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:57:8c:cd brd ff:ff:ff:ff:ff:ff inet 192.168.73.141/24 brd 192.168.73.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::720b:92b0:7f78:57ed/64 scope link noprefixroute valid_lft forever preferred_lft forever
192.168.73.150的IP找不到了,咱們再去192.168.73.142(主2)上去查看,能夠發現192.168.73.150的IP。咱們在navicat上操做數據庫,是能夠正常使用的。但這時實際鏈接的是192.168.73.142(主2)的數據庫。咱們是沒有感知的。若是咱們把192.168.73.141(主1)上的mysql服務再啓動起來,192.168.73.150還會切換到192.168.73.141(主1)。
總結
咱們經過MySQL主主結構+keepalived雙機熱備實現了MySQL的高可用,咱們應用程序能夠鏈接虛IP,具體鏈接的實際MySQL,不須要咱們關心。若是咱們再作讀寫分離的話,能夠將MySQL(主2)做爲主,配置數據庫的主從關係。這時,虛IP鏈接的是MySQL(主1),MySQL(主1)將數據同步到MySQL(主2),而後MySQL(主2)再將數據同步到其餘從庫。若是MySQL(主1)掛掉,虛IP指向MySQL(主2),MySQL(主2)再將數據同步到其餘從庫。