在 Docker 中使用 mysql 的一些技巧


  • 啟動到后台:  docker-compose start

  • docker-composer 執行命令: entrypoint: pwd
  app:
    build: ./app
    working_dir: /app
    volumes:
      - ./app:/app
      - ~/.m2:/root/.m2
    expose:
      - "8080"
    depends_on:
      - nginx
      - mysql
    entrypoint: pwd

 

 

今天我寫一點在 Docker 容器中使用 MYSQL 的 tips.
要不要在生產環境使用 Docker 運行數據庫這么深奧的問題,等我踩足夠的坑再來寫吧。
但是至少在開發和測試環境你可以用 docker 管理數據庫啊。

Compose file

先貼一個我常用的 docker-compose 片段,后邊進行詳細的解釋。這是日常使用的狀態,此處省略了別的服務。

version: '2' services: mysql: image: mysql:5.7.16 ports: - ${DB_PORT}:3306 environment: - TZ=Asia/Shanghai command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./mysql_data:/var/lib/mysql restart: unless-stopped

版本

一定要鎖定鏡像到最小的版本,因為mysql鏡像升級后需要你手動在容器中執行命令去 mysql-upgrade,否則很久之后,你才發現有的數據已經損壞了。
實在想升級,升級步驟如下:

  • 如果是用 docker run 啟動的,那么停掉再啟動個新的。如果是用 docker-compose 啟動的,直接改版本號 pull 鏡像重新 up。

  • 在新的版本啟動后執行 docker exec -it 你的容器名稱或id mysql-upgrade

端口

如果想在外部通過工具訪問,需要將3306端口映射到host上的一個端口,不准備外部訪問的環境則不必。
一般來說開發和測試環境還是經常需要登到數據庫上查看的。

時區

添加環境變量 TZ 讓mysql用你的默認時區啟動。
這是因為 mysql 的基礎鏡像是 debian, 這個環境變量可以聲明 debian 的時區,然后被 mysql 繼承。

字符編碼

mysql 的鏡像默認編碼是 latin1 這可不行,在中國我們一般都用 UTF8 。
一般我們要是在主機上配置 mysql 的話,是去修改配置文件。但使用容器時映射進去一個配置文件是很復雜的。
於是我們有個簡單的辦法,mysql 接受很多 flag 通過啟動時傳入。其中就有聲明服務器默認編碼的。
我們的 command 命令就是給 mysql 在啟動時加了兩個參數。

存儲

容器中有需要持久化存儲的內容時就會有點麻煩。一般有兩種方案,一種是映射主機的一個目錄,一種是利用數據卷。
在很長時間的使用中,我總結出了這個比較方便的辦法。

  • 因為 docker-compose 有個潛規則就是大家一般都在有 compose 文件那個目錄執行命令。

  • 於是我們做一個以環境名稱命名的文件夾,里邊是 compose 文件,.env 文件,和各種需要持久化的文件夾。

  • 在 compose 文件中,我們映射文件夾用相對目錄。

  • 最后,這個文件夾就是一個整體,只需要把它拷貝在任何機器任何地方都可以啟動這個環境。

初始化

mysql 容器在首次啟動的時候,必須指定一個root密碼才能啟動,指定的方式是聲明環境變量 MYSQL_ROOT_PASSWORD 。
一旦在指定的數據文件夾發現已經存在庫的時候,這個參數就會被忽略掉。
所以我們只需要在第一次啟動的時候加上,后面有了數據后都去掉就好了。

導入導出

在容器中運行的 mysql 該怎么導入導出數據或結構呢?照這么做吧:

# Backup docker exec CONTAINER /usr/bin/mysqldump -u root --password=root DATABASE > backup.sql # Restore docker exec -i CONTAINER /usr/bin/mysql -u root --password=root DATABASE < backup.sql

就這么多吧,還有什么 Tips ,歡迎大家補充。

 

測試創建一個docker-compose.yml測試

