利用 Docker 快速實現(xiàn) MySQL binlog 主從備份

Docker

Intro

主從備份是容災(zāi)的一種手段, 模擬主從備份可以有下面幾種方式:

  • 不差錢方式, 買幾臺主機測試, 這種方式也比較接近線上環(huán)境.
  • 通過創(chuàng)建幾臺虛擬機來模擬. 這種方式對本機性能要求相對較高. 相對不差錢可以選這種方式, 但安裝幾臺虛擬機也不是一件效率高的事.
  • 在一臺主機上創(chuàng)建多個數(shù)據(jù)庫實例. 缺點是環(huán)境無法隔離, 需要額外加多一些配置
  • 通過 Docker-compose 直接創(chuàng)建多個數(shù)據(jù)庫容器, 暴露端口訪問即可.

binlog 是MySQL數(shù)據(jù)庫的二進制日志,用于記錄用戶對數(shù)據(jù)庫操作的SQL語句(不包括 SELECT),可以在配置文件開啟备蚓,也可以在 MySQL 客戶端開啟. 可以在客戶端鍵入show plugins; 查看 binlog 是否已安裝開啟( Active )

+----------------------------+----------+--------------------+---------+---------+
| Name                       | Status   | Type               | Library | License |
+----------------------------+----------+--------------------+---------+---------+
| binlog                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| mysql_native_password      | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| sha256_password            | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| PERFORMANCE_SCHEMA         | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MEMORY                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| CSV                        | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |

環(huán)境準備

0.1 測試環(huán)境

必須安裝有 dockerdocker-compose 用于構(gòu)建容器環(huán)境, 本測試在 Ubuntu 16.04 及下列版本下進行, 使用其他版本可能會有使用差異.

docker-compose 1.25.4
docker 19.03.6

有關(guān)安裝的細節(jié), 請搜索相關(guān)關(guān)鍵詞, 或者直接根據(jù) Docker 官方文檔 進行安裝

0.2 Docker 加速

由于眾所周知的原因, 拉取鏡像時可能會很慢, 推薦設(shè)置國內(nèi)的鏡像源進行加速
Ubuntu/Centos/Debian 下修改或創(chuàng)建此文件 /etc/docker/daemon.json
示例文件內(nèi)容如下, 可以自由添加鏡像源. 鏡像源有可能會宕機, 鏡像源測試請參閱docker-registry-cn-mirror-test

{
    "registry-mirrors":[
        "https://dockerhub.azk8s.cn",
        "https://docker.mirrors.ustc.edu.cn",
        "https://reg-mirror.qiniu.com"
    ]
  }

一. Docker 文件準備

1.1 文件目錄

  • Dockerfile 是一個文本文件, 只需要 touch Dockerfile 創(chuàng)建即可.
  • docker-compose.yml 是用于運行多個 Docker 容器的配置文件, 使用 yaml 語言.

如只準備測試一主一從, 那么移除 slave02 目錄, 添加多個從服務(wù)器則相應(yīng)增加文件夾.

├── docker-compose.yml
├── master
│   ├── Dockerfile
│   └── my.cnf
├── slave01
│   ├── Dockerfile
│   └── my.cnf
└── slave02
    ├── Dockerfile
    └── my.cnf

1.2 docker-compose 文件及解釋

  • environment
    在創(chuàng)建 MySQL 密碼時, 測試用途用 root 沒問題, 其他時候記得創(chuàng)建復(fù)雜密碼, 至少可以使用 uuidgen 命令生成.
    支持在創(chuàng)建時同時創(chuàng)建一個數(shù)據(jù)庫, 創(chuàng)建多個或進行其他數(shù)據(jù)初始化, 建議依靠外部 SQL 文件.
  • links
    這個不是推薦的配置方式, 不利于擴展, 但在此處我們只是用于測試. 可以自由添加你要的從服務(wù)器名稱, 用于容器間的連接. 更推薦配置 networks
  • ports
    冒號左邊為暴露的端口, 右邊為容器內(nèi)部的端口號, 在不配置網(wǎng)絡(luò)的情況下(此時默認為 127.0.0.1), 為了避免端口沖突, 必須使暴露的端口號不一致.
