Mac中使用Docker搭建Redis Cluster集群

本文详述了在MacOS环境下,利用Docker和colima搭建Redis Cluster的过程,包括环境准备、创建Docker容器网络、编写配置文件、启动容器以及集群测试。特别指出,如果仅用于本地开发,无需创建Docker网络,直接使用host模式。同时,文章提到了多个注意事项和常见问题,例如端口映射、集群配置以及对外提供服务的IP设置等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

免责声明:自己也是docker新人,主要是学习和记录
是真的脑抽才会用Docker搭redis集群,homebrew安装的redis配多个配置文件应该也可以直接搭建,时间全花在搞Docker上了,后续有时间了搞一下另一种搭建方式再写一篇博客。
真心建议不要用MacOS搭服务,很痛苦,有时候觉得还不如Windows。开发的话还可以

一、环境准备
1.系统版本

本文演示的系统版本是MacOS 13。

2.确认Docker已安装

在这里插入图片描述
并且,这里本人用的不是Docker Desktop,而是colima,因此使用Docker之前记得colima start启动Docker。

3.拉取Redis镜像
➜  ~ docker pull redis
Using default tag: latest
latest: Pulling from library/redis
d981f2c20c93: Pull complete 
5b8f51f5c4bb: Pull complete 
2d3d8bc9388e: Pull complete 
849e9b1b24f1: Pull complete 
6e2590bc72d8: Pull complete 
bdd261b6469d: Pull complete 
Digest: sha256:f9724694a0b97288d2255ff2b69642dfba7f34c8e41aaf0a59d33d10d8a42687
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
二、创建Docker容器网络

注意:这里有一点需要说清楚,这也是在这篇博客快要结束的时候才发现的。
如果你要搭建的Redis集群需要对外提供服务,那么可以进行这一步。而如果你只是需要搭建一个本地的Redis集群,供自己本地开发使用,即使用127.0.0.1来访问,那么就不需要这一步了。在下文中,会有多处描述这种区别,会用“需要对外提供服务”和“不需要对外提供服务”的简述来区分上述两种情况,读者根据情况做不同的配置即可。

如果 不需要对外提供服务, 本章节不需要配置。

1.创建虚拟网卡
➜  ~ docker network create myredis
d4bece55cbc015be462605755377faa4a15694d815eb39f9fe2f973f5d8154e1
2.查看Docker网卡信息
➜  ~ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
3831cf1496c6   bridge    bridge    local
01f8f8a01a74   host      host      local
d4bece55cbc0   myredis   bridge    local
1fc0198954f8   none      null      local
3.查看Docker网络详细信息

在这里插入图片描述

4.补充(删除网卡信息、帮助命令)
docker network rm myredis #删除网卡命令 多个中间 空格隔开
docker network --help #显示可带参数等
三、编写配置文件

这里用一个脚本来生成多个配置文件,部分内容根据实际情况做更改
如果 需要对外提供服务使用如下配置:

for port in $(seq 6379 6384);
do
mkdir -p /[你想设置的目录]/redis/node-${port}/conf
touch /[你想设置的目录]/redis/node-${port}/conf/redis.conf

docker volume create redis_${port};

cat << EOF > /[你想设置的目录]/redis/node-${port}/conf/redis.conf
port ${port}
requirepass 1234
bind 0.0.0.0
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip  [你的宿主机IP]
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
EOF
done

如果 不需要对外提供服务可使用如下配置:

for port in $(seq 6379 6384);
do
mkdir -p /[你想设置的目录]/redis/node-${port}/conf
touch /[你想设置的目录]/redis/node-${port}/conf/redis.conf

docker volume create redis_${port};

cat << EOF > /[你想设置的目录]/redis/node-${port}/conf/redis.conf
port ${port}
requirepass 1234
bind 0.0.0.0
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip  127.0.0.1
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
EOF
done

将脚本写成脚本文件后执行,通过tree查看目录结构,目录结构如图
如果没有tree命令可以先安装tree(brew install tree
在这里插入图片描述
命令解释:
port:节点端口;
requirepass:设置密码,访问时需要验证
protected-mode:保护模式,默认值 yes,即开启。开启保护模式以后,需配置 bind ip 或者设置访问密码;关闭保护模式,外部网络可以直接访问;
daemonize:是否以守护线程的方式启动(后台启动),默认 no;
appendonly:是否开启 AOF 持久化模式,默认 no;
cluster-enabled:是否开启集群模式,默认 no;
cluster-config-file:集群节点信息文件;
cluster-node-timeout:集群节点连接超时时间;
cluster-announce-ip:集群节点 IP
注意: 如果你想要你的redis集群可以供外网访问,这里直接填 服务器的IP 地址即可
如若为了安全,只是在服务器内部进行访问,这里还需要做一些修改。
cluster-announce-port:集群节点映射端口;
cluster-announce-bus-port:集群节点总线端口。

坑一:redis 在官网上有说明为什么需要映射两个端口 :
在这里插入图片描述

四、创建并启动容器
1.启动Redis容器

使用如下shell脚本,一次性启动6个Redis容器:
如果 需要对外提供服务,且配置了docker虚拟网卡,使用如下配置:

for port in $(seq 6379 6384); do \
  docker run -it -d -p ${port}:${port} -p 1${port}:1${port} \
  --privileged=true -v /Users/sqs/Dev/redis/node-${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
  --privileged=true -v redis_${port}:/data \
  --restart always --name redis-${port} --net myredis --sysctl net.core.somaxconn=1024 \
  redis redis-server /usr/local/etc/redis/redis.conf
done

如果 不需要对外提供服务,可使用如下配置:

for port in $(seq 6379 6384); do \
  docker run -it -d \
  --privileged=true -v /Users/sqs/Dev/redis/node-${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
  --privileged=true -v redis_${port}:/data \
  --restart always --name redis-${port} --net host \
  redis redis-server /usr/local/etc/redis/redis.conf
done

这两个脚本的主要区别在于,第一脚本使用的端口映射,使用的网络模式是桥接模式;第二个脚本没有使用端口映射,使用的网络模式是host模式。

补充
如果使用的–net host网络模式,docker run命令中还做了端口映射的话,端口映射会被docker忽略,执行结果中会有相关提示,上面给出的脚本中已经去掉了端口映射的内容。
在这里插入图片描述

参数解释
-it:交互
-d:后台运行,容器启动完成后打印容器
–privileged:是否让docker 应用容器 获取宿主机root权限(特殊权限-)
-p :端口映射
-v:文件挂载
–sysctl参数来设置系统参数,通过这些参数来调整系统性能
–restart always:在容器退出时总是重启容器
–name :给容器取名
–net myredis :使用我们创建的虚拟网卡 (想详细了解,可以去看看Docker 网络方面知识)

如果 用的第一个脚本创建的容器,docker run成功后结果如下:
在这里插入图片描述
如果 用的第二个脚本创建的容器,docker run成功后结果如下:
在这里插入图片描述

坑二:关于脚本中为什么要创建Docker volume
在步骤三“编写配置文件”中可以看到,脚本中创建了docker volum,本质的原因就是在第四部创建并启动容器中,如果将宿主机的本地目录挂载到容器的/data目录,会出现如下的问题,所以干脆又创建了docker volume使得/data目录可以正常挂载,且能保证数据的持久化。
如果挂载的是宿主机本地的目录,执行脚本后出现如下错误:
在这里插入图片描述
查看了一下发现容器根本就没有起来
在这里插入图片描述
删除容器,重新执行脚本,发现容器没有正常运行:
在这里插入图片描述
容器的状态都是Restarting,这里真的是让人很郁闷了。
接下来使用docker logs -f [container id]来查看容器启动日志,发现如下错误:
在这里插入图片描述
从报错信息大致来看是因为没有权限,至于具体是哪里没有权限,还真的是让我一头雾水。
网上大概查了一下,主要就是因为容器没有权限操作宿主机的目录。如果是Linux环境,好像是关闭SELINUX即可,但是我这里是Mac环境,无法验证这种说法。至于MacOS环境下,有博主说是因为SIP的原因,说是需要关闭SIP,但是MacOS中SIP还是很不建议关闭的,因此这个说法也就不去实际操作验证了,所以还需要另想它法。
因此,就选择了使用docker volume来做映射的方法,命令已经写在了步骤三的脚本中,同样的也是需要创建6个。

docker volume create redis_${port};

问题:volume中的数据如何访问?
创建了volume之后,首先通过如下命令可以查看其挂载点

docker volume inspect redis_6379

在这里插入图片描述
如图所示,可以看到其挂载的目录是在/var/lib/docker/volumes下,但是在宿主机上,可以发现这个目录是不存在的。那么容器关闭后需要持久化的数据怎么办??
其实这里不用担心,虽然看不到这个目录,但是Redis的/data目录中的数据确实是持久化到我们创建的volume中的。想要访问这个目录,可以使用如下命令:

docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

这里也是启动一个容器并进入其命令行(第一次执行需要下载debian的镜像),在其中就可以访问volume所在的目录了,并且也可以方便的其中的文件拷贝到宿主机的本地目录里。

参数解释:

-即使未连接也保持标准输入打开 + 分配伪 TTY
--privileged “给出了所有功能的容器。允许特殊情况下,像跑步泊坞窗”。
--pid定义使用主机 VM 命名空间。
debian要使用的实际映像。
nsenter一个debian 的工具来在不同的命名空间中运行程序
-t是目标PID
-m挂载提供的 PID 命名空间。
-u输入 Unix 时间共享 (UTS) 命名空间。
-n输入提供的 PID 网络命名空间。
-i输入提供的 PID IPC 命名空间。
2.创建Redis Cluster集群

如果 需要对外提供服务,且配置了docker虚拟网卡,使用如下步骤创建:

可以随意选择其中一个节点进入,创建Redis集群。这里以6379节点为例:
1.进入redis-6379容器

docker exec -it redis-6379 /bin/bash

![在这里插入图片描述](https://img-blog.csdnimg.cn/f9cebd89dc4142c587aaeebdd8c8fa1f.png =400xx)
2.创建集群
进入6379容器后,在命令行执行如下命令将所有节点组建成集群:
其中的IP地址就是在redis.conf文件中的cluster-announce-ip的IP地址,也是前面最开始创建的docker虚拟网卡的网关地址。

redis-cli -a <你设置的redis密码> --cluster create [宿主机IP]:6379 [宿主机IP]:6380 [宿主机IP]:6381 [宿主机IP]:6382 [宿主机IP]:6383 [宿主机IP]:6384 --cluster-replicas 1

执行上述命令后,显示如下内容,需要输入一个yes确认配置
在这里插入图片描述
最终出现这几行内容,就说明集群创建完成。
在这里插入图片描述

如果 不需要对外提供服务,直接使用如下步骤创建:
因为docker网络模式用的host模式,创建集群时可以直接使用IP 127.0.0.1

redis-cli -a 1234 --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1

在这里插入图片描述
同样的,出现如下内容代表创建完成。
在这里插入图片描述

3.集群创建验证

可以继续在容器6379中执行:

redis-cli -c -a 1234

连接上redis后,执行cluster info,可以看到共6个节点
在这里插入图片描述
再执行cluster nodes,可以看到共六个节点,三个master,三个slave,验证没问题。
在这里插入图片描述
如果使用的是--net host网络模式及上述配置,验证截图如下:
在这里插入图片描述
在这里插入图片描述

五、集群测试
1.本地测试

我们就不在容器内测试了,直接在宿主机测试。
外网是无法测试的,因为目前是本地环境,没有公网IP。局域网也不测了先,没有那么多电脑。
主要测试逻辑就是:使用端口A set值,然后通过端口B get值,如果可以get到说明集群模式没有问题。
1.首先我们通过6380端口连接Redis集群,进行set操作,可以看到已经set成功
在这里插入图片描述
2.然后我们通过另一个master节点6381进行get操作
可以看到因为name所在的slot在6380节点上,这里会自动重定向到6380,且重定向成功
在这里插入图片描述

坑三:cluster-announce-ip如果设置的为docker内网关IP,会导致容器外部访问无法重定向
其实,之前踩坑的整个过程中,是用的docker虚拟网卡桥接的网络模式搭建一个本地可用的Redis Cluter模式集群,因为宿主机的IP也不固定,所以redis.conf文件中cluster-announce-ip设置的是docker虚拟网卡的网关地址,这样就造成了一个问题,如果进入到其中一个Redis节点的容器内,整个cluster集群是可用的。但是如果在宿主机访问这个Redis集群的时候,因为加了端口映射,6379-6384端口也都能通过127.0.0.1访问,不涉及重定向的get,set指令也都能正常执行,但是一旦涉及到slot的重定向,redis返回的重定向IP是docker容器内部的IP 172.18.0.1,这个IP在宿主机是无法访问的,因此会导致重定向失败。
在这里插入图片描述
所以,本文后来又在之前的基础上加了不需要对外提供服务的部分,即使用host网络模式搭建集群,这样就可以正常重定向了,也就可以在本地的项目中调用该redis集群了。
但是也导致了本文看起来有点复杂,有点混乱。暂时先这样吧,细心看应该还是能看懂的,毕竟也不是太难的东西。以后有时间可能改改吧,目前为止已经耗费了太多精力了。

参考资料

http://www.taodudu.cc/news/show-568884.html?action=onClick
https://www.cnblogs.com/mrhelloworld/p/docker12.html
https://blog.youkuaiyun.com/flyzing/article/details/113178480
https://zenn.dev/kentama/articles/5d79ba1e28cddd
https://qa.1r1g.com/sf/ask/2697273841/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值