以下配置了外部數據卷、外部配置文件、外部初始化文件(文件名必須以.sh或者.sql結尾)
這樣配置之后,數據庫本地直接連接得上去,而且使用的是你配置的賬號密碼。

version: '3' services:  db:  image: 'mysql/mysql-server:5.7'  restart: always  container_name: mysql  volumes:  - data:/var/lib/mysql  - ./mysql/config/my.cnf:/etc/my.cnf  - ./mysql/init:/docker-entrypoint-initdb.d/  ports:  - '3306:3306' volumes:  data:  driver: local 

/mysql/config/my.cnf

[mysqld]
user=mysql
default-storage-engine=INNODB
character-set-server=utf8
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8

/mysql/init/init.sql

CREATE USER 'luna'@'%' IDENTIFIED BY 'pwdluna'; GRANT All privileges ON *.* TO 'luna'@'%';



使用DockerCompose搭建MySQL高可用集群,並平滑遷移

!!!由於MySQL官方驅動還不支持Group Replication,因此當前只是服務端可用,客戶端驅動還需要等待新版本。

本文描述如何使用Docker+DockerCompose來部署一個MySQL的高可用集群。

此集群由3個MySQL實例組成,一個Master節點,2個Secondary節點。Master可讀寫,Secondary可讀。集群之間會自動同步數據。Master失效剩余的Secondary會自動選舉Master。

  • 請准備三台Linux VM(Ubuntu14.04),最好是異地的
  • 每台VM上請部署docker

由於公司內部網絡隔離,很多地址需要從公司內鏡像網站下載。請注意,某些配置步驟在可以直連外網的情況下並不需要。

配置Docker環境(每台VM)

  1. 在配置文件/etc/default/docker中DOCKER_OPTS選項添加--insecure-registry hub.witcloud.huawei.com,並重啟docker服務

  2. 執行apt-get install python-pip

  3. 配置pip公司內網鏡像

    在~/.pip/目錄下增加pip.conf文件 然后編輯其內容為: [global] trusted-host=rnd-mirrors.huawei.com index-url=http://rnd-mirrors.huawei.com/pypi/simple/ 
  4. 安裝docker-compose

    pip install docker-compose
    

部署完成后就可以使用docker-compose來進行鏡像的下載和容器的啟動了。

使用Docker部署MySQL(每台VM)

首先我們要編寫DockerCompose文件,用於配置MySQL鏡像的啟動。

mkdir /home/docker/mysql -p
vim /home/docker/mysql/docker-compose.yml

注意:因為數據庫容量未來可能較大,因此最好將大容量磁盤掛載到/data目錄。

version: '2' services:  mysql:  network_mode: "host"  environment:  MYSQL_ROOT_PASSWORD: "blu3Spoon55"  image: hub.witcloud.huawei.com/it-ark/mysql  restart: unless-stopped  volumes:  - "/data/mysql/db:/var/lib/mysql"  - "/data/mysql/conf:/etc/mysql/conf.d" 

MYSQL_ROOT_PASSWORD為管理員密碼,請自己設置一個強密碼。

配置Group Replication節點(每台VM)

需要注意的差異如下:

  1. server_id每台VM不同
    節點1: 1
    節點2: 2
    節點3: 3
    
  2. loose-group_replication_local_address每台VM不同
    節點1: 10.183.22.167:24901 節點2: 100.112.98.176:24901 節點3: 10.167.117.41:24901 
  3. bind-addressreport_host綁定為各VM的IP地址

我們使用配置文件來對集群進行配置:

mkdir /data/mysql/conf -p
vim /data/mysql/conf/ha.cnf

文件內容:

