如何搭建雙 M 結構的主從備份?

關於 MySQL 主從搭建,松哥之前寫過好多篇文章了,還錄過一個視頻。不過之前的都是一主一從的結構,但是小夥伴們知道,我們在項目中,更常見一種結構是雙 M 結構,即兩個 MySQL 實例,每個 MySQL 實例互爲主備,這樣在主節點突然斷電或者不可用的時候,slave 節點可以很快切換爲 master,架構圖如下:

在這種結構中,兩個 MySQL 實例的地位是平等的,互爲對方的主備,我們判斷誰是主機誰是從機的方式主要是看 readonly,誰是隻讀的,那誰就是從機,所以這種情況下,主從切換也很方便,只要修改 readonly 屬性即可。

接下來我們就來搭建一個雙 M 的主從備份,看看和單純的 M-S 結構的有啥區別。

1. 準備工作

以下配置基於 Docker。

這裏,我們首先準備兩臺機器:

  • M1:10.3.50.27:33061
  • M2:10.3.50.27:33062

1.1 M1 配置

M1 的配置就三個步驟,比較容易:

1. 授權給 M2 服務器

GRANT REPLICATION SLAVE ON *.* to 'rep1'@'10.3.50.27' identified by '123';
FLUSH PRIVILEGES;

這裏表示配置 M2 登錄用戶名爲 rep1,密碼爲 123,並且必須從 10.3.50.27 這個地址登錄,登錄成功之後可以操作任意庫中的任意表。其中,如果不需要限制登錄地址,可以將 IP 地址更換爲一個 %

>注意,在 MySQL8 裏邊,這塊有一些變化。MySQL8 中用戶創建和授權需要分開,不能像上面那樣一步到位,具體方式如下:

CREATE USER `rep1`@`10.3.50.27` IDENTIFIED WITH caching_sha2_password BY 'javaboy.COM';

GRANT Replication Slave ON *.* TO `rep1`@`10.3.50.27`;

2. 修改主庫配置文件

開啓 binlog ,並設置 server-id ,每次修改配置文件後都要重啓 MySQL 服務纔會生效

開啓 binlog 主要是修改 MySQL 的配置文件 mysqld.cnf,該文件在容器的 /etc/mysql/mysql.conf.d 目錄下。

針對該配置文件,我們做如下修改:

[mysqld]
# 這個參數表示啓用 binlog 功能,並指定 binlog 的存儲目錄
log-bin=javaboy_logbin
# 設置 binlog_format 格式,注意不要使用 STATEMENT
binlog_format=ROW
# 設置一個 binlog 文件的最大字節
# 設置最大 100MB
max_binlog_size=104857600

# 設置了 binlog 文件的有效期(單位:天)
expire_logs_days = 7

# binlog 日誌只記錄指定庫的更新(配置主從複製的時候會用到)
binlog-do-db=javaboy_db

# binlog 日誌不記錄指定庫的更新(配置主從複製的時候會用到)
#binlog-ignore-db=javaboy_no_db

# 寫緩存多少次,刷一次磁盤,默認 0 表示這個操作由操作系統根據自身負載自行決定多久寫一次磁盤
# 1 表示每一條事務提交都會立即寫磁盤,n 則表示 n 個事務提交纔會寫磁盤
sync_binlog=0

# 爲當前服務取一個唯一的 id(MySQL5.7 開始需要)
server-id=1

各項配置的含義松哥已經在注視中說明了。截圖如下:

如下圖:

  • log-bin:同步的日誌路徑及文件名,一定注意這個目錄要是 MySQL 有權限寫入的(我這裏是偷懶了,直接放在了下面那個datadir下面)。
  • binlog-do-db:要同步的數據庫名,當從機連上主機後,只有這裏配置的數據庫纔會被同步,其他的不會被同步。
  • server-id: MySQL 在主從環境下的唯一標誌符,給個任意數字,注意不能和 M2 重複,因爲將來 server-id 用於標誌 binlog 是由哪個庫產生的,所以主從數據庫的 server-id 千萬不能一樣,不然可能導致主從數據庫 binlog 的循環複製問題。
  • 注意 binlog_format 的值爲 ROW,具體原因在之前的文章中松哥已經和大家聊過了,這裏就不再贅述。

