Docker--利用dockerfile搭建mysql主從集群和redis集群
搭建mysql主從集群
mysql主從同步的原理
==MySQL主從同步(Replication)是一種實現數據冗余和高可用性的技術,通過將主數據庫(Master)的變更操作同步到一個或多個從數據庫(Slave),實現數據的實時或準實時復制==。
為什么要用主從分離?
?讀寫分離,提高性能:主庫負責寫,從庫負責讀
?數據實時備份:主庫的數據實時存儲到從庫
?高可用HA:當有一個節點發生故障時,可以隨時切換
核心流程
主庫記錄變更日志(Binary Log)
? 主庫將所有數據變更操作(如INSERT、UPDATE、DELETE)記錄到二進制日志(Binary Log)中。
? Binary Log是二進制格式的文件,記錄了每個事務的SQL語句或行級變更。
從庫讀取主庫的日志
? 從庫通過I/O線程連接到主庫,并請求讀取Binary Log。
? 主庫的I/O線程將Binary Log的內容發送給從庫。
從庫重放日志(Relay Log)
? 從庫將接收到的Binary Log寫入本地的中繼日志(Relay Log)。
? 從庫的SQL線程讀取Relay Log,并按照順序執行其中的SQL語句,從而實現數據同步。
數據一致性保障
? 主庫和從庫通過日志的順序執行保證數據一致性。
? 異步復制模式下,從庫可能稍有延遲;半同步復制模式下,主庫會等待至少一個從庫確認接收日志。
主從分布架構圖
組件 | 作用 |
Binary Log | 主庫記錄所有數據變更的日志,是主從同步的核心。 |
I/O線程 | 從庫的線程,負責從主庫獲取Binary Log并寫入Relay Log。 |
SQL線程 | 從庫的線程,負責讀取Relay Log并執行其中的SQL語句。 |
Relay Log | 從庫本地存儲主庫Binary Log的中間日志,用于SQL線程重放。 |
==當主節點mysql接收到數據的時候,向binlog寫入事務,binlog通過多線程的讀取,發送到從節點,從節點先由IO線程接收,然后再寫入laylog中,之后讓laolog線程進行讀取,最后放入到從節點的mysql中==
主從同步的方式
異步復制(Asynchronous Replication)
主庫提交事務后立即返回,不等待從庫確認。
? 優點:性能高,延遲低。
? 缺點:從庫可能滯后,數據一致性較差。
半同步復制(Semi-Synchronous Replication)
==主庫提交事務后,至少等待一個從庫確認接收日志==。
? 優點:數據一致性更好。
? 缺點:性能略有下降。
全同步復制(Synchronous Replication)
==主庫提交事務后,等待所有從庫確認接收日志==。
? 優點:數據一致性更好。
? 缺點:性能較低。
增強半同步復制 (Rising-Semi-Synchronous Replication)
==對半同步復制做的一個改進,原理上幾乎是一樣的,主要是解決幻讀的問題==.
? 優點:數據一致性更好,解決幻讀問題
? 缺點:性能略有下降
主要配置
1.主庫配置
啟用Binary Log:
[mysqld] log-bin=mysql-bin server-id=1 # 唯一標識符
創建同步用戶(供從庫連接):
CREATE USER'repl'@'%'IDENTIFIED BY'password'; GRANT REPLICATION SLAVE ON *.* TO'repl'@'%';
2.從庫配置
指定主庫信息:
CHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='repl', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=120;
啟動同步:
START SLAVE;
3.驗證同步狀態
檢查從庫狀態:
SHOW SLAVE STATUSG;
實戰
創建對應目錄在這里插入圖片描述
編輯Master目錄下的Dockerfile:
FROM mysql:5.7.36 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
FROM mysql:5.7.36:這一行指定了Docker 鏡像的基礎鏡像。
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime:
? RUN 是 Dockerfile 中的一個指令,表示在構建鏡像時運行指定的命令。
? ln -sf 是創建符號鏈接(symbolic link)的命令:
? -s 表示創建符號鏈接(軟鏈接)。
? -f 表示如果目標文件已存在,則強制覆蓋。
? /usr/share/zoneinfo/Asia/Shanghai 是系統中的時區文件,表示中國上海時區(東八區)。
? /etc/localtime 是 Linux 系統中表示當前容器時區的文件。
這一行的作用是將 /etc/localtime 鏈接到 /usr/share/zoneinfo/Asia/Shanghai,從而將容器的時區設置為上海時區(UTC+8)。
編輯slave目錄下的Dockerfile:
FROM mysql:5.7.36 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY ./slave/slave.sql /docker-entrypoint-initdb.d
編輯slave.sql
change master to master_host='mysql-master', master_user='root',master_password='root',master_port=3306; start slave;
CHANGE MASTER TO語句:用于配置從庫連接主庫的相關信息。
參數說明:
? master_host=‘mysql-master’:
指定主庫的主機名或 IP 地址,這里的主庫名是 mysql-master。
? master_user=‘root’:
指定用于從庫連接主庫的用戶名,這里是 root。
? master_password=‘root’:
指定用于從庫連接主庫的密碼,這里是 root。
? master_port=3306:
指定主庫的端口號,這里是默認的 MySQL 端口 3306。
? 作用:
這部分語句告訴從庫如何連接到主庫,包括主庫地址、用戶名、密碼和端口號
START SLAVE語句:
? 用于啟動從庫的復制進程。
? 在執行 ==CHANGE MASTER TO== 配置后,從庫需要執行 START SLAVE; ==才能開始從主庫拉取數據并同步==
在主目錄mysqlcluster下創建docker-compose.yml文件進行編輯:
name: mysqlcluster services: mysql-master: build: context: ./ dockerfile: ./master/Dockerfile image: mysqlmaster:1.0 restart: always container_name: mysql-master volumes: - ./mastervarlib:/var/lib/mysql ports: -8080:3306 environment: MYSQL_ROOT_PASSWORD: root privileged:true command: ['--server-id=1', '--log-bin=master-bin', '--binlog-ignore-db=mysql', '--binlog_cache_size=256M', '--binlog_format=mixed', '--lower_case_table_names=1', '--character-set-server=utf8', '--collation-server=utf8_general_ci'] mysql-slave: build: context: ./ dockerfile: ./slave/Dockerfile image: mysqlslave:1.0 restart: always container_name: mysql-slave volumes: - ./slavevarlib:/var/lib/mysql ports: -8081:3306 environment: MYSQL_ROOT_PASSWORD: root privileged:true command: ['--server-id=2', '--relay_log=slave-relay', '--lower_case_table_names=1', '--character-set-server=utf8', '--collation-server=utf8_general_ci'] depends_on: - mysql-master mysql-slave2: build: context: ./ dockerfile: ./slave/Dockerfile image: mysqlslave:1.0 restart: always container_name: mysql-slave2 volumes: - ./slavevarlib2:/var/lib/mysql ports: -8082:3306 environment: MYSQL_ROOT_PASSWORD: root privileged:true command: ['--server-id=3', '--relay_log=slave-relay', '--lower_case_table_names=1', '--character-set-server=utf8', '--collation-server=utf8_general_ci'] depends_on: - mysql-master
mysql-master:
?restart:指定容器的重啟策略。
always 表示無論容器因何種原因退出,Docker 都會嘗試重新啟動它。
?volume:用于將主機目錄掛載到容器中
./mastervarlib是主機上的目錄,/var/lib/mysql是容器中 MySQL 默認的數據存儲路徑。
作用:將 MySQL 的數據存儲在主機上,確保容器重啟或刪除后數據不會丟失。
?envirnment:設置環境變量
MYSQL_ROOT_PASSWORD: root 指定 MySQL 的 root 用戶密碼為 root。
privileged:設置容器以特權模式運行
?command:
設置 MySQL 服務器的唯一 ID,主從復制中必須指定,且每個服務器的 ID 必須唯一
啟用二進制日志(Binary Log),日志文件前綴為 master-bin,記錄主庫的寫操作
指定忽略mysql系統數據庫的二進制日志記錄
設置二進制日志緩存的大小為256MB
設置二進制日志的格式為mixed
設置表名不區分大小寫
設置服務器的默認字符集為utf8
設置服務器的默認排序規則為utf8_general_ci
mysql-slave1:
?depends-on:指定服務之間的依賴關系
mysql-slave 服務依賴于 mysql-master 服務
確保在啟動 mysql-slave 之前,mysql-master 服務已經啟動
創建出鏡像并創建啟動對應的容器:
docker compose build docker compose up -d
查看對應狀態
docker ps

