前言
隨著應用業務資料不斷的增大,應用的 響應速度不斷下降,在檢測過程中我們不難發現大多數的請求都是 查詢操作。此時,我們可以將資料庫擴充套件成 主從複製模式,將 讀操作 和 寫操作 分離開來,多臺資料庫 分攤請求,從而 減少單庫 的 訪問壓力,進而應用得到優化。
正文
主從複製的方式
MySQL 5.6
開始主從複製有兩種方式:基於日誌(binlog
)和 基於 GTID
(全域性事務標示符)。
本文只涉及基於日誌 binlog
的 主從配置。
主從複製的流程
MySQL
同步操作通過 3
個執行緒實現,其基本步驟如下:
-
主伺服器 將資料的更新記錄到 二進位制日誌(
Binary log
)中,用於記錄二進位制日誌事件,這一步由 主庫執行緒 完成; -
從庫 將 主庫 的 二進位制日誌 複製到本地的 中繼日誌(
Relay log
),這一步由 從庫I/O
執行緒 完成; -
從庫 讀取 中繼日誌 中的 事件,將其重放到資料中,這一步由 從庫
SQL
執行緒 完成。
主從模式的優點
1. 負載均衡
通常情況下,會使用 主伺服器 對資料進行 更新、刪除 和 新建 等操作,而將 查詢 工作落到 從庫 頭上。
2. 異地容災備份
可以將主伺服器上的資料同步到 異地從伺服器 上,極大地提高了 資料安全性。
3. 高可用
資料庫的複製功能實現了 主伺服器 與 從伺服器間 的資料同步,一旦主伺服器出了 故障,從伺服器立即擔當起主伺服器的角色,保障系統持續穩定運作。
4. 高擴充套件性
主從複製 模式支援 2
種擴充套件方式:
- scale-up
向上擴充套件或者 縱向擴充套件,主要是提供比現在伺服器 效能更好 的伺服器,比如 增加 CPU
和 記憶體 以及 磁碟陣列等,因為有多臺伺服器,所以可擴充套件性比單臺更大。
- scale-out
向外擴充套件或者 橫向擴充套件,是指增加 伺服器數量 的擴充套件,這樣主要能分散各個伺服器的壓力。
主從模式的缺點
1. 成本增加
搭建主從肯定會增加成本,畢竟一臺伺服器和兩臺伺服器的成本完全不同,另外由於主從必須要開啟 二進位制日誌,所以也會造成額外的 效能消耗。
2. 資料延遲
從庫 從 主庫 複製資料肯定是會有一定的 資料延遲 的。所以當剛插入就出現查詢的情況,可能查詢不出來。當然如果是插入者自己查詢,那麼可以直接從 主庫 中查詢出來,當然這個也是需要用程式碼來控制的。
3. 寫入更慢
主從複製 主要是針對 讀遠大於寫 或者對 資料備份實時性 要求較高的系統中。因為 主伺服器 在寫中需要更多操作,而且 只有一臺 可以寫入的 主庫,所以寫入的壓力並不能被分散。
主從複製的前提條件
-
主從伺服器 作業系統版本 和 位數 一致。
-
主資料庫和從資料庫的 版本 要一致。
-
主資料庫和從資料庫中的 資料 要一致。
-
主資料庫 開啟 二進位制日誌,主資料庫和從資料庫的
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
主資料庫 和 從資料庫 的容器建立成功。
分別配置 主資料庫 和 從資料庫 的連線資訊如下:
- 主資料庫
- 從資料庫
6. 配置從資料庫
檢查從庫的起始狀態
$ show master status;
複製程式碼
如圖所示,從資料庫處於 未同步複製狀態。
檢查主庫的狀態
$ show master status;
複製程式碼
記錄 主資料庫 binary-log
的 檔名稱 和 資料同步起始位置。
- File: replicas-mysql-bin.000003
- Position: 154
從庫配置主庫資訊
在 從資料庫 上執行 主資料庫 的相關配置 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
複製程式碼
進一步檢查 從資料庫 的狀態資訊,兩者已經進行 資料同步 關聯。
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;
複製程式碼
主資料庫 和 從資料庫 的 資料處於 同步狀態,主從複製叢集搭建完成。
MySQL的複製型別
基於語句的複製
主伺服器上面執行的語句在從伺服器上面再執行一遍,在 MySQL-3.23
版本以後支援。
問題:時間上可能不完全同步造成偏差,執行語句的使用者也可能是不同一個使用者。
基於行的複製
把主伺服器上面改變後的內容直接複製過去,而不關心到底改變該內容是由哪條語句引發的,在 MySQL-5.0
版本以後引入。
問題:比如一個工資表中有一萬個使用者,我們把每個使用者的工資+1000,那麼基於行的複製則要複製一萬行的內容,由此造成的開銷比較大,而基於語句的複製僅僅一條語句就可以了。
混合型別的複製
MySQL
預設使用 基於語句的複製,當 基於語句的複製 會引發問題的時候就會使用 基於行的複製,MySQL
會自動進行選擇。
歡迎關注公眾號: 零壹技術棧
本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。