前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Linux】Docker 中搭建Redis单节点以及集群

【Linux】Docker 中搭建Redis单节点以及集群

原创
作者头像
阿东
发布2023-01-19 20:48:33
2.9K0
发布2023-01-19 20:48:33
举报
文章被收录于专栏:公众号:懒时小窝

引言

搭建集群首先需要安装Docker,Linux中安装比较简单,具体可以参考[【Docker】Linux安装Docker(极简版)]

[【RocketMq】RocketMq 4.9.4 Windows-docker 部署] 中提到了Windows安装Docker的一部分些细节,这里不再过多讨论,安装完成之后的Redis集群搭建同样可以参考本篇进行构建。

过去个人在Mac上搭建过一次集群,和本文的搭建思路相似。如果是Mac用户可以参考:[M1-Mac中docker的redis集群配置]

Docker拉取Redis

查找和拉取Redis的命令为 docker search redisdocker pull reids:latest(或指定其他版本),查找之后拉取指定版本的Redis到本地Docker即可。

具体的操作流程如下,这里省略了docker search redis的过程。下面是在windows的Docker操作,Linux指定效果一致:

单节点启动

单节点非常简单,适合立马上手使用学习的开发者,按照下面的命令执行:

代码语言:text
复制
#默认拉取一个最新的redis镜像
docker pull redis
#在默认的6379端口上启动一个redis服务
docker run --name test-redis -p 6379:6379 -d redis
#进入容器内部
docker exec -it test-redis /bin/bash
# 连接redis
redis-cli
#进入之后安装惯例 ping一下即可
ping

自定义配置单节点

Linux中可以使用下面的方式:

代码语言:text
复制
docker run -d -p 6380:6379 -v /usr/docker/redis/myRedis/redis.conf:/etc/redis/redis.conf -v /usr/docker/redis/myRedis/data:/data --name myRedis redis redis-server /etc/redis/redis.conf

在Windows版本的docker仅仅是路径配置不太一样,需要替换为指定盘符的地址。

集群搭建

集群构建的步骤其实并不算特别复杂,关键在于配置以及一些模版命令上需要读者自行修改。

自定义redis-net

创建docker newwork 虚拟网段用于redis集群节点通信使用。

此命令需要提前执行,否则后续的步骤会报错,建议一开始立即执行。

代码语言:text
复制
docker network create redis-net

创建redis.conf配置模版

我们需要创建一个docker/redis/目录,在新建目录内创建6个redis.conf文件。比较笨的传统办法是一个个构建,当然这样一个个复制实在是太麻烦了,我们寻找更快的方式,下文会进行介绍。

为了更高效的构建redis的配置,我们通过创建模板的方式构建redis.conf模板,注意这一份配置文件格式既不能有误也不能乱写,否则整个redis构建过程是必定会出问题的,配置文件如下:

先来个简单版本的模板:

代码语言:text
复制
port ${PORT}
cluster-enabled yes
protected-mode no
cluster-config-file nodes.conf
cluster-node-timeout 5000
#对外ip,这里的ip要改为你的服务器Ip。【注意不能使用127.0.0.1】
cluster-announce-ip 192.168.58.128
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes

如果对于模板构建熟练,可以使用复杂点的版本,具体内容如下:

代码语言:text
复制
# 启动端口
port ${PORT}

# 绑定IP, 0.0.0.0 为本地    
#bind 0.0.0.0  

# 日志等级
#loglevel notice    

# 日志文件位置
#logfile /opt/docker/${PORT}/redis${PORT}_log.txt

# 是否开启 AOF 持久化模式,默认 no
appendonly yes

# aof持久化文件格式
appendfilename appendonly.${PORT}.aof

# 集群文件
cluster-enabled yes

# 集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。
# 不配置,默认配置为nodes-6379.conf                        
#cluster-config-file nodes.${PORT}.conf
cluster-config-file nodes.conf

# 节点互连超时的阀值,集群节点超时毫秒数
cluster-node-timeout 5000

# 集群节点 IP,填写宿主机的 IP
cluster-announce-ip 192.168.58.128

# 集群节点映射端口
cluster-announce-port ${PORT}

# 集群节点总线端口
# 此参数建议+10000
cluster-announce-bus-port 1${PORT}

# 断线时间过长的从节点不允许设置为master,该参数就是用来判断slave节点与master断线的时间是否过长,作为计算参数之一
# 公式:(node-timeout * slave-validity-factor) + repl-ping-slave-perio,假设 node-timeout = 30,默认的repl-ping-slave-period是10秒,则如果超过310秒此slave将不会尝试进行故障转移 cluster-slave-validity-factor 10

# 可以配置值为1,表示master的slave数量大于这个数值,slave才能迁移到孤立的master上面
# 如果这个数值被设置为2,则只有一个主节点拥有2个可工作节点才会从一个从节点迁移。
cluster-migration-barrier 1

# 默认情况下,集群全部的slot有节点负责,集群状态才为ok,才能提供服务。  设置为no,可以在slot没有全部分配的时候提供服务。
# 不建议设置为no,因为容易造成分区并且可能导致小分区的Master节点一直在被写入造成数据不平衡的问题。
#cluster-require-full-coverage no

# redis 连接密码 访问认证
#requirepass 123456

# 主节点访问认证
#masterauth 123456

# 是否启动保护模式
protected-mode no

以上两个版本其实就是配置多和少的区别,个人以简单版本的文件进行记录和演示。新手如果不熟悉Docker集群搭建,建议把上面的配置单独配置保存,以便需要的时候立刻翻阅回忆构建流程。

模板配置

拥有redis.conf模板之后,我们开始依据这个模板构建集群目录和对应的数据存储。

集群配置

首先我们可以执行下面的命令构建对应的目录和配置,注意在构建之前跳转到自己部署redis集群的根目录,比如个人先cd /opt/docker/redis当中:

代码语言:shell
复制
for port in `seq 6000 6000`; do 
  mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis_template_version2.conf > ./${port}/conf/redis.conf && mkdir -p ./${port}/data;
done

上面的命令是几个子命令拼凑在一起的,比较好理解:

  1. 在当前目录下构建“端口”对应的文件夹
  2. 定义把文件内部的${port}替换为对应的端口,重定向到页面替换。
  3. 输出到端口文件夹下面的conf/redis.conf,这样每个端口文件夹相当于一个独立的redis服务
  4. 最后构建data存储数据目录

这里略微解释一下${xx}这样的写法含义: 用shell格式字符串中的值替换环境变量。要替换的变量需要是${var}$var格式。 比如: echo '{{$HOME}}' | envsubst, 替换环境变量stdin输出到stdout: envsubst < {{path/to/input_file}},将输入文件中的环境变量替换为stdout: redis_template_version2.conf 就是前面的.conf模板文件的目录里。

简单版本的内容如下,这个文件的配置内容较为简化:

代码语言:shell
复制
port ${PORT}
cluster-enabled yes
protected-mode no
cluster-config-file nodes.conf
cluster-node-timeout 5000
#对外ip,这里的ip要改为你的服务器Ip。【注意不能使用127.0.0.1】,因为Docker自身运行有一层内部网络,这个网络是为了支持节点内部通信的。
cluster-announce-ip 192.168.58.128
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes

构建完成之后,我们可以看到对应的文件夹内容如下(部分文件为个人实验命令):

为了方便展示,这里使用 tree 命令,注意tree通常需要手动安装,具体的安装过程如下:

代码语言:shell
复制
sudo yum install tree

最后整个树形目录构建如下:

代码语言:shell
复制
[zxd@localhost docker]$ tree
.
├── 6000
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6001
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6002
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6003
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6004
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6005
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── redis-back1.conf
├── redis_init_config.txt
├── redis_init.txt
├── redis_template.conf
└── redis_templat_version2.conf

运行redis节点

构建集群需要确保每一个节点都能够单独执行:

代码语言:shell
复制
for port in `seq 6000 6000`; do
  docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} -v /opt/docker/redis/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /opt/docker/redis/${port}/data:/data  --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
done

之后docker ps查看所有节点是否正常启动,同时对于每个节点进行连接测试,由于篇幅有限,这里就不过多介绍了。

如果是线上部署,建议每个节点进入试一遍看看是否能正常单节点运行,保证都可以正常启动的情况下,开始尝试构建集群。

构建redis集群

我们启动6个节点之后,只需要进入到某一个节点的容器内部执行构建集群的命令即可,以个人的启动过程为例,执行下面的步骤:

  1. 执行docker ps命令。检查所有集群均正常搭建。
  1. 获取其中一个节点的容器id,当然也可以直接通过最后一列的NAMES进入,我们执行下面的命令:
代码语言:text
复制
docker exec -it d0073d25a732 /bin/bash

或者执行命令

`

代码语言:text
复制
docker exec -it redis-6000 /bin/bash

顺利进入到容器当中,此时还需要执行redis-cli真正进入到redis内部。注意启动端口是从6000-6005,直接用默认的redis-cli 会进入到6379的端口,这样连接是会失败的,所以我们最好指定端口和ip运行redis-cli

代码语言:shell
复制
docker exec -it redis-6000 /bin/bash

root@d0073d25a732:/data# redis-cli -h 192.168.58.128 -p 6000
192.168.58.128:6000> ping
PONG
192.168.58.128:6000> 

注意:进入节点容器内部之后,可以直接执行redis-cli,也可以进入到/usr/local/bin下运行相关命令。

到了关键的步骤,我们开始构建redis节点集群。注意这一步建议进入容器之后跳转到/usr/local/bin

代码语言:shell
复制
redis-cli --cluster create 192.168.58.128:6000 192.168.58.128:6001 192.168.58.128:6002 192.168.58.128:6003 192.168.58.128:6004 192.168.58.128:6005 --cluster-replicas 1

自己构建集群需要把Ip和端口进行相对应的修改操作

代码语言:shell
复制
root@d0073d25a732:/usr/local/bin# ./redis-cli --cluster create 192.168.58.128:6000 192.168.58.128:6001 192.168.58.128:6002 192.168.58.128:6003 192.168.58.128:6004 192.168.58.128:6005 --cluster-replicas 1

最终的打印内容如下:

代码语言:shell
复制
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.58.128:6004 to 192.168.58.128:6000
Adding replica 192.168.58.128:6005 to 192.168.58.128:6001
Adding replica 192.168.58.128:6003 to 192.168.58.128:6002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: a3d907505eb8575c95fb91f13d8580e144ae2ebd 192.168.58.128:6000
   slots:[0-5460] (5461 slots) master
M: d429ebb22ff24dcc4a01f77776e3b8ba367c0365 192.168.58.128:6001
   slots:[5461-10922] (5462 slots) master
M: 868b2e39ebf455e086c5e418537a04f1fc24f23b 192.168.58.128:6002
   slots:[10923-16383] (5461 slots) master
S: c2e9e28bf4dec5f9603e176eea4e19857a548c27 192.168.58.128:6003
   replicates 868b2e39ebf455e086c5e418537a04f1fc24f23b
S: 9dc71ed4313eb7db87bee287954c38d26a9ef950 192.168.58.128:6004
   replicates a3d907505eb8575c95fb91f13d8580e144ae2ebd
S: cbbc3c7a21a16581ddd3136d7169eecb6c2faf83 192.168.58.128:6005
   replicates d429ebb22ff24dcc4a01f77776e3b8ba367c0365
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.58.128:6000)
M: a3d907505eb8575c95fb91f13d8580e144ae2ebd 192.168.58.128:6000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 868b2e39ebf455e086c5e418537a04f1fc24f23b 192.168.58.128:6002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 9dc71ed4313eb7db87bee287954c38d26a9ef950 192.168.58.128:6004
   slots: (0 slots) slave
   replicates a3d907505eb8575c95fb91f13d8580e144ae2ebd
M: d429ebb22ff24dcc4a01f77776e3b8ba367c0365 192.168.58.128:6001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: c2e9e28bf4dec5f9603e176eea4e19857a548c27 192.168.58.128:6003
   slots: (0 slots) slave
   replicates 868b2e39ebf455e086c5e418537a04f1fc24f23b
S: cbbc3c7a21a16581ddd3136d7169eecb6c2faf83 192.168.58.128:6005
   slots: (0 slots) slave
   replicates d429ebb22ff24dcc4a01f77776e3b8ba367c0365
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

如果出现类似的提示,说明集群创建成功,如果报错则确定节点是否正确,构建集群的命令是否正确,比如IP和端口是否写对,是否存在对应的节点等等。

连接测试

要连接Docker的Redis,首先要进入到某个容器的内部,然后再容器内部的Shell连接上Redis集群,下面是个人的实验步骤:

  1. docker ps -a 查看当前的集群情况,这里的容器ID为d0073d25a732
代码语言:shell
复制
[zxd@localhost ~]$ docker ps -a
CONTAINER ID   IMAGE                                      COMMAND                  CREATED       STATUS                     PORTS                                                                                                               NAMES
27ea2f9dced7   mysql:5.7                                  "docker-entrypoint.s…"   3 weeks ago   Up About an hour           33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp                                                              mysql57
8aad8f4d75af   apache/rocketmq:4.9.4                      "sh mqbroker -c ../c…"   3 weeks ago   Up About an hour           0.0.0.0:10909->10909/tcp, :::10909->10909/tcp, 9876/tcp, 10912/tcp, 0.0.0.0:10911->10911/tcp, :::10911->10911/tcp   rmqbroker
dc2aefc4db1f   apache/rocketmq:4.9.4                      "sh mqnamesrv"           3 weeks ago   Up About an hour           10909/tcp, 0.0.0.0:9876->9876/tcp, :::9876->9876/tcp, 10911-10912/tcp                                               rmqnamesrv
195d102724b5   apacherocketmq/rocketmq-dashboard:latest   "sh -c 'java $JAVA_O…"   3 weeks ago   Up About an hour           0.0.0.0:8888->8080/tcp, :::8888->8080/tcp                                                                           rocketmq-dashboard
cb04e4c79e39   redis                                      "docker-entrypoint.s…"   3 weeks ago   Exited (255) 3 weeks ago   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp                                                                           test-redis
d0073d25a732   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6000->6000/tcp, :::6000->6000/tcp, 0.0.0.0:16000->16000/tcp, :::16000->16000/tcp, 6379/tcp                  redis-6000
559261cf34e6   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6005->6005/tcp, :::6005->6005/tcp, 0.0.0.0:16005->16005/tcp, :::16005->16005/tcp, 6379/tcp                  redis-6005
bd0fd81d54e7   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6004->6004/tcp, :::6004->6004/tcp, 0.0.0.0:16004->16004/tcp, :::16004->16004/tcp, 6379/tcp                  redis-6004
7a5545e038e8   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6003->6003/tcp, :::6003->6003/tcp, 0.0.0.0:16003->16003/tcp, :::16003->16003/tcp, 6379/tcp                  redis-6003
599b070b4afd   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6002->6002/tcp, :::6002->6002/tcp, 0.0.0.0:16002->16002/tcp, :::16002->16002/tcp, 6379/tcp                  redis-6002
d551114d11de   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6001->6001/tcp, :::6001->6001/tcp, 0.0.0.0:16001->16001/tcp, :::16001->16001/tcp, 6379/tcp                  redis-6001
  1. 我们进入到容器内部,使用命令docker exec -it d0073d25a732 /bin/bash
代码语言:shell
复制
[zxd@localhost ~]$ docker exec -it d0073d25a732 /bin/bash
root@d0073d25a732:/data# 
  1. 进入到容器之后,使用命令redis-cli -c -h 192.168.58.128 -p 6000连接,然后经典的pingpong测试即可,注意这里的-c代表集群模式连接:
代码语言:shell
复制
root@d0073d25a732:/data# redis-cli -c -h 192.168.58.128 -p 6000
192.168.58.128:6000> ping
PONG

以上整个docker集群搭建完毕。

常见问题

Could not connect to Redis at 127.0.0.1:6379: Connection refused

代码语言:txt
复制
[root@rongle bin]# redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused
[root@rongle /]# redis-server /etc/redis.conf
[root@rongle /]# redis-cli
redis 127.0.0.1:6379>

这是 redis初学者比较常见的问题,可以从下面几个方面排查问题:

  1. redis.conf 是否关闭“保护模式”以及注释掉bind配置(默认 127.0.0.1)
  2. 是否启动端口和IP和连接的端口和IP不一致。
  3. docker的redis节点是否正常启动,如果在status里面发现不断重启,多半还是redis.conf存在问题。
  4. 命令的格式和规范是否正确。

收尾

以上就是快速构建docker redis集群的方式,整个过程不算很难,但是对于配置这一块需要小心不要写错了,否则很容易浪费时间调试,因为在Docker中会对于redis容器进行无限重启。

参考资料

Docker搭建Redis Cluster集群及扩容和收容 - Dvomu - 博客园 (cnblogs.com)

Redis集群原理及搭建(Twemproxy、Predixy代理搭建、Redis Cluster集群) - Dvomu - 博客园 (cnblogs.com)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • Docker拉取Redis
  • 单节点启动
    • 自定义配置单节点
    • 集群搭建
      • 自定义redis-net
        • 创建redis.conf配置模版
          • 模板配置
            • 集群配置
          • 运行redis节点
            • 构建redis集群
              • 连接测试
              • 常见问题
                • Could not connect to Redis at 127.0.0.1:6379: Connection refused
                • 收尾
                • 参考资料
                相关产品与服务
                容器镜像服务
                容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档