文章目錄
- @[toc]
- 部署 mysql
- 關閉防火墻
- 關閉 selinux
- 創建相關目錄
- 創建 mysql 用戶
- 配置 PATH 變量
- 驗證 mysql 命令
- 切換到 mysql 用戶
- 在 172.72.0.116 生成配置文件
- 在 172.72.0.137 生成配置文件
- mysql 初始化
- 啟動 mysql 服務
- 修改 mysql 的 root 用戶密碼
- 配置主從關系
- 172.72.0.137 配置成 172.72.0.116 的從庫
- 172.72.0.116 配置成 172.72.0.137 的從庫
- 主從復制驗證
- 部署 haproxy
- 創建 haproxy 配置文件
- 啟動 haproxy
- 驗證 haproxy 登錄到 mysql
- 部署 keepalived
- Keepalived 工作原理
- 搶占和非搶占模式
- 在 172.72.0.116 創建 keepalived 配置文件
- 在 172.72.0.137 創建 keepalived 配置文件
- 配置 haproxy 健康檢測腳本
- 啟動 keepalived 服務
- 驗證 VIP 登錄 mysql
- 驗證高可用是否有效
- 當一臺 mysql 服務無進程
- 驗證 keepalived 是否為非搶占模式
- 當一臺 haproxy 服務無進程,mysql 服務均正常
文章目錄
- @[toc]
- 部署 mysql
- 關閉防火墻
- 關閉 selinux
- 創建相關目錄
- 創建 mysql 用戶
- 配置 PATH 變量
- 驗證 mysql 命令
- 切換到 mysql 用戶
- 在 172.72.0.116 生成配置文件
- 在 172.72.0.137 生成配置文件
- mysql 初始化
- 啟動 mysql 服務
- 修改 mysql 的 root 用戶密碼
- 配置主從關系
- 172.72.0.137 配置成 172.72.0.116 的從庫
- 172.72.0.116 配置成 172.72.0.137 的從庫
- 主從復制驗證
- 部署 haproxy
- 創建 haproxy 配置文件
- 啟動 haproxy
- 驗證 haproxy 登錄到 mysql
- 部署 keepalived
- Keepalived 工作原理
- 搶占和非搶占模式
- 在 172.72.0.116 創建 keepalived 配置文件
- 在 172.72.0.137 創建 keepalived 配置文件
- 配置 haproxy 健康檢測腳本
- 啟動 keepalived 服務
- 驗證 VIP 登錄 mysql
- 驗證高可用是否有效
- 當一臺 mysql 服務無進程
- 驗證 keepalived 是否為非搶占模式
- 當一臺 haproxy 服務無進程,mysql 服務均正常
話不多說,直接開搞
ip | 服務 |
---|---|
172.72.0.116 | keepalived+haproxy+mysql |
172.72.0.137 | keepalived+haproxy+mysql |
172.72.0.100 | VIP |
部署前,大家先要確認集群之間的時間是否一致,集群類的服務,最怕時間不一致
部署 mysql
- Mysql 二進制文件下載地址
部署相關的操作,兩臺機器都需要執行,需要執行指定機器時,會額外提示
關閉防火墻
systemctl disable firewalld --now
關閉 selinux
setenforce 0
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
創建相關目錄
mkdir -p /data/{software,mysql/{config,logs},script,mysql-back}
創建完成后的目錄結構如下
/data/
├── mysql
│ ├── config
│ ├── logs
│ ├── mysql_data
├── mysql-back
├── script
└── software
解壓下載好的二進制文件
tar xf mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz
創建 mysql 用戶
useradd mysql
# 配置用戶密碼
echo mysqldba | passwd --stdin mysql
給對應的目錄和文件修改權限
chown -R mysql /data/software/mysql-5.7.29-linux-glibc2.12-x86_64
chown -R mysql /data/mysql
chown -R mysql /data/mysql-back
配置 PATH 變量
echo 'MYSQL_HOME="/data/software/mysql-5.7.29-linux-glibc2.12-x86_64"' >> /etc/profile
echo 'PATH=${PATH}:${MYSQL_HOME}/bin' >> /etc/profile
source /etc/profile
驗證 mysql 命令
查看是否缺少依賴庫
ldd /data/software/mysql-5.7.29-linux-glibc2.12-x86_64/bin/mysql
例如我這邊缺了倆依賴
linux-vdso.so.1 (0x00007ffe91b5a000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f495203f000)librt.so.1 => /lib64/librt.so.1 (0x00007f4951e37000)libdl.so.2 => /lib64/libdl.so.2 (0x00007f4951c33000)libncurses.so.5 => not foundlibstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f495189e000)libm.so.6 => /lib64/libm.so.6 (0x00007f495151c000)libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4951304000)libc.so.6 => /lib64/libc.so.6 (0x00007f4950f3e000)/lib64/ld-linux-x86-64.so.2 (0x00007f495225f000)libtinfo.so.5 => not found
找一下是否有高版本的依賴
find / -type f -name "libncurses.so*"
嘗試用軟連接
ln -s /usr/lib64/libncurses.so.6.1 /usr/lib64/libncurses.so.5
再次使用上面的 ldd 命令去檢查依賴,發現不是 not found 了,用這個辦法,再去解決剩下的依賴缺失
驗證 mysql 命令能不能正常使用
mysql -V
可以獲取到當前的 mysql 客戶端版本
mysql Ver 14.14 Distrib 5.7.29, for linux-glibc2.12 (x86_64) using EditLine wrapper
切換到 mysql 用戶
后續的操作都使用 mysql 用戶
su - mysql
在 172.72.0.116 生成配置文件
cat << EOF > /data/mysql/config/my.cnf
[mysqld]
pid-file=/data/mysql/mysqld.pid
socket=/data/mysql/mysqld.sock
datadir=/data/mysql/mysql_data
log-error=/data/mysql/logs/error.log
port=13306
# MySQL 在運行時需要 errmsg.sys 文件來顯示和報告錯誤消息
lc-messages-dir=/data/software/mysql-5.7.29-linux-glibc2.12-x86_64/share/englishserver_id=116# binlog
# binlog 文件的名稱
log_bin=mysql-bin
# 設置每個二進制日志文件的最大大小
max_binlog_size=100m
# 設置用于緩存二進制日志事件的緩沖區大小
binlog_cache_size=4m
# 設置 binlog 緩存的最大大小
max_binlog_cache_size=512m
# binlog 類型
binlog_format=MIXED
# binlog 過期時間
expire_logs_days=7bind-address=0.0.0.0
# 是否允許在數據庫目錄下使用符號鏈接
## symbolic-links=0:表示不允許使用符號鏈接。如果設置為 0,MySQL 服務器在啟動時將不會使用數據庫目錄下的符號鏈接,并且可能會在符號鏈接存在時報錯。
## symbolic-links=1:表示允許使用符號鏈接。如果設置為 1,MySQL 服務器在啟動時將允許使用數據庫目錄下的符號鏈接,但僅限于特定目錄或文件(根據權限設置)。
## symbolic-links=2:表示允許使用符號鏈接,且沒有限制。如果設置為 2,MySQL 服務器在啟動時將允許使用數據庫目錄下的任意符號鏈接,包括對任意文件或目錄的鏈接。
symbolic-links=0
# mysql 最大連接數
max_connections=1000
# 默認存儲引擎
default_storage_engine=innodb
# 禁用外部鎖定,MySQL 將使用內部鎖定來代替外部鎖定
skip_external_locking
# 0:表名存儲為原始大小寫,區分大小寫;
# 1:表名存儲為小寫,不區分大小寫;
# 2:表名存儲為小寫,但會在文件系統上進行名稱比較,因此會區分大小寫。
lower_case_table_names=1
# 禁用主機緩存,每次都要重新解析域名
skip_host_cache
# 開啟主機名解析
skip_name_resolve
# 設置服務器的默認字符集
character_set_server=utf8
# 客戶端與服務器之間允許的最大數據包大小
max_allowed_packet=12M
# 控制 SQL 的執行模式
## STRICT_TRANS_TABLES:啟用嚴格模式,對于事務表,如果有非法數據插入或更新,將會引發錯誤
## NO_ZERO_IN_DATE:禁止在日期中使用 "0000-00-00" 這樣的零值,否則會被轉換為 NULL 值
## ERROR_FOR_DIVISION_BY_ZERO:當除零錯誤發生時,產生錯誤而不是返回 NULL 值
## NO_AUTO_CREATE_USER:禁止 GRANT 語句自動創建新用戶,必須手動創建
## NO_ENGINE_SUBSTITUTION:如果指定的存儲引擎不可用或不存在,不要自動替換為其他可用的存儲引擎,而應該返回錯誤
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'[client]
# 設置 MySQL 客戶端連接的默認字符集
character-set-client=utf8
EOF
在 172.72.0.137 生成配置文件
cat << EOF > /data/mysql/config/my.cnf
[mysqld]
pid-file=/data/mysql/mysqld.pid
socket=/data/mysql/mysqld.sock
datadir=/data/mysql/mysql_data
log-error=/data/mysql/logs/error.log
port=13306
# MySQL 在運行時需要 errmsg.sys 文件來顯示和報告錯誤消息
lc-messages-dir=/data/software/mysql-5.7.29-linux-glibc2.12-x86_64/share/englishserver_id=137# binlog
# binlog 文件的名稱
log_bin=mysql-bin
# 設置每個二進制日志文件的最大大小
max_binlog_size=100m
# 設置用于緩存二進制日志事件的緩沖區大小
binlog_cache_size=4m
# 設置 binlog 緩存的最大大小
max_binlog_cache_size=512m
# binlog 類型
binlog_format=MIXED
# binlog 過期時間
expire_logs_days=7bind-address=0.0.0.0
# 是否允許在數據庫目錄下使用符號鏈接
## symbolic-links=0:表示不允許使用符號鏈接。如果設置為 0,MySQL 服務器在啟動時將不會使用數據庫目錄下的符號鏈接,并且可能會在符號鏈接存在時報錯。
## symbolic-links=1:表示允許使用符號鏈接。如果設置為 1,MySQL 服務器在啟動時將允許使用數據庫目錄下的符號鏈接,但僅限于特定目錄或文件(根據權限設置)。
## symbolic-links=2:表示允許使用符號鏈接,且沒有限制。如果設置為 2,MySQL 服務器在啟動時將允許使用數據庫目錄下的任意符號鏈接,包括對任意文件或目錄的鏈接。
symbolic-links=0
# mysql 最大連接數
max_connections=1000
# 默認存儲引擎
default_storage_engine=innodb
# 禁用外部鎖定,MySQL 將使用內部鎖定來代替外部鎖定
skip_external_locking
# 0:表名存儲為原始大小寫,區分大小寫;
# 1:表名存儲為小寫,不區分大小寫;
# 2:表名存儲為小寫,但會在文件系統上進行名稱比較,因此會區分大小寫。
lower_case_table_names=1
# 禁用主機緩存,每次都要重新解析域名
skip_host_cache
# 開啟主機名解析
skip_name_resolve
# 設置服務器的默認字符集
character_set_server=utf8
# 客戶端與服務器之間允許的最大數據包大小
max_allowed_packet=12M
# 控制 SQL 的執行模式
## STRICT_TRANS_TABLES:啟用嚴格模式,對于事務表,如果有非法數據插入或更新,將會引發錯誤
## NO_ZERO_IN_DATE:禁止在日期中使用 "0000-00-00" 這樣的零值,否則會被轉換為 NULL 值
## ERROR_FOR_DIVISION_BY_ZERO:當除零錯誤發生時,產生錯誤而不是返回 NULL 值
## NO_AUTO_CREATE_USER:禁止 GRANT 語句自動創建新用戶,必須手動創建
## NO_ENGINE_SUBSTITUTION:如果指定的存儲引擎不可用或不存在,不要自動替換為其他可用的存儲引擎,而應該返回錯誤
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'[client]
# 設置 MySQL 客戶端連接的默認字符集
character-set-client=utf8
EOF
mysql 初始化
mysqld --initialize-insecure \
--user=mysql \
--basedir=${MYSQL_HOME} \
--datadir=/data/mysql/mysql_data
啟動 mysql 服務
${MYSQL_HOME}/bin/mysqld \
--defaults-file=/data/mysql/config/my.cnf --daemonize \
--plugin-dir=${MYSQL_HOME}/lib/plugin
修改 mysql 的 root 用戶密碼
進入 mysql,初始化的時候沒有設定密碼,直接回車就可以了
mysql -uroot -p -S /data/mysql/mysqld.sock
修改密碼
SET PASSWORD FOR root@localhost = PASSWORD ('YWJjMTIzCg==');
配置主從關系
以下的配置,都是基于新部署的數據庫實現的,如果當前數據庫本身存在數據的情況下,需要先把 master 的數據備份,然后在 slave 節點上恢復數據后,再進行主從配置
172.72.0.137 配置成 172.72.0.116 的從庫
在 172.72.0.116 的 mysql 里面操作,創建一個從復制專用的用戶
CREATE USER 'rpldb'@'%' IDENTIFIED BY 'cnBsZGIwMDcK';
GRANT REPLICATION SLAVE ON *.* TO 'rpldb'@'%';
查看 binlog 的文件名稱和 Position 信息
SHOW MASTER STATUS\G
獲取到類似如下的信息
*************************** 1. row ***************************File: mysql-bin.000001Position: 841Binlog_Do_DB:Binlog_Ignore_DB: sys,mysql,performance_schema,information_schema
Executed_Gtid_Set:
1 row in set (0.00 sec)
在 172.72.0.137 的 mysql 里面操作
CHANGE MASTER TO MASTER_HOST='172.72.0.116', MASTER_PORT=13306, MASTER_USER='rpldb', MASTER_PASSWORD='cnBsZGIwMDcK', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=841;
啟動復制
STOP SLAVE;
START SLAVE;
查看復制是否成功
SHOW SLAVE STATUS\G
看到這兩個都是 yes,表示主從復制已經建立成功了
Slave_IO_Running: YesSlave_SQL_Running: Yes
172.72.0.116 配置成 172.72.0.137 的從庫
在 172.72.0.137 的 mysql 里面操作,創建一個從復制專用的用戶
CREATE USER 'rpldb'@'%' IDENTIFIED BY 'cnBsZGIwMDcK';
GRANT REPLICATION SLAVE ON *.* TO 'rpldb'@'%';
查看 binlog 的文件名稱和 Position 信息
SHOW MASTER STATUS\G
獲取到類似如下的信息
*************************** 1. row ***************************File: mysql-bin.000001Position: 841Binlog_Do_DB:Binlog_Ignore_DB: sys,mysql,performance_schema,information_schema
Executed_Gtid_Set:
1 row in set (0.00 sec)
在 172.72.0.116 的 mysql 里面操作
CHANGE MASTER TO MASTER_HOST='172.72.0.137', MASTER_PORT=13306, MASTER_USER='rpldb', MASTER_PASSWORD='cnBsZGIwMDcK', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=841;
啟動復制
STOP SLAVE;
START SLAVE;
查看復制是否成功
SHOW SLAVE STATUS\G
看到這兩個都是 yes,表示主從復制已經建立成功了
Slave_IO_Running: YesSlave_SQL_Running: Yes
主從復制驗證
- 先使用 mysql root 用戶創建一個庫
create database music;
再創建一個 mysql 的普通用戶,并且對 music 庫有增改查的權限
CREATE USER 'vinci'@'%' IDENTIFIED BY 'DavVinci';
GRANT SELECT,UPDATE,INSERT,CREATE ON music.* TO 'vinci'@'%';
使用 vinci 用戶登錄到 172.72.0.116 的 mysql,進行建庫建表
CREATE TABLE music.favorite(name char(10),music_name char(20)
)charset=utf8;
插入幾條數據
INSERT INTO music.favorite(name, music_name) VALUES
('Eason Chan','遙遠的她'),
('Ronald','怪胎'),
('Hacken Lee','李香蘭');
使用 vinci 用戶登錄到 172.72.0.137 的 mysql,查看數據是否存在
SELECT music_name FROM music.favorite WHERE name='Ronald' limit 5;
部署 haproxy
- 官網:http://www.haproxy.com
- HAProxy提供高可用性、負載均衡以及基于TCP和HTTP的應用代理,支持虛擬主機,它是免費、快速并且可靠的一種負載均衡解決方案。適合處理高負載站點的七層數據請求。類似的代理服務可以屏蔽內部真實服務器,防止內部服務器遭受攻擊。
使用 yum 安裝
yum install -y haproxy
創建 haproxy 配置文件
備份原來的配置文件
cp /etc/haproxy/haproxy.cfg{,.bak}
創建配置文件
cat << EOF > /etc/haproxy/haproxy.cfg
global log 127.0.0.1 local3 info # 在本機記錄日志maxconn 65535 # 每個進程可用的最大連接數chroot /data/haproxy # haproxy 安裝目錄pidfile /data/haproxy/haproxy.pid # haproxy pid 文件目錄uid 994 # 運行 haproxy 的用戶uid(id haproxy 命令可以查看)gid 991 # 運行 haproxy 的用戶組id(id haproxy 命令可以查看)daemon # 以后臺守護進程運行defaultslog globalmode http # 運行模式 tcp、 http、 healthretries 3 # 三次連接失敗,則判斷服務不可用option redispatch # 如果后端有服務器宕機,強制切換到正常服務器stats uri /haproxy # 統計頁面 URL 路徑stats refresh 30s # 統計頁面自動刷新時間stats realm haproxy-status # 統計頁面輸入密碼框提示信息stats auth admin:YWJjMTIzCg== # 統計頁面用戶名和密碼stats hide-version # 隱藏統計頁面上 HAProxy 版本信息maxconn 65535 # 每個進程可用的最大連接數timeout connect 5000 # 連接超時 timeout client 50000 # 客戶端超時timeout server 50000 # 服務器端超時frontend http_haproxymode http # 運行模式 tcp、 http、 healthmaxconn 65535 # 每個進程可用的最大連接數bind :18080 # 監聽 18080 端口log global option httplog option httpclose # 每次請求完畢后主動關閉 http 通道frontend mysqls # 自定義描述信息mode tcp # 運行模式 tcp、 http、 healthmaxconn 65535 # 每個進程可用的最大連接數bind *:13307 # 監聽 13307 端口default_backend mysql_backendbackend mysql_backendmode tcpbalance roundrobin # 設置負載均衡模式,source 保存 session 值,roundrobin 輪詢模式# rise 2是2次正確認為服務器可用# fall 3是3次失敗認為服務器不可用server mysql01 172.72.0.116:13306 check inter 5s rise 2 fall 3server mysql02 172.72.0.137:13306 check inter 5s rise 2 fall 3
EOF
給 haproxy 的 chroot 目錄授權
mkdir /data/haproxy
chown -R haproxy /data/haproxy
啟動 haproxy
systemctl enable haproxy
systemctl start haproxy
可以在瀏覽器輸入
172.72.0.116:18080/haproxy
或者172.72.0.137:18080/haproxy
來驗證是否可以看到統計頁面,這里的 ip,大家以自己實際的為準
驗證 haproxy 登錄到 mysql
haproxy 正確的情況下,兩個地址都可以用 13307 端口來登錄到 mysql 內
mysql -uvinci -pDavVinci -h172.72.0.116 -P13307
mysql -uvinci -pDavVinci -h172.72.0.137 -P13307
部署 keepalived
Keepalived 工作原理
-
keepalived 是以 VRRP 協議為實現基礎的,VRRP 全稱 Virtual Router Redundancy Protocol ,即虛擬路由冗余協議。
- 虛擬路由冗余協議,可以認為是實現路由器高可用的協議。也就是說N臺提供相同功能的路由器組成一個路由器組,這個組里面有一個 master 和多個 backup,master上面有一個對外提供服務的vip,master 不斷向 backup 發送心跳信息,告訴 backup 自己還活著,當 backup 收不到心跳消息時就認為 master 已經宕機啦,這時就需要根據 VRRP 的優先級來選舉一個 backup 當 master。從而保證高可用。
-
keepalived主要有三個模塊,分別是 core、check 和 vrrp。
- core 模塊為 keepalived 的核心,負責主進程的啟動、維護、以及全局配置文件的加載和解析。
- check 負責健康檢查,包括常見的各種檢查方式。
- vrrp 模塊是來實現 VRRP 協議的。
-
vrrp 虛擬路由冗余協議
- 使用ip報文作為傳輸協議;
- 協議號112;
- 使用固定組播網絡 224.0.0.18 進行發送;
- 只是用advertisement報文;
-
master路由器的選舉:
- 比較每臺路由器設備的優先級,優先級大的為 master。優先級相同的,比較接口IP地址,地址大的成為 master;
- master 會主動周期的發送 advertisement 報文,一秒發送一次;
- backup 如果 3 秒沒有接到 master 發送的 advertisment 報文,就說明 master down;
搶占和非搶占模式
摘抄自:MySQL + Keepalived 雙主熱備高可用操作記錄
keepalive 通過組播,單播等方式(自定義),實現 keepalive 主備推選。工作模式分為搶占和非搶占(通過參數 nopreempt 來控制)。
-
搶占模式
:- 主服務正常工作時,虛擬 IP 會在主上,備不提供服務,當主服務優先級低于備的時候,備會自動搶占虛擬 IP,這時,主不提供服務,備提供服務。
也就是說,工作在搶占模式下,不分主備,只管優先級。 - 不管 keepalived.conf 里的 state 配置成 master 還是 backup,只看誰的 priority 優先級高(一般而言,state 為 MASTER 的優先級要高于 BACKUP)。priority 優先級高的那一個在故障恢復后,會自動將 VIP 資源再次搶占回來!!
- 主服務正常工作時,虛擬 IP 會在主上,備不提供服務,當主服務優先級低于備的時候,備會自動搶占虛擬 IP,這時,主不提供服務,備提供服務。
-
非搶占模式:
- 這種方式通過參數 nopreempt(一般設置在 advert_int 的那一行下面)來控制。不管 priority 優先級,只要 MASTER 機器發生故障,VIP 資源就會被切換到 BACKUP 上。
并且當 MASTER 機器恢復后,也不會去將 VIP 資源搶占回來,直至 BACKUP 機器發生故障時,才能自動切換回來。
- 這種方式通過參數 nopreempt(一般設置在 advert_int 的那一行下面)來控制。不管 priority 優先級,只要 MASTER 機器發生故障,VIP 資源就會被切換到 BACKUP 上。
千萬注意
:
nopreempt 這個參數只能用于 state 為 backup 的情況,所以在配置的時候要把 master 和 backup 的 state 都設置成 backup,這樣才會實現 keepalived 的非搶占模式!
也就是說:
- 當 state 狀態一個為 master,一個為 backup 的時候,加不加 nopreempt 這個參數都是一樣的效果。即都是根據 priority 優先級來決定誰搶占 vip 資源的,是搶占模式!
- 當 state 狀態都設置成 backup,如果不配置 nopreempt 參數,那么也是看 priority 優先級決定誰搶占 vip 資源,即也是搶占模式。
- 當 state 狀態都設置成 backup,如果配置 nopreempt 參數,那么就不會去考慮 priority 優先級了,是非搶占模式!即只有 vip 當前所在機器發生故障,另一臺機器才能接管 vip。即使優先級高的那一臺機器恢復 后也不會主動搶回 vip,只能等到對方發生故障,才會將 vip 切回來。
使用 yum 安裝
yum install -y keepalived
在 172.72.0.116 創建 keepalived 配置文件
備份原來的配置文件
cp /etc/keepalived/keepalived.conf{,.bak}
創建配置文件,這里采用非搶占模式
cat << EOF > /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {# 每個 keepalived 要配置成不一樣的router_id mysql1
}# 作用:添加一個周期性執行的腳本。
## 腳本的退出狀態碼會被調用它的所有的VRRP Instance記錄。
## 注意:至少有一個VRRP實例調用它并且優先級不能為0。
## 優先級范圍是1-254,用來做健康檢查的,當檢查失敗時會將 vrrp_instance 的 priority 減少相應的值
vrrp_script chk_haproxy {# 監控服務腳本,腳本x執行權限;script "/data/script/chk_haproxy.sh"# 檢測時間間隔(執行腳本間隔)interval 2weight -2# 解釋 weight:## 如果腳本執行成功(退出狀態碼為0),weight大于0,則priority增加。## 如果腳本執行失敗(退出狀態碼為非0),weight小于0,則priority減少。## 其他情況下,priority不變。
}vrrp_instance VI_1 {state BACKUP# 指定虛擬 ip 的網卡接口,根據自己實際網卡名稱修改interface ens160# 路由器標識,MASTER 和 BACKUP 必須是一致的virtual_router_id 51# 定義優先級,數字越大,優先級越高,在同一個 vrrp_instance 下,MASTER 的優先級必須大于 BACKUP 的優先級。這樣 MASTER 故障恢復后,就可以將VIP資源再次搶回來priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.72.0.100}# 添加此行表示非搶占模式# nopreempttrack_script {chk_haproxy}
}
EOF
在 172.72.0.137 創建 keepalived 配置文件
備份原來的配置文件
cp /etc/keepalived/keepalived.conf{,.bak}
創建配置文件,這里采用非搶占模式
cat << EOF > /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {# 每個 keepalived 要配置成不一樣的router_id mysql2
}# 作用:添加一個周期性執行的腳本。
## 腳本的退出狀態碼會被調用它的所有的VRRP Instance記錄。
## 注意:至少有一個VRRP實例調用它并且優先級不能為0。
## 優先級范圍是1-254,用來做健康檢查的,當檢查失敗時會將 vrrp_instance 的 priority 減少相應的值
vrrp_script chk_haproxy {# 監控服務腳本,腳本x執行權限;script "/data/script/chk_haproxy.sh"# 檢測時間間隔(執行腳本間隔)interval 2weight -2# 解釋 weight:## 如果腳本執行成功(退出狀態碼為0),weight大于0,則priority增加。## 如果腳本執行失敗(退出狀態碼為非0),weight小于0,則priority減少。## 其他情況下,priority不變。
}vrrp_instance VI_1 {state BACKUP# 指定虛擬 ip 的網卡接口,根據自己實際網卡名稱修改interface ens160# 路由器標識,MASTER 和 BACKUP 必須是一致的virtual_router_id 51# 定義優先級,數字越大,優先級越高,在同一個 vrrp_instance 下,MASTER 的優先級必須大于 BACKUP 的優先級。這樣 MASTER 故障恢復后,就可以將VIP資源再次搶回來priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.72.0.100}# 添加此行表示非搶占模式# nopreempttrack_script {chk_haproxy}
}
EOF
配置 haproxy 健康檢測腳本
- 所有 keepalived 節點都需要配置
- 因為非搶占模式,所以需要手動切換 VIP,這里腳本用停止 keepalived 服務來觸發手動切換 VIP
- 腳本里面是探測 haproxy 的端口三次,如果返回狀態碼都是非0,就會觸發停止 keepalived 服務
cat << EOF > /data/script/chk_haproxy.sh
#!/bin/bash
exitNum=0while true
doif ! nc -z 127.0.0.1 13307; thenlet exitNum++[ ${exitNum} -lt 3 ] || systemctl stop keepalivedfi
done
EOF
keepalived 的健康檢測腳本必須要有執行權限
chmod +x /data/script/chk_haproxy.sh
啟動 keepalived 服務
注意啟動順序,要先啟動一個 keepalived 組件,并且有 VIP 了之后,再去啟動剩下的 keepalived 組件,如果同時啟動 keepalived 組件,那就都會有 VIP 地址了
systemctl enable keepalived
systemctl start keepalived
驗證 VIP 登錄 mysql
能讀取到數據,證明 keepalived 部署沒有問題
mysql -uvinci -pDavVinci -h172.72.0.100 -P13307 -e "SELECT music_name FROM music.favorite WHERE name='Hacken Lee' limit 1;"
驗證高可用是否有效
當一臺 mysql 服務無進程
- 殺掉一個 mysql 的進程,模擬 mysql 出現故障,等 30秒后,看是否能寫入 mysql 數據
- 殺掉一個 mysql 的進程后,可以從 haproxy 的統計頁面看到顯示為 down
cat /data/mysql/mysqld.pid | xargs kill -9 && \
sleep 30 && \
mysql -uvinci -pDavVinci -h172.72.0.100 -P13307 -e "INSERT INTO music.favorite(name, music_name) VALUES ('Beyond','冷雨夜');"
驗證完成后,再次啟動 mysql,在 haproxy 的統計頁面看到顯示為 up,并且進入 mysql 查看
SHOW SLAVE STATUS
確認Slave_IO_Running
和Slave_SQL_Running
都是YES
驗證 keepalived 是否為非搶占模式
存在 VIP 的節點,停止 keepalived 服務,模擬 keepalived 故障,看 VIP 是否會漂移到其他節點
systemctl stop keepalived
此時去其他節點,發現 VIP 已經漂移過來了,并且可以讀取 mysql 數據
- 將停止的 keepalived 重新啟動,看 VIP 是否會漂移回來
- 正常情況下,處于非搶占模式,VIP 是不會再次漂移的
systemctl start keepalived
當一臺 haproxy 服務無進程,mysql 服務均正常
- 這里直接把有 VIP 節點的 haproxy 服務停止,模擬 haproxy 故障,并且觸發 keepalived 的健康檢測,進行 VIP 的漂移,同時驗證是否能讀取 mysql 數據
systemctl stop haproxy && \
sleep 10 && \
ip a | grep 172.72.0.100; \
mysql -uvinci -pDavVinci -h172.72.0.100 -P13307 -e "SELECT music_name FROM music.favorite WHERE name='Hacken Lee' limit 1;"
使用 tcpdump 命令觀察地址的變化
tcpdump -i ens160 vrrp -nn
可以看到,VIP 從 172.72.0.116 機器切換到 172.72.0.137 機器上,并且也能正常讀取 mysql 的數據
22:25:19.569090 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:20.569328 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:21.570001 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:21.578036 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 0, authtype simple, intvl 1s, length 20
22:25:22.196273 IP 172.72.0.137 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:23.196572 IP 172.72.0.137 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:24.196795 IP 172.72.0.137 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
基于二進制部署的 mysql 寫了一個腳本來做啟停和重啟
#!/usr/bin/env bash
baseDir="$(cd `dirname $0`;pwd)"
envName="$1"
envOpt="$2"
pidFile="/data/mysql/mysqld.pid"
MYSQL_HOME='/data/software/mysql-5.7.29-linux-glibc2.12-x86_64'function opt_usage () {echo "usage: bash $0 'start|stop|restart'"exit 1
}if [ $# -lt 1 ];thenopt_usageexit 1
fifunction start_mysql () {if [[ ! -f "${pidFile}" ]];then${MYSQL_HOME}/bin/mysqld \--defaults-file=/data/mysql/config/my.cnf --daemonize \--plugin-dir=${MYSQL_HOME}/lib/pluginif [ $? -eq 0 ];thenecho "mysql start success"fielsepidNum=$(ps -ef | grep -v grep | grep mysqld | awk '{print $2}')echo "pid: ${pidNum} is running for mysqld,please check it"exit 1fi
}function stop_mysql () {if [[ ! -f "${pidFile}" ]];thenecho "pid file: ${pidFile} is not found"exit 1elsekill $(cat ${pidFile})sleep 5num=0while truedops -ef | grep -v grep | grep mysqld | awk '{print $2}' &> /dev/nullif [ $? -eq 0 ];thenecho "stop mysql success"breakelseecho "wating for mysql shutdown......"let num++sleep 1fiif [ ${num} -eq 3 ];thenecho "stop mysql failed,please check it"exit 1fidonefi
}function status_mysql () {if [ -f "${pidFile}" ];thenpidNum="$(ps -ef | grep -v grep | grep mysqld | awk '{print $2}')"if [ ${pidNum} -eq $(cat ${pidFile}) ];thenecho "mysql is running"echo "mysql version is: $(mysql -V)"echo " mysql pid is: ${pidNum}"fielseecho "mysql is not running"fi
}case $1 in'start')start_mysql;;'stop')stop_mysql;;'restart')stop_mysqlstart_mysql;;'status')status_mysql;;'*')opt_usageexit 1
esac