前言:本文记录了如何使用docker-compose和redis官方镜像和第三方redis-trib镜像组建3主3从的redis集群并设置密码.踩坑不易,未经本人允许不得转载.

一 创建文件结构

  1. 新建redis文件夹
  2. 在redis文件夹下新建docker-compose.yml文件
  3. 在redis文件夹下新建slave1到slave6共6个文件夹作为从属结点的文件夹
    这里写图片描述

二 配置redis.conf文件

  1. http://download.redis.io/redis-stable/redis.conf下载官方redis.conf文件
  2. 拷贝到各个slave文件夹下,分别配置如下内容,以端口6061为例(默认为6379)
# bind 127.0.0.1 //加上注释#
protected-mode no //关闭保护模式
port 6061  //绑定自定义端口
#daemonize yes //禁止redis后台运行
pidfile /var/run/redis_6061.pid 
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes_6061.conf //集群的配置 配置文件首次启动自动生成 

配置文件是最容易出问题的,这里面有一些注意事项:

  • requirepass和masterauth不能启用
    因为使用redis-trib连接集群时是不能指定密码的,如果开启了requirepass或者masterauth会导致集群连接失败,所以应该等集群创建好后再修改密码,这个后文会说

  • bind
    表示设置redis监听哪个ip,设置了监听之后,只有使用这些ip才能访问这个redis服务,不指定则默认所有ip都能访问该redis服务
    注意:这里的ip指的是redis的ip而非访问方的ip,bind并不直接限制哪些ip能够访问redis,显示ip访问是限制监听后的效果,如果想限制ip访问应使用Linux防火墙功能.
    比方说,在生产条件下的redis服务器有3个ip(外网ip 122.122.122.122,局域网ip192.128.0.1,本地ip127.0.0.1),则为了安全,bind后面只应该写局域网ip和本地ip,这样就只有局域网用户(包括本机)可以通过192.128.0.1访问redis服务,间接起到限制ip访问的作用.

  • protected-mode

    • 作用:
      禁止公网访问redis cache,加强redis安全的
    • 启用条件:
      1. 没有bind IP
      2. 没有设置requirepass访问密码
    • 解释:
      由于前面提及的原因,保护模式会开启导致无法通过公网访问,故这里需要关闭保护模式,但注意集群建好后要及时添加密码,增强安全性
  • daemonize 和 pidfile
    实测开启守护模式(daemonize yes)容器会启动失败,因为是使用docker,所以前台启动也没什么关系,pidfile的文件名和端口号一致是一个良好的习惯

三 编写Dockerfile

首先先贴出配置,同样以6061端口为例

#基础镜像
FROM redis

#将自定义conf文件拷入
COPY redis.conf /usr/local/etc/redis/redis.conf

#修复时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

#修改文件权限,使之可以通过config rewrite重写
RUN chmod 777 /usr/local/etc/redis/redis.conf

# Redis客户端连接端口
EXPOSE 6061
# 集群总线端口:redis客户端连接的端口 + 10000
EXPOSE 16061

#使用自定义conf启动
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

注意:

  1. 集群总线端口
    Redis集群中每个redis实例(可能一台机部署多个实例)会使用两个Tcp端口,一个用于给客户端(redis-cli或应用程序等)使用的端口,另一个是用于集群中实例相互通信的内部总线端口,且第二个端口比第一个端口一定大10000.内部总线端口通信使用特殊协议,以便实现集群内部高带宽低时延的数据交换。所以配置redis实例时只需要指明第一个端口就可以了。
    但是由于我们使用的是docker,所以要将这个端口暴露出来,否则集群无法建立(使用redis-trib时会一直显示Waiting for the cluster to join)
  2. 修改redis.conf文件权限,否则后面写入访问密码到文件的时候会提示Permission denied
  3. 修复时区是个人习惯,与本文无关,想了解的可见:https://blog.csdn.net/alinyua/article/details/80944543

四 编写docker-compose.yml文件

先贴出配置如下,没什么好说的,是最简单的配置了

redis-slave1:
  build: ./slave1
  ports:
   - 6061:6061
   - 16061:16061
redis-slave2:
  build: ./slave2
  ports:
   - 6062:6062
   - 16062:16062
redis-slave3:
  build: ./slave3
  ports:
   - 6063:6063
   - 16063:16063
redis-slave4:
  build: ./slave4
  ports:
   - 6064:6064
   - 16064:16064
redis-slave5:
  build: ./slave5
  ports:
   - 6065:6065
   - 16065:16065
redis-slave6:
  build: ./slave6
  ports:
   - 6066:6066
   - 16066:16066

五 启动

在redis目录下(即docker-compose.yml同级目录),运行

docker-compose up -d

再查看容器运行情况

docker ps -a

结果如下
这里写图片描述
这时启动使用redis客户端连接测试一下,我这里使用的是Redis Desktop Manager,注意,此时连接还不需要密码,十分不安全,以6061端口为例,测试结果如下:
这里写图片描述
可以看到此时请求访问密码和访问master密码是空白的,另外集群状态是失败
这个时候使用redis会报"CLUSTERDOWN Hash slot not served"错误

六 连接集群

连接集群非常简单,不需要去修改什么配置,只需要一条docker指令

docker run --rm -it zvelo/redis-trib create --replicas 1 ip:6061 ip:6062 ip:6063 ip:6064 ip:6065 ip:6066

ip替换成实际ip地址,结果如下,中间需要用yes来同意集群方案
结果如下
这里写图片描述

七 验证集群

输入cluster info查看集群信息,此时已为 ok,再测试一下set和get,另外可以看到,结点会自己切换,并且6061端口set和数据可以在6062端口get到
这里写图片描述

八 设置集群密码

  1. 使用redis-trib.rb工具构建集群,集群构建完成前不要配置密码,集群构建完毕再通过config set + config rewrite命令逐个机器设置密码
  2. 如果对集群设置密码,那么requirepass和masterauth都需要设置,否则发生主从切换时,就会遇到授权问题
  3. 各个节点的密码都必须一致,否则Redirected就会失败

具体指令如下:

  • 设置masterauth
config set masterauth 密码
  • 设置requirepass
config set requirepass 密码
  • 验证密码,以继续操作
auth LinShen
  • 回写到文件,使其永久生效(如果这里出现Permission denied,则说明Dockerfile少了RUN chmod 777 /usr/local/etc/redis/redis.conf)
config rewrite

如下图
这里写图片描述
然后再使用docker exec指令进入容器内部看一下masterauth和requirepass是否写入到文件里

docker exec -it 容器ID /bin/bash

cat指令查看

cat /usr/local/etc/redis/redis.conf

得到如下图
这里写图片描述
可以看到masterauth和requirepass被追加到文件的最后,即使重启密码也还生效

至此,利用docker-compose组建redis集群结束

可以看到,其实docker-compose起的作用并不大,因为在单机上部署redis集群确实没什么实际意义,但是,你完全可以把slave结点放到不同的服务器上,再通过docker的redis-trib容器来连接,十分灵活和方便.

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