隨着應用業務數據不斷的增大,應用的 響應速度不斷降低,在檢測過程當中咱們不難發現大多數的請求都是 查詢操做。此時,咱們能夠將數據庫擴展成 主從複製模式,將 讀操做 和 寫操做 分離開來,多臺數據庫 分攤請求,從而 減小單庫 的 訪問壓力,進而應用獲得優化。mysql
MySQL 5.6
開始主從複製有兩種方式:基於日誌(binlog
)和 基於 GTID
(全局事務標示符)。sql
本文只涉及基於日誌 binlog
的 主從配置。docker
MySQL
同步操做經過 3
個線程實現,其基本步驟以下:數據庫
主服務器 將數據的更新記錄到 二進制日誌(Binary log
)中,用於記錄二進制日誌事件,這一步由 主庫線程 完成;編程
從庫 將 主庫 的 二進制日誌 複製到本地的 中繼日誌(Relay log
),這一步由 從庫 I/O
線程 完成;後端
從庫 讀取 中繼日誌 中的 事件,將其重放到數據中,這一步由 從庫 SQL
線程 完成。緩存
一般狀況下,會使用 主服務器 對數據進行 更新、刪除 和 新建 等操做,而將 查詢 工做落到 從庫 頭上。安全
能夠將主服務器上的數據同步到 異地從服務器 上,極大地提升了 數據安全性。bash
數據庫的複製功能實現了 主服務器 與 從服務器間 的數據同步,一旦主服務器出了 故障,從服務器當即擔當起主服務器的角色,保障系統持續穩定運做。服務器
主從複製 模式支持 2
種擴展方式:
向上擴展或者 縱向擴展,主要是提供比如今服務器 性能更好 的服務器,好比 增長 CPU
和 內存 以及 磁盤陣列等,由於有多臺服務器,因此可擴展性比單臺更大。
向外擴展或者 橫向擴展,是指增長 服務器數量 的擴展,這樣主要能分散各個服務器的壓力。
搭建主從確定會增長成本,畢竟一臺服務器和兩臺服務器的成本徹底不一樣,另外因爲主從必需要開啓 二進制日誌,因此也會形成額外的 性能消耗。
從庫 從 主庫 複製數據確定是會有必定的 數據延遲 的。因此當剛插入就出現查詢的狀況,可能查詢不出來。固然若是是插入者本身查詢,那麼能夠直接從 主庫 中查詢出來,固然這個也是須要用代碼來控制的。
主從複製 主要是針對 讀遠大於寫 或者對 數據備份實時性 要求較高的系統中。由於 主服務器 在寫中須要更多操做,並且 只有一臺 能夠寫入的 主庫,因此寫入的壓力並不能被分散。
主從服務器 操做系統版本 和 位數 一致。
主數據庫和從數據庫的 版本 要一致。
主數據庫和從數據庫中的 數據 要一致。
主數據庫 開啓 二進制日誌,主數據庫和從數據庫的 server_id
在局域網內必須 惟一。
名稱 | 版本號 |
---|---|
Docker | 18.03.1-ce |
Docker Compose | 1.21.1 |
MySQL | 5.7.17 |
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
複製代碼
Dockerfile
FROM mysql:5.7.17
MAINTAINER harrison
ADD ./master/my.cnf /etc/mysql/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
複製代碼
Dockerfile
FROM mysql:5.7.17
MAINTAINER harrison
ADD ./slave/my.cnf /etc/mysql/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
複製代碼
進入 docker
目錄,運行 docker-compose
啓動命令。
$ docker-compose up -d
複製代碼
如圖所示,MySQL
主數據庫 和 從數據庫 的容器建立成功。
分別配置 主數據庫 和 從數據庫 的鏈接信息以下:
$ show master status;
複製代碼
如圖所示,從數據庫處於 未同步複製狀態。
$ show master status;
複製代碼
記錄 主數據庫 binary-log
的 文件名稱 和 數據同步起始位置。
在 從數據庫 上運行 主數據庫 的相關配置 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
複製代碼
進一步檢查 從數據庫 的狀態信息,二者已經進行 數據同步 關聯。
在 主數據庫 中建立一張測試數據表 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-3.23
版本之後支持。
問題:時間上可能不徹底同步形成誤差,執行語句的用戶也多是不一樣一個用戶。
把主服務器上面改變後的內容直接複製過去,而不關心到底改變該內容是由哪條語句引起的,在 MySQL-5.0
版本之後引入。
問題:好比一個工資表中有一萬個用戶,咱們把每一個用戶的工資+1000,那麼基於行的複製則要複製一萬行的內容,由此形成的開銷比較大,而基於語句的複製僅僅一條語句就能夠了。
MySQL
默認使用 基於語句的複製,當 基於語句的複製 會引起問題的時候就會使用 基於行的複製,MySQL
會自動進行選擇。
歡迎關注公衆號: 零壹技術棧
本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。