運行主數據庫查看運轉
dockerexec-it mysql-master bash
連上主庫,查看數據庫可以看到運行正常
mysql -u root -p

連接上從庫,通過命令查看
SHOW MASTER STATUSG SHOW SLAVE STATUSG

主庫創建一個數據庫
create databasetest;

從庫上查看,可以看到也有了對應的test數據庫:

主庫上創建表,插入數據:
mysql> usetest; Database changed mysql> create tableusers(sno int,sname varchar(20)); Query OK, 0 rows affected (0.03 sec) mysql> insert into usersvalues (1,'xixi'); Query OK, 1 row affected (0.02 sec) mysql> insert into usersvalues (2,'haha'); Query OK, 1 row affected (0.01 sec)
在從表上查看
mysql> usetest; Reading table informationforcompletion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +----------------+ | Tables_in_test | +----------------+ |users | +----------------+ 1 rowinset(0.00 sec) mysql>select* fromusers; +------+-------+ | sno | sname | +------+-------+ | 1 | xixi | | 2 | haha | +------+-------+ 2 rowsinset(0.00 sec)
至此完成了mysql主從集群的部署;
docker compose down
搭建Redis集群
==Redis 集群是 Redis 提供的一種分布式解決方案,旨在通過將數據分布到多個節點上來實現水平擴展和高可用性==。它解決了單機 Redis 在存儲容量、讀寫性能和容錯能力上的限制,適用于大規模、高并發的應用場景。
核心特性
數據分片(Sharding)
? Redis 集群將數據分散到多個節點上,每個節點負責一部分數據。
? 數據分片基于哈希槽(Hash Slot),共有 16384 個哈希槽,每個鍵通過哈希算法映射到一個哈希槽,再分配到具體節點。
高可用性
? 每個主節點(Master)可以有多個從節點(Slave)。
? 當主節點故障時,集群會自動將從節點提升為主節點(故障轉移),確保服務可用。
水平擴展
? 可以通過增加節點來擴展集群的存儲容量和性能。
? 集群支持動態添加或移除節點,無需停機。
無中心架構
?Redis集群沒有中心節點,所有節點平等,避免了單點故障。
下載源碼壓縮包
首先,我們要去官網,找到源碼的下載鏈接
redis-7.0.15 版本的鏈接
組成
?主節點(Master):負責處理讀寫請求和存儲數據。
?從節點(Slave):復制主節點的數據,用于故障轉移和只讀請求。
?哈希槽(Hash Slot):數據分片的基本單位,共有 16384 個。
準備目錄
mkdir/data/ahri/dockerfile/rediscluster/redis
設置redis.conf
==在redis目錄下創建一個redis.conf進行配置==
#表示前臺運行 daemonize no #端口 port 6379 #持久化 dir/data/redis #啟用集群 cluster-enabledyes #集群參數配置 cluster-config-file nodes.conf #集群超時時間 cluster-node-timeout 5000 #密碼配置 requirepass 123456 #主節點密碼配置 masterauth 123456 #表示遠端可以連接 bind* -::*
編輯 Dockefile
==在redis目錄下創建Dockerfile文件進行編輯==
注:centos:7 已經停止維護了,所以這里使用了ubuntu
# 第一階段:構建階段 FROM ubuntu:22.04 AS buildstage # 更新包列表并安裝必要的構建工具和依賴 RUN apt-get update && apt-get install -y build-essential wget gcc g++ make &&rm-rf /var/lib/apt/lists/* # 下載 Redis 源碼和配置文件 #wget https://download.redis.io/releases/redis-7.0.15.tar.gz ADD redis-7.0.15.tar.gz / ADD redis.conf /redis/ # 切換到 Redis 源碼目錄并編譯 WORKDIR /redis-7.0.15 RUN make # 將 Redis 可執行文件移動到指定目錄 RUNmv/redis-7.0.15/src/redis-server /redis/ &&mv/redis-7.0.15/src/redis-cli /redis/ ENTRYPOINT ["/redis/redis-server","/redis/redis.conf"] # 第二階段:運行階段 FROM ubuntu:22.04 RUNmkdir-p /data/redis &&mkdir-p /redis COPY --from=buildstage /redis /redis EXPOSE 6379 ENTRYPOINT ["/redis/redis-server","/redis/redis.conf"]
測試
==通過docker build創建鏡像進行測試==
docker build -t myredis:v1.0 .
嘗試啟動一個容器進行測試
docker run -d --name myredis --rmmyredis:1.0 416541b280d91f04e80c7df864ed097d5471b26bf93a5c82b090d458402217f9

