Docker Compose搭建MySQL主從複製叢集

零壹技術棧發表於2018-07-02

前言

隨著應用業務資料不斷的增大,應用的 響應速度不斷下降,在檢測過程中我們不難發現大多數的請求都是 查詢操作。此時,我們可以將資料庫擴充套件成 主從複製模式,將 讀操作寫操作 分離開來,多臺資料庫 分攤請求,從而 減少單庫訪問壓力,進而應用得到優化。

正文

主從複製的方式

MySQL 5.6 開始主從複製有兩種方式:基於日誌binlog)和 基於 GTID全域性事務標示符)。

本文只涉及基於日誌 binlog主從配置

主從複製的流程

Docker Compose搭建MySQL主從複製叢集

MySQL 同步操作通過 3 個執行緒實現,其基本步驟如下:

  1. 主伺服器 將資料的更新記錄到 二進位制日誌Binary log)中,用於記錄二進位制日誌事件,這一步由 主庫執行緒 完成;

  2. 從庫主庫二進位制日誌 複製到本地的 中繼日誌Relay log),這一步由 從庫 I/O 執行緒 完成;

  3. 從庫 讀取 中繼日誌 中的 事件,將其重放到資料中,這一步由 從庫 SQL 執行緒 完成。

主從模式的優點

1. 負載均衡

通常情況下,會使用 主伺服器 對資料進行 更新刪除新建 等操作,而將 查詢 工作落到 從庫 頭上。

2. 異地容災備份

可以將主伺服器上的資料同步到 異地從伺服器 上,極大地提高了 資料安全性

3. 高可用

資料庫的複製功能實現了 主伺服器從伺服器間 的資料同步,一旦主伺服器出了 故障,從伺服器立即擔當起主伺服器的角色,保障系統持續穩定運作。

4. 高擴充套件性

主從複製 模式支援 2 種擴充套件方式:

  • scale-up

向上擴充套件或者 縱向擴充套件,主要是提供比現在伺服器 效能更好 的伺服器,比如 增加 CPU記憶體 以及 磁碟陣列等,因為有多臺伺服器,所以可擴充套件性比單臺更大。

  • scale-out

向外擴充套件或者 橫向擴充套件,是指增加 伺服器數量 的擴充套件,這樣主要能分散各個伺服器的壓力。

主從模式的缺點

1. 成本增加

搭建主從肯定會增加成本,畢竟一臺伺服器和兩臺伺服器的成本完全不同,另外由於主從必須要開啟 二進位制日誌,所以也會造成額外的 效能消耗

2. 資料延遲

從庫主庫 複製資料肯定是會有一定的 資料延遲 的。所以當剛插入就出現查詢的情況,可能查詢不出來。當然如果是插入者自己查詢,那麼可以直接從 主庫 中查詢出來,當然這個也是需要用程式碼來控制的。

3. 寫入更慢

主從複製 主要是針對 讀遠大於寫 或者對 資料備份實時性 要求較高的系統中。因為 主伺服器 在寫中需要更多操作,而且 只有一臺 可以寫入的 主庫,所以寫入的壓力並不能被分散。

主從複製的前提條件

  1. 主從伺服器 作業系統版本位數 一致。

  2. 主資料庫和從資料庫的 版本 要一致。

  3. 主資料庫和從資料庫中的 資料 要一致。

  4. 主資料庫 開啟 二進位制日誌,主資料庫和從資料庫的 server_id 在區域網內必須 唯一

具體配置

1. 環境準備

名稱 版本號
Docker 18.03.1-ce
Docker Compose 1.21.1
MySQL 5.7.17

2. 配置docker-compose.yml

docker-compose.yml

version: '2'
services:
  mysql-master:
    build:
      context: ./
      dockerfile: master/Dockerfile
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
      - "MYSQL_DATABASE=replicas_db"
    links:
      - mysql-slave
    ports:
      - "33065:3306"
    restart: always
    hostname: mysql-master
  mysql-slave:
    build:
      context: ./
      dockerfile: slave/Dockerfile
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
      - "MYSQL_DATABASE=replicas_db"
    ports:
      - "33066:3306"
    restart: always
    hostname: mysql-slave
複製程式碼

3. 主資料庫配置

3.1. 配置Dockerfile

Dockerfile

FROM mysql:5.7.17
MAINTAINER harrison
ADD ./master/my.cnf /etc/mysql/my.cnf
複製程式碼

3.2. 配置my.cnf檔案

my.cnf

