https://www.jianshu.com/p/453a2d70a5de
可前往语雀阅读,体验更好:docker 搭建 redis 伪分布式集群
该实验主要来源于《Docker 容器与容器云 第2版》一书的 2.3 节:“搭建你的第一个 Docker 应用栈”中的一小步,搭建一个 redis 的一主双从的伪分布式集群
但书中的示例,在配置主、从 redis 实例的配置文件 redis.conf 时,漏掉了一个参数:bind 0.0.0.0,该参数在配置文件中的默认值为:bind 127.0.0.1,导致按书中步骤使用 docker 搭建 redis 的伪分布式集群时,主从之间无法同步数据
本文将按照,我优化过的实验步骤,介绍如何使用 docker 搭建 redis 伪分布式集群
阿里云 centos 云主机一台:
docker 相关信息:
使用 docker 搭建一主双从的 redis 伪分布式集群,使用 redis 的 slaveof <master_ip> <master_port>
命令完成 redis 的主从复制,结构图如下:
如果是一个真正的分布式架构集群,还需要处理容器的跨主机通信问题,这里不做介绍
鉴于是在同一个宿主机完成 redis 伪分布式集群的搭建,只需要完成容器互联来实现容器间的通信即可,这里采用 docker run
命令的 --link
选项来建立容器间的互联关系
介绍下 --link
选项:
--link
选项能够进行容器间安全的相互通信name:alias
docker run
命令中重复使用该参数通过
--link
选项,可以避免容器的 IP 和端口暴露到外网所导致的安全问题,还可以防止容器在重启后 IP 地址变化导致的访问失效它的原理类似 DNS 服务器的域名和地址映射,当容器的 IP 地址发生变化时,Docker 将自动维护映射关系中的 IP 地址,在容器内的
/etc/hosts
文件中会体现上述映射关系
下载最新版 redis 镜像:
docker pull redis
找到 redis 镜像对应的 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
复制 redis-master.conf:
cp redis-6.0.10/redis.conf ./redis-master.conf
redis-master.conf 修改如下参数:
daemonize yes
pidfile /var/run/redis.pid
bind 0.0.0.0
复制 redis-slave.conf(两台 redis):
cp redis-6.0.10/redis.conf ./redis-slave.conf
redis-slave.conf 修改如下参数:
daemonize yes
pidfile /var/run/redis.pid
bind 0.0.0.0
slaveof master 6379
启动 redis-master 容器(单独开一个 terminal 操作):
# 启动 redis-master 容器,并进入该容器
docker run -it --name redis-master -v /usr/local/jsj/redis-master.conf:/usr/local/bin/redis.conf redis /bin/bash
# 在容器内,启动 redis-server 进程
/usr/local/bin/redis-server /usr/local/bin/redis.conf
启动 redis-slave1 容器(单独开一个 terminal 操作):
# 启动 redis-slave1 容器,并进入该容器
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
# 在容器内,启动 redis-server 进程
/usr/local/bin/redis-server /usr/local/bin/redis.conf
启动 redis-slave2 容器(单独开一个 terminal 操作):
# 启动 redis-slave1 容器,并进入该容器
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
# 在容器内,启动 redis-server 进程
/usr/local/bin/redis-server /usr/local/bin/redis.conf
在 redis-master 容器中,连接上 redis-server,进行数据写入:
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,进行数据查询(这里展示 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>
从数据测试结果得知,一主双从的 redis 伪分布式集群已搭建完毕
为了方便操作 json 数据,主机上已安装 jq rpm,jq 是一个操作 json 数据非常方便的命令行工具
# 删除 redis-slave1
a=$(docker inspect redis-slave1 | jq -r '.[].Mounts[1].Source') && echo ${a}
docker rm -f redis-slave1
# 删除 redis-slave1 的宿主机默认 bind 目录
cd ~ && rm -rfv ${a} && unset a
# 删除 redis-slave2
a=$(docker inspect redis-slave2 | jq -r '.[].Mounts[1].Source') && echo ${a}
docker rm -f redis-slave2
# 删除 redis-slave2 的宿主机默认 bind 目录
cd ~ && rm -rfv ${a} && unset a
# 删除 redis-master
a=$(docker inspect redis-master | jq -r '.[].Mounts[1].Source') && echo ${a}
docker rm -f redis-master
# 删除 redis-master 的宿主机默认 bind 目录
cd ~ && rm -rfv ${a} && unset a
rm -rfv /usr/local/jsj
docker rmi redis