測試成功,釋放資源
docker stop myredis
編寫Docker-compose.yml
name: rediscluster services: redis01: image: myredis:1.0 build: ./redis ports: - 6379:6379 container_name: redis01 healthcheck: test: /redis/redis-cli ping interval: 10s timeout: 5s retries: 10 redis02: image: myredis:1.0 container_name: redis02 healthcheck: test: /redis/redis-cli ping interval: 10s timeout: 5s retries: 10 redis03: image: myredis:1.0 container_name: redis03 healthcheck: test: /redis/redis-cli ping interval: 10s timeout: 5s retries: 10 redis04: image: myredis:1.0 container_name: redis04 healthcheck: test: /redis/redis-cli ping interval: 10s timeout: 5s retries: 10 redis05: image: myredis:1.0 container_name: redis05 healthcheck: test: /redis/redis-cli ping interval: 10s timeout: 5s retries: 10 redis06: image: myredis:1.0 container_name: redis06 healthcheck: test: /redis/redis-cli ping interval: 10s timeout: 5s retries: 10 redis07: image: myredis:1.0 container_name: redis07 entrypoint: ["/redis/redis-cli", "--cluster", "create", "redis01:6379", "redis02:6379", "redis03:6379", "redis04:6379", "redis05:6379", "redis06:6379", "--cluster-replicas", "1", "-a", "123456", "--cluster-yes"] depends_on: redis01: condition: service_healthy redis02: condition: service_healthy redis03: condition: service_healthy redis04: condition: service_healthy redis05: condition: service_healthy redis06: condition: service_healthy
測試
==通過下面命令檢查配置文件是否書寫格式錯誤==
docker compose config
對 容器進行啟動
docker compose up -d查看容器的狀態