[mysqld]
## 設定server_id,一般設定為IP,注意要唯一
server_id=100  
## 複製過濾:也就是指定哪個資料庫不用同步(mysql庫一般不同步)
binlog-ignore-db=mysql  
## 開啟二進位制日誌功能,可以隨便取,最好有含義(關鍵就是這裡了)
log-bin=replicas-mysql-bin  
## 為每個session分配的記憶體,在事務過程中用來儲存二進位制日誌的快取
binlog_cache_size=1M  
## 主從複製的格式(mixed,statement,row,預設格式是statement)
binlog_format=mixed  
## 二進位制日誌自動刪除/過期的天數。預設值為0,表示不自動刪除。
expire_logs_days=7  
## 跳過主從複製中遇到的所有錯誤或指定型別的錯誤,避免slave端複製中斷。
## 如:1062錯誤是指一些主鍵重複,1032錯誤是因為主從資料庫資料不一致
slave_skip_errors=1062
複製程式碼

4. 從資料庫配置

4.1. 配置Dockerfile

Dockerfile

FROM mysql:5.7.17
MAINTAINER harrison
ADD ./slave/my.cnf /etc/mysql/my.cnf
複製程式碼

4.2. 配置my.cnf檔案

[mysqld]
## 設定server_id,一般設定為IP,注意要唯一
server_id=101  
## 複製過濾:也就是指定哪個資料庫不用同步(mysql庫一般不同步)
binlog-ignore-db=mysql  
## 開啟二進位制日誌功能,以備Slave作為其它Slave的Master時使用
log-bin=replicas-mysql-slave1-bin  
## 為每個session 分配的記憶體,在事務過程中用來儲存二進位制日誌的快取
binlog_cache_size=1M  
## 主從複製的格式(mixed,statement,row,預設格式是statement)
binlog_format=mixed  
## 二進位制日誌自動刪除/過期的天數。預設值為0,表示不自動刪除。
expire_logs_days=7  
## 跳過主從複製中遇到的所有錯誤或指定型別的錯誤,避免slave端複製中斷。
## 如:1062錯誤是指一些主鍵重複,1032錯誤是因為主從資料庫資料不一致
slave_skip_errors=1062  
## relay_log配置中繼日誌
relay_log=replicas-mysql-relay-bin  
## log_slave_updates表示slave將複製事件寫進自己的二進位制日誌
log_slave_updates=1  
## 防止改變資料(除了特殊的執行緒)
read_only=1  
複製程式碼

5. 建立容器

進入 docker 目錄,執行 docker-compose 啟動命令。

$ docker-compose up -d
複製程式碼

如圖所示,MySQL 主資料庫從資料庫 的容器建立成功。

Docker Compose搭建MySQL主從複製叢集

分別配置 主資料庫從資料庫 的連線資訊如下:

  • 主資料庫

Docker Compose搭建MySQL主從複製叢集

  • 從資料庫

Docker Compose搭建MySQL主從複製叢集

6. 配置從資料庫

檢查從庫的起始狀態

$ show master status;
複製程式碼

如圖所示,從資料庫處於 未同步複製狀態

Docker Compose搭建MySQL主從複製叢集

檢查主庫的狀態

$ show master status;
複製程式碼

記錄 主資料庫 binary-log檔名稱資料同步起始位置

  • File: replicas-mysql-bin.000003
  • Position: 154

Docker Compose搭建MySQL主從複製叢集

從庫配置主庫資訊

從資料庫 上執行 主資料庫 的相關配置 sql 進行主從關聯

CHANGE MASTER TO
    MASTER_HOST='mysql-master',
    MASTER_USER='root',
    MASTER_PASSWORD='root',
    MASTER_LOG_FILE='replicas-mysql-bin.000003',
    MASTER_LOG_POS=154;
複製程式碼

重新啟動 slave 服務

$ stop slave
$ start slave
複製程式碼

進一步檢查 從資料庫 的狀態資訊,兩者已經進行 資料同步 關聯。

Docker Compose搭建MySQL主從複製叢集

7. 建立目標表

主資料庫 中建立一張測試資料表 course

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `lesson_period` double(5,0) DEFAULT NULL,
  `score` double(10,0) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
複製程式碼

主資料庫從資料庫 的 資料處於 同步狀態,主從複製叢集搭建完成。

Docker Compose搭建MySQL主從複製叢集

MySQL的複製型別

基於語句的複製

主伺服器上面執行的語句在從伺服器上面再執行一遍,在 MySQL-3.23 版本以後支援。

問題:時間上可能不完全同步造成偏差,執行語句的使用者也可能是不同一個使用者。

基於行的複製

把主伺服器上面改變後的內容直接複製過去,而不關心到底改變該內容是由哪條語句引發的,在 MySQL-5.0 版本以後引入。

問題:比如一個工資表中有一萬個使用者,我們把每個使用者的工資+1000,那麼基於行的複製則要複製一萬行的內容,由此造成的開銷比較大,而基於語句的複製僅僅一條語句就可以了。

混合型別的複製

MySQL 預設使用 基於語句的複製,當 基於語句的複製 會引發問題的時候就會使用 基於行的複製MySQL 會自動進行選擇。


歡迎關注公眾號: 零壹技術棧

零壹技術棧

本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。

相關文章