version: '2' 
services:
  mysql-master: 
    build:
      context: ./                      # 聲明構(gòu)建的文件夾
      dockerfile: master/Dockerfile    # 聲明 Docker 文件目錄
    environment: # 環(huán)境變量, 支持數(shù)組或列表方式
      - "MYSQL_ROOT_PASSWORD=root"
      - "MYSQL_DATABASE=db0" # 初始創(chuàng)建的數(shù)據(jù)庫
    links:
      - mysql-slave01
      - mysql-slave02
    ports:
      - "33065:3306" 
    restart: always
    hostname: mysql-master

  mysql-slave01:
    build:
      context: ./
      dockerfile: slave/Dockerfile
    environment:
      - "MYSQL_ROOT_PASSWORD=6954D5F0"
      - "MYSQL_DATABASE=db0"
    ports:
      - "33066:3306"
    restart: always
    hostname: mysql-slave01

  mysql-slave02:
    build:
      context: ./
      dockerfile: slave02/Dockerfile
    environment:
      - "MYSQL_ROOT_PASSWORD=6954D5F0"
      - "MYSQL_DATABASE=db0"
    ports:
      - "33067:3306"
    restart: always
    hostname: mysql-slave02

1.3 Dockerfile 文件及解釋

  • FROM指定了基礎(chǔ)鏡像, 可以根據(jù)需求更改 MySQL 鏡像版本
  • COPY
    將源文件復(fù)制到目標容器, 從服務(wù)器相應(yīng)地創(chuàng)建 Dockerfile, 修改源文件位置. 也可以使用 ADD 這個更高級的復(fù)制命令, 但沒必要.
FROM mysql:5.7.17
COPY ./master/my.cnf /etc/mysql/my.cnf

二. MySQL 配置文件準備

2.1 Master 節(jié)點配置

# master/my.cnf
[mysqld]
## 設(shè)置server_id萍桌,注意要唯一
server_id=100  
## 復(fù)制過濾:也就是指定哪個數(shù)據(jù)庫不用同步(mysql庫一般不同步)
binlog-ignore-db=mysql  
## 開啟二進制日志功能散吵,可以隨便取孔轴,最好有含義
log-bin=replicas-mysql-bin  
## 為每個session分配的內(nèi)存蓬衡,在事務(wù)過程中用來存儲二進制日志的緩存
binlog_cache_size=1M  
## 主從復(fù)制的格式(mixed,statement,row杀糯,默認格式是statement)
binlog_format=mixed  
## 二進制日志自動刪除/過期的天數(shù)扫俺。默認值為0,表示不自動刪除固翰。
expire_logs_days=7  
## 跳過主從復(fù)制中遇到的所有錯誤或指定類型的錯誤狼纬,避免slave端復(fù)制中斷。
## 如:1062錯誤是指一些主鍵重復(fù)骂际,1032錯誤是因為主從數(shù)據(jù)庫數(shù)據(jù)不一致
slave_skip_errors=1062

2.2 Slave 節(jié)點配置

Slave 節(jié)點的配置與 Master 相似, 但每個節(jié)點的 server_id 必須不同, 此外增加了 relay_log 中繼日志的配置以及只讀的設(shè)置

[mysqld]
## 設(shè)置server_id疗琉,注意要唯一
server_id=101 
# ... 省略配置
## relay_log配置中繼日志
relay_log=replicas-mysql-relay-bin  
## log_slave_updates表示slave將復(fù)制事件寫進自己的二進制日志
log_slave_updates=1  
## 防止改變數(shù)據(jù)(除了特殊的線程)
read_only=1 

三. 構(gòu)建容器并運行

進入有 docker-compose.yml 的目錄, 執(zhí)行以下命令
該命令十分強大,它將嘗試自動完成包括構(gòu)建鏡像歉铝,(重新)創(chuàng)建服務(wù)盈简,啟動服務(wù),并關(guān)聯(lián)服務(wù)相關(guān)容器的一系列操作, -d 表示后臺運行鏡像.

docker-compose up -d

之后執(zhí)行docker ps 查看正在運行的鏡像, 如果是一主一從, 可以看到至少兩個正在運行的鏡像

$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                     NAMES
ef799b7d8cf8        mstest_mysql-master   "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes        0.0.0.0:33065->3306/tcp   mstest_mysql-master_1
9d7ea93b7a85        mstest_mysql-slave    "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes        0.0.0.0:33066->3306/tcp   mstest_mysql-slave_1

鍵入 docker exec -it [name/id] /bin/bash 進入容器, 可以是容器名稱也可以是容器 id, 如下方示例:

docker exec -it mysql-master_1 /bin/bash

四. 配置主從

可以直接進入容器再進入 mysql 配置, 也可以不進入, 直接在終端鍵入下方命令, port 就是 docker-compose.xml 設(shè)置的端口號, 例如前面 master33065