查看07日志是否創建成功
root@VM-8-12-ubuntu:/data/ahri/dockerfile/rediscluster# docker logs -f redis07 Warning: Using a password with'-a'or'-u'option on thecommandline interface may not be safe. >>> Performinghashslots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica redis05:6379 to redis01:6379 Adding replica redis06:6379 to redis02:6379 Adding replica redis04:6379 to redis03:6379 M: 148bf218eac4b30786ef89e5c5cc1bf4facdf4be redis01:6379 slots:[0-5460] (5461 slots) master M: 5964d6968e8527be920f1d60aad8e549ac1c327a redis02:6379 slots:[5461-10922] (5462 slots) master M: 4a33cf88ed2334e78fe468c35446a2a8bd14f805 redis03:6379 slots:[10923-16383] (5461 slots) master S: 4ee8406f204b7ee8778a40f7d6ec979cc4f9bfff redis04:6379 replicates 4a33cf88ed2334e78fe468c35446a2a8bd14f805 S: fb59eccda63bd4bb8d33526262612e1ab694da02 redis05:6379 replicates 148bf218eac4b30786ef89e5c5cc1bf4facdf4be S: 8b7b54ee2f4c7a327e1e954db379a519aa7e68b8 redis06:6379 replicates 5964d6968e8527be920f1d60aad8e549ac1c327a >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages tojointhe cluster Waitingforthe cluster tojoin . >>> Performing Cluster Check (using node redis01:6379) M: 148bf218eac4b30786ef89e5c5cc1bf4facdf4be redis01:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: 4a33cf88ed2334e78fe468c35446a2a8bd14f805 172.19.0.5:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 4ee8406f204b7ee8778a40f7d6ec979cc4f9bfff 172.19.0.2:6379 slots: (0 slots) slave replicates 4a33cf88ed2334e78fe468c35446a2a8bd14f805 S: fb59eccda63bd4bb8d33526262612e1ab694da02 172.19.0.7:6379 slots: (0 slots) slave replicates 148bf218eac4b30786ef89e5c5cc1bf4facdf4be S: 8b7b54ee2f4c7a327e1e954db379a519aa7e68b8 172.19.0.4:6379 slots: (0 slots) slave replicates 5964d6968e8527be920f1d60aad8e549ac1c327a M: 5964d6968e8527be920f1d60aad8e549ac1c327a 172.19.0.6:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Checkforopen slots... >>> Check slots coverage... [OK] All 16384 slots covered.
==登錄容器01-06任意一個進行查看==
登錄進redis客戶端
dockerexec-it redis02 bash /redis/redis-cli -c -a 123456
查看對應的配置信息
cluster info
查看對應日志
cluster nodes
設置一個key值,然后獲取
seta 123 get a "123"
退出后釋放資源
exit exit docker compose down
注意:
[ERR] Node redis01:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
==出現這個錯誤時,檢查你的 docker-compose.yml 文件或 Docker 命令,確保每個 Redis 實例的端口映射是唯一的,并且沒有沖突==。
鏈接:https://blog.csdn.net/m0_74068921/article/details/147077108?spm=1001.2014.3001.5501
-
數據庫
+關注
關注
7文章
3893瀏覽量
65695 -
MySQL
+關注
關注
1文章
844瀏覽量
27466 -
Docker
+關注
關注
0文章
507瀏覽量
12635 -
Redis
+關注
關注
0文章
384瀏覽量
11298
原文標題:告別單點故障!基于Docker的MySQL主從+Redis集群高可靠架構詳解
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
求MySQL集群配置的思路分享?
如何構建一個穩定、高性能的Redis集群?

redis集群狀態查看命令
redis查看集群狀態命令
云服務器 Flexus X 實例,Docker 集成搭建 Redis 集群

評論