建議閱讀方式
可前往語雀閱讀,體驗更好:docker 搭建 redis 偽分布式集群
背景介紹
該實驗主要來源于《Docker 容器與容器云 第2版》一書的 2.3 節(jié):“搭建你的第一個 Docker 應(yīng)用棧”中的一小步,搭建一個 redis 的一主雙從的偽分布式集群
但書中的示例,在配置主、從 redis 實例的配置文件 redis.conf 時,漏掉了一個參數(shù):bind 0.0.0.0,該參數(shù)在配置文件中的默認(rèn)值為:bind 127.0.0.1,導(dǎo)致按書中步驟使用 docker 搭建 redis 的偽分布式集群時,主從之間無法同步數(shù)據(jù)
本文將按照,我優(yōu)化過的實驗步驟,介紹如何使用 docker 搭建 redis 偽分布式集群
環(huán)境說明
阿里云 centos 云主機(jī)一臺:

docker 相關(guān)信息:

搭建架構(gòu)
使用 docker 搭建一主雙從的 redis 偽分布式集群,使用 redis 的 slaveof <master_ip> <master_port> 命令完成 redis 的主從復(fù)制,結(jié)構(gòu)圖如下:

如果是一個真正的分布式架構(gòu)集群,還需要處理容器的跨主機(jī)通信問題,這里不做介紹
鑒于是在同一個宿主機(jī)完成 redis 偽分布式集群的搭建,只需要完成容器互聯(lián)來實現(xiàn)容器間的通信即可,這里采用 docker run 命令的 --link 選項來建立容器間的互聯(lián)關(guān)系
介紹下 --link 選項:
- 通過
--link選項能夠進(jìn)行容器間安全的相互通信 - 使用格式為
name:alias - 可在一個
docker run命令中重復(fù)使用該參數(shù)
通過
--link選項,可以避免容器的 IP 和端口暴露到外網(wǎng)所導(dǎo)致的安全問題,還可以防止容器在重啟后 IP 地址變化導(dǎo)致的訪問失效它的原理類似 DNS 服務(wù)器的域名和地址映射,當(dāng)容器的 IP 地址發(fā)生變化時,Docker 將自動維護(hù)映射關(guān)系中的 IP 地址,在容器內(nèi)的
/etc/hosts文件中會體現(xiàn)上述映射關(guān)系
搭建步驟
1. 下載 redis 鏡像,并下載鏡像對應(yīng)版本的 redis 壓縮包
下載最新版 redis 鏡像:
docker pull redis

找到 redis 鏡像對應(yīng)的 redis.tar.gz 壓縮包:
docker history --no-trunc redis | grep -i tar.gz

將 redis-6.0.10.tar.gz 下載到指定目錄 /usr/local/jsj 中:
mkdir -p /usr/local/jsj && cd /usr/local/jsj && curl -O http://download.redis.io/releases/redis-6.0.10.tar.gz

解壓 redis-6.0.10.tar.gz,得到與 redis 鏡像匹配的 redis.conf 配置文件:
tar xzf redis-6.0.10.tar.gz

2. 復(fù)制兩份 redis.conf,作為 master, slave 的配置文件
復(fù)制 redis-master.conf:
cp redis-6.0.10/redis.conf ./redis-master.conf
redis-master.conf 修改如下參數(shù):
daemonize yes
pidfile /var/run/redis.pid
bind 0.0.0.0
復(fù)制 redis-slave.conf(兩臺 redis):
cp redis-6.0.10/redis.conf ./redis-slave.conf
redis-slave.conf 修改如下參數(shù):
daemonize yes
pidfile /var/run/redis.pid
bind 0.0.0.0
slaveof master 6379
3. 先后分別啟動 1 臺 redis-master, 2 臺 redis-slave 容器
啟動 redis-master 容器(單獨開一個 terminal 操作):
# 啟動 redis-master 容器,并進(jìn)入該容器
docker run -it --name redis-master -v /usr/local/jsj/redis-master.conf:/usr/local/bin/redis.conf redis /bin/bash
# 在容器內(nèi),啟動 redis-server 進(jìn)程
/usr/local/bin/redis-server /usr/local/bin/redis.conf

啟動 redis-slave1 容器(單獨開一個 terminal 操作):
# 啟動 redis-slave1 容器,并進(jìn)入該容器
docker run -it --name redis-slave1 -v /usr/local/jsj/redis-slave.conf:/usr/local/bin/redis.conf --link redis-master:master redis /bin/bash
# 在容器內(nèi),啟動 redis-server 進(jìn)程
/usr/local/bin/redis-server /usr/local/bin/redis.conf

啟動 redis-slave2 容器(單獨開一個 terminal 操作):
# 啟動 redis-slave1 容器,并進(jìn)入該容器
docker run -it --name redis-slave2 -v /usr/local/jsj/redis-slave.conf:/usr/local/bin/redis.conf --link redis-master:master redis /bin/bash
# 在容器內(nèi),啟動 redis-server 進(jìn)程
/usr/local/bin/redis-server /usr/local/bin/redis.conf

4. 數(shù)據(jù)測試,驗證主從復(fù)制
在 redis-master 容器中,連接上 redis-server,進(jìn)行數(shù)據(jù)寫入:
root@14ab3c0d0f9f:/data# redis-cli
127.0.0.1:6379> set master jsj
OK
127.0.0.1:6379> get master
"jsj"
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.17.0.6,port=6379,state=online,offset=372,lag=1
slave1:ip=172.17.0.7,port=6379,state=online,offset=372,lag=1
master_replid:7eb1e8150916a477ff171bd0ab79bdff6bd002fe
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:372
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:372
127.0.0.1:6379>

在兩臺 redis-slave 容器中,連接上 redis-server,進(jìn)行數(shù)據(jù)查詢(這里展示 redis-slave1):
root@7d830a49430a:/data# redis-cli
127.0.0.1:6379> get master
"jsj"
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:master
master_port:6379
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:372
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:7eb1e8150916a477ff171bd0ab79bdff6bd002fe
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:372
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:372
127.0.0.1:6379>

從數(shù)據(jù)測試結(jié)果得知,一主雙從的 redis 偽分布式集群已搭建完畢
環(huán)境復(fù)原
為了方便操作 json 數(shù)據(jù),主機(jī)上已安裝 jq rpm,jq 是一個操作 json 數(shù)據(jù)非常方便的命令行工具
1. 刪除 redis-slave1 容器
# 刪除 redis-slave1
a=$(docker inspect redis-slave1 | jq -r '.[].Mounts[1].Source') && echo ${a}
docker rm -f redis-slave1
# 刪除 redis-slave1 的宿主機(jī)默認(rèn) bind 目錄
cd ~ && rm -rfv ${a} && unset a

2. 刪除 redis-slave2 容器
# 刪除 redis-slave2
a=$(docker inspect redis-slave2 | jq -r '.[].Mounts[1].Source') && echo ${a}
docker rm -f redis-slave2
# 刪除 redis-slave2 的宿主機(jī)默認(rèn) bind 目錄
cd ~ && rm -rfv ${a} && unset a

3. 刪除 redis-master 容器
# 刪除 redis-master
a=$(docker inspect redis-master | jq -r '.[].Mounts[1].Source') && echo ${a}
docker rm -f redis-master
# 刪除 redis-master 的宿主機(jī)默認(rèn) bind 目錄
cd ~ && rm -rfv ${a} && unset a

4. 刪除 redis 資源目錄:/usr/local/jsj
rm -rfv /usr/local/jsj
5. 刪除 redis 鏡像
docker rmi redis