mysql -uroot -p -P[port] -h127.0.0.1

4.1 獲取主節(jié)點狀態(tài)

鍵入 show master status; 記住當前 File 的名稱和 Position, 這是從節(jié)點進行 binlog 復(fù)制找點用的.

mysql> show master status
    -> ;
+---------------------------+----------+--------------+------------------+-------------------+
| File                      | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------------+----------+--------------+------------------+-------------------+
| replicas-mysql-bin.000003 |      154 |              | mysql            |                   |
+---------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec

4.2 開啟從節(jié)點復(fù)制

這里設(shè)置復(fù)制主節(jié)點的相關(guān)信息, 在前面文件用的是 root 密碼,因此這里也是 root 用戶, 將MASTER_LOG_FILEMASTER_LOG_POS 填上相應(yīng)信息

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

接著啟動復(fù)制.

  • 鍵入start slave;
  • 鍵入show slave status\G;查看是否啟用成功, 關(guān)注Slave_IO_RunningSlave_SQL_Running 是否為 Yes
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G;
            ...
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            ...

同樣地, 如果有多個 Slave 節(jié)點, 就這一步多做幾次.

4.3 驗證是否成功

回到 Master 節(jié)點, 創(chuàng)建一個數(shù)據(jù)庫 或者 往已經(jīng)創(chuàng)建好的 db0 寫入數(shù)據(jù),

mysql> create database db1;

回到 Slave 節(jié)點, 查看兩邊是否同步.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db0                |
| db1                |

五. 后話——另一種主從復(fù)制 GTID

GTID 自 MySQL 5.6.MySQL 5.6.5 便引入了太示,中文叫全局事務(wù) ID(Global Transaction ID)

在本文的基于二進制日志復(fù)制中柠贤,從庫需要告知主庫要從哪個偏移量(就是 Log File 的 Position)進行增量同步,如果指定錯誤會造成數(shù)據(jù)的遺漏类缤,從而造成數(shù)據(jù)的不一致臼勉。

但有了 GTID,發(fā)生主備切換時餐弱,MySQL 的其它從庫可以自動在新主庫上找到正確的復(fù)制位置宴霸,這大大簡化了復(fù)雜復(fù)制拓撲下集群的維護囱晴,也減少了人為設(shè)置復(fù)制位置發(fā)生誤操作的風(fēng)險。另外瓢谢,基于 GTID 的復(fù)制還可以忽略已經(jīng)執(zhí)行過的事務(wù)畸写。

參考

  1. Docker Compose搭建MySQL主從復(fù)制集群
  2. GTID Concept - MySQL
  3. Docker 從入門到實踐 - Compose 命令說明

公眾號:程序員的碎碎念
Github:github.com/FesonX

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市恩闻,隨后出現(xiàn)的幾起案子艺糜,更是在濱河造成了極大的恐慌,老刑警劉巖幢尚,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件破停,死亡現(xiàn)場離奇詭異,居然都是意外死亡尉剩,警方通過查閱死者的電腦和手機真慢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來理茎,“玉大人黑界,你說我怎么就攤上這事≡砹郑” “怎么了朗鸠?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長础倍。 經(jīng)常有香客問我烛占,道長,這世上最難降的妖魔是什么沟启? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任忆家,我火速辦了婚禮,結(jié)果婚禮上德迹,老公的妹妹穿的比我還像新娘芽卿。我一直安慰自己,他們只是感情好胳搞,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布卸例。 她就那樣靜靜地躺著,像睡著了一般肌毅。 火紅的嫁衣襯著肌膚如雪币厕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天芽腾,我揣著相機與錄音,去河邊找鬼页衙。 笑死摊滔,一個胖子當著我的面吹牛阴绢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艰躺,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼呻袭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腺兴?” 一聲冷哼從身側(cè)響起左电,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎页响,沒想到半個月后篓足,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡闰蚕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年栈拖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片没陡。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡涩哟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盼玄,到底是詐尸還是另有隱情贴彼,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布埃儿,位于F島的核電站器仗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蝌箍。R本人自食惡果不足惜青灼,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妓盲。 院中可真熱鬧杂拨,春花似錦、人聲如沸悯衬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筋粗。三九已至策橘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娜亿,已是汗流浹背丽已。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留买决,地道東北人沛婴。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓吼畏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嘁灯。 傳聞我的和親對象是個殘疾皇子泻蚊,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355