配置完成後重啓 MySQL 服務端:

docker restart mysql33061

3. 查看 M1 當前二進制日誌名和偏移量

這個操作的目的是爲了在 M2 啓動後,從這個點開始進行數據的恢復:

show master status;

至此,M1 配置完成。

1.2 M2 配置

M2 的配置和 M1 一模一樣,唯一不同的地方在於,M2 的 mysqld.cnf 這個文件中的 server-id=2,其他都一模一樣,我就不重複了。

配置完成後,相當於 M2 現在也是一個主機,我們在 M2 上也可以執行 show master status; 命令,結果如下:

1.3 主從配置

接下來配置 M1 和 M2 分別爲對方的主機。

M1 配置

先來配置給 M1 配置吧,執行如下命令設置主機:

change master to master_host='10.3.50.77',master_port=33062,master_user='rep1',master_password='123',master_log_file='javaboy_logbin.000001',master_log_pos=154;

這裏配置了主機地址、端口以及從機登錄主機的用戶名和密碼,注意最後兩個參數要和 M2 中的保持一致。

注意,由於 MySQL8 密碼插件的問題,這個問題同樣會給主從配置帶來問題,所以在 MySQL8 配置主從上,上面這行命令需要添加 get_master_public_key=1,完整命令如下:

change master to master_host='10.3.50.77',master_port=33062,master_user='rep1',master_password='123',master_log_file='javaboy_logbin.000001',master_log_pos=154,get_master_public_key=1;

3. 啓動 slave 進程

start slave;

啓動之後查看從機狀態:

show slave status\G;

4. 查看 slave 的狀態

主要是下面兩項值都要爲爲 YES,則表示配置正確:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

至此,配置完成,主機創建庫,添加數據,從機會自動同步。

如果這兩個有一個不爲 YES ,表示主從環境搭建失敗,此時可以閱讀日誌,查看出錯的原因,再具體問題具體解決。

M2 配置

接下來再來配置 M2,M2 和 M1 的配置基本上是一致的,change master 中記得把地址和端口寫對:

change master to master_host='10.3.50.77',master_port=33061,master_user='rep1',master_password='123',master_log_file='javaboy_logbin.000001',master_log_pos=154;

配置完成後,現在 M1 和 M2 就互爲主備了。

1.4 測試

測試分兩步:

  • M1 中新建 javaboy_db 庫,庫中建 user 表,表中插入一條記錄,然後查看 M2 中是否將數據同步過來了。
  • M2 中向 user 表中添加一條記錄,查看 M1 中是否有對應的值。

經過測試,我們發現沒問題,現在可以兩邊互相同步對方的數據了。

2. 誰主誰從

雖然是雙 M 結構,但是在實際應用中還是得分個主從,那麼雙 M 該怎麼分主從呢?

在生產環境中,我們一般會將備份節點設置爲 read_only,也就是隻讀,防止有誤操作,當然不用擔心設置爲 read_onlybinlog 的寫入也被阻止,super 用戶依然擁有寫入權限。

設置全庫只讀的辦法也很簡單,首先我們執行如下 SQL 先看看對應變量的值:

show variables like 'read_only';

可以看到,默認情況下,read_only 是 OFF,即關閉狀態,我們先把它改爲 ON,執行如下 SQL:

set global read_only=1;

1 表示 ON,0 表示 OFF,執行結果如下:

這個 read_only 對 super 用戶無效,所以設置完成後,接下來我們退出來這個會話,然後創建一個不包含 super 權限的用戶,用新用戶登錄,登錄成功之後,執行一個插入 SQL,結果如下:

可以看到,這個錯誤信息中說,現在的 MySQL 是隻讀的(只能查詢),不能執行當前 SQL。

如此設置之後,在 master 發生異常需要主從切換的時候再將 slave 臨時頂替上來。爲了更好的做到主從同步,binlog 的類型建議使用 row 模式,關於 binlog 的三種模式,可以參考666!MySQL 的 binlog 的三種格式這麼好玩!一文。

好啦,有問題歡迎留言討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章