[mysqld]  
#Encoding collation-server = utf8_unicode_ci init-connect='SET NAMES utf8' character-set-server = utf8 #Replication Framework gtid_mode=ON enforce_gtid_consistency=ON master_info_repository=TABLE relay_log_info_repository=TABLE binlog_checksum=NONE log_slave_updates=ON log_bin=binlog binlog_format=ROW # Host specific replication configuration server_id=1 bind-address="10.183.22.167" report_host="10.183.22.167" loose-group_replication_local_address ="10.183.22.167:24901" #Group Replication transaction_write_set_extraction=XXHASH64 loose-group_replication_group_name="9a261783-7436-4df7-be2c-97fc7b37eb85" loose-group_replication_start_on_boot=on loose-group_replication_group_seeds="10.183.22.167:24901,100.112.98.176:24901,10.167.117.41:24901" loose-group_replication_bootstrap_group=off loose-group_replication_ip_whitelist="10.183.22.167,100.112.98.176,10.167.117.41,127.0.0.1/8" 

依次啟動每個節點,進行數據庫內部配置

  1. 啟動節點數據庫

    docker-compose up -d
    
  2. 使用數據庫工具鏈接節點

  3. 僅針對節點2,3,第一個節點不用:清理Docker容器內部產生的binlog,從完全干凈的狀態進行集群同步

    RESET MASTER ; 
  4. 創建group replication所需要的用戶

    SET SQL_LOG_BIN =0; CREATE USER rpl_user@'%' IDENTIFIED BY 'rpl_pass'; GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; FLUSH PRIVILEGES ; SET SQL_LOG_BIN =1; CHANGE MASTER TO MASTER_USER ='rpl_user', MASTER_PASSWORD ='rpl_pass' FOR CHANNEL 'group_replication_recovery'; 
  5. 安裝組復制插件

    INSTALL PLUGIN group_replication SONAME 'group_replication.so'; 

    檢查是否插件是否啟用:

    mysql> SHOW PLUGINS;
    +----------------------------+----------+--------------------+----------------------+-------------+
    | Name | Status | Type | Library | License | +----------------------------+----------+--------------------+----------------------+-------------+ | binlog | ACTIVE | STORAGE ENGINE | NULL | PROPRIETARY | (...) | group_replication | ACTIVE | GROUP REPLICATION | group_replication.so | PROPRIETARY | +----------------------------+----------+--------------------+----------------------+-------------+ 
  6. 啟動group replication

    • 節點1:
      SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF; 
    • 節點2/3
      START GROUP_REPLICATION; 
  7. 僅針對節點1: 增加一些測試數據,用於測試節點2和節點3是否同步了數據

    CREATE DATABASE test; use test; CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL); INSERT INTO t1 VALUES (1, 'mysql集群測試'); 

客戶端使用

!!!由於MySQL官方驅動還不支持Group Replication,因此當前只是服務端可用,客戶端驅動還需要等待新版本。

官方ConnectJ支持使用Replication,以支持MySQL Group Replication。

只需要在連接字符串中配置即可:

jdbc:mysql:loadbalance://100.112.98.176:3306,10.183.22.167:3306,10.167.117.41:3306 

應用程序代碼無需修改,驅動會自動判斷可用的Master。

Master/Secondary異步延時

由於Master/Secondary之間的數據同步存在一定延時,可能導致先寫入后讀取的時候,讀取不到數據。

舉例說明:

  1. 線程A在Master 1上插入一條數據,id為6217614201566007296
  2. 線程A把此ID(6217614201566007296)給線程B
  3. 線程B在Secondary 1上通過此ID(6217614201566007296)讀取數據
  4. 但是此時數據還未從Master1同步到Secondary 1
  5. 線程B讀取數據為空

因此,在這種情況下,由於寫入到讀取之間可能存在延時,那么在寫入之后的處理階段(比如線程B),需要增加重試或者延時,來等待數據同步。
這也是分布式數據庫最終一致性帶來的問題。

參考資料:

  1. MySQL Group Replication官方文檔
  2. 細細探究MySQL Group Replication — 配置維護故障處理全集
  3. 使用ConnectJ配置負載均衡
  4. 數據庫分庫分表(二)Twitter-Snowflake(64位分布式ID算法)分析與JAVA實現
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM