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

2023-01-28 20:07:01来源:哔哩哔哩

引言

搭建集群首先需要安装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指定效果一致:

单节点启动

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

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

自定义配置单节点

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

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集群节点通信使用。

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

docker network create redis-net

创建redis.conf配置模版

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

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

先来个简单版本的模板:

port ${PORT}cluster-enabled yesprotected-mode nocluster-config-file nodes.confcluster-node-timeout 5000#对外ip,这里的ip要改为你的服务器Ip。【注意不能使用127.0.0.1】cluster-announce-ip 192.168.58.128cluster-announce-port ${PORT}cluster-announce-bus-port 1${PORT}appendonly yes

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

# 启动端口port ${PORT}# 绑定IP, 0.0.0.0 为本地    #bind 0.0.0.0  # 日志等级#loglevel notice    # 日志文件位置#logfile /opt/docker/${PORT}/redis${PORT}_log.txt# 是否开启 AOF 持久化模式,默认 noappendonly yes# aof持久化文件格式appendfilename appendonly.${PORT}.aof# 集群文件cluster-enabled yes# 集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。# 不配置,默认配置为nodes-6379.conf                        #cluster-config-file nodes.${PORT}.confcluster-config-file nodes.conf# 节点互连超时的阀值,集群节点超时毫秒数cluster-node-timeout 5000# 集群节点 IP,填写宿主机的 IPcluster-announce-ip 192.168.58.128# 集群节点映射端口cluster-announce-port ${PORT}# 集群节点总线端口# 此参数建议+10000cluster-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当中:

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

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

在当前目录下构建“端口”对应的文件夹

定义把文件内部的${port}替换为对应的端口,重定向到页面替换。

输出到端口文件夹下面的conf/redis.conf,这样每个端口文件夹相当于一个独立的redis服务

最后构建data存储数据目录

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

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

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

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

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

sudo yum install tree

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

[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节点

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

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个节点之后,只需要进入到某一个节点的容器内部执行构建集群的命令即可,以个人的启动过程为例,执行下面的步骤:

执行docker ps命令。检查所有集群均正常搭建。

获取其中一个节点的容器id,当然也可以直接通过最后一列的NAMES进入,我们执行下面的命令:

docker exec -it d0073d25a732 /bin/bash

或者执行命令`

docker exec -it redis-6000 /bin/bash

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

docker exec -it redis-6000 /bin/bashroot@d0073d25a732:/data# redis-cli -h 192.168.58.128 -p 6000192.168.58.128:6000> pingPONG192.168.58.128:6000> 

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

到了关键的步骤,我们开始构建redis节点集群。注意这一步建议进入容器之后跳转到/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

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

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

最终的打印内容如下:

>>> Performing hash slots allocation on 6 nodes...Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383Adding replica 192.168.58.128:6004 to 192.168.58.128:6000Adding replica 192.168.58.128:6005 to 192.168.58.128:6001Adding 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 masterM: a3d907505eb8575c95fb91f13d8580e144ae2ebd 192.168.58.128:6000   slots:[0-5460] (5461 slots) masterM: d429ebb22ff24dcc4a01f77776e3b8ba367c0365 192.168.58.128:6001   slots:[5461-10922] (5462 slots) masterM: 868b2e39ebf455e086c5e418537a04f1fc24f23b 192.168.58.128:6002   slots:[10923-16383] (5461 slots) masterS: c2e9e28bf4dec5f9603e176eea4e19857a548c27 192.168.58.128:6003   replicates 868b2e39ebf455e086c5e418537a04f1fc24f23bS: 9dc71ed4313eb7db87bee287954c38d26a9ef950 192.168.58.128:6004   replicates a3d907505eb8575c95fb91f13d8580e144ae2ebdS: cbbc3c7a21a16581ddd3136d7169eecb6c2faf83 192.168.58.128:6005   replicates d429ebb22ff24dcc4a01f77776e3b8ba367c0365Can 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 clusterWaiting 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 a3d907505eb8575c95fb91f13d8580e144ae2ebdM: 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 868b2e39ebf455e086c5e418537a04f1fc24f23bS: 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集群,下面是个人的实验步骤:

docker ps -a查看当前的集群情况,这里的容器ID为d0073d25a732

[zxd@localhost ~]$ docker ps -aCONTAINER ID   IMAGE                                      COMMAND                  CREATED       STATUS                     PORTS                                                                                                               NAMES27ea2f9dced7   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                                                              mysql578aad8f4d75af   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   rmqbrokerdc2aefc4db1f   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                                               rmqnamesrv195d102724b5   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-dashboardcb04e4c79e39   redis                                      "docker-entrypoint.s…"   3 weeks ago   Exited (255) 3 weeks ago   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp                                                                           test-redisd0073d25a732   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-6000559261cf34e6   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-6005bd0fd81d54e7   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-60047a5545e038e8   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-6003599b070b4afd   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-6002d551114d11de   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

我们进入到容器内部,使用命令docker exec -it d0073d25a732 /bin/bash

[zxd@localhost ~]$ docker exec -it d0073d25a732 /bin/bashroot@d0073d25a732:/data# 

进入到容器之后,使用命令redis-cli -c -h 192.168.58.128 -p 6000连接,然后经典的pingpong测试即可,注意这里的-c代表集群模式连接:

root@d0073d25a732:/data# redis-cli -c -h 192.168.58.128 -p 6000192.168.58.128:6000> pingPONG

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

常见问题

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

``

[root@rongle bin]# redis-cliCould not connect to Redis at 127.0.0.1:6379: Connection refused[root@rongle /]# redis-server /etc/redis.conf[root@rongle /]# redis-cliredis 127.0.0.1:6379>

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

redis.conf 是否关闭“保护模式”以及注释掉bind配置(默认 127.0.0.1)

是否启动端口和IP和连接的端口和IP不一致。

docker的redis节点是否正常启动,如果在status里面发现不断重启,多半还是redis.conf存在问题。

命令的格式和规范是否正确。

收尾

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

参考资料

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

关键词: PORT NODE DOCKER ABOUT redis Slots SOME TREE weeks REPLICA DATA CHECK Opening RESTART ADDITIONAL linux WINDOWS ALLOCATION ALWAYS SHELL CONNECT IMAGE ROOT EPOCH ERROR PING TRYING ASSIGN Linux安装 connection ping pong warning MASTER MYSQL ECHO Java OPEN

上一篇:最辣小三“上半身全空“吊钢丝,一动作邪恶曲线被看光 每日速读
下一篇:最后一页