背景
在使用 Docker 部署 redis 集群时,我们通常会使用 redis-sentinel 来实现高可用性。然而,在某些情况下,我们可能会遇到 redis-sentinel 启动时提示 “找不到 master” 的错误,导致服务无法正常启动。本文将介绍这个问题的原因和解决方案。
问题分析
在 Docker 环境下,我们通常会使用 Docker Compose 来管理多个容器。假设我们的 redis 集群由 3 个节点组成,其中一个节点作为 master,其余两个节点作为 slave。我们在启动 sentinel 容器时,需要指定 master 的 IP 和端口号。通常情况下,我们会使用 Docker Compose 中的服务名来指定 master 的 IP,例如:
// www.javascriptcn.com code example
redis-sentinel:
image: redis
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
environment:
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PORT=6379这里的 REDIS_MASTER_HOST 参数指定了 master 节点的 IP,使用了 Docker Compose 中的服务名 redis-master。然而,当 sentinel 容器启动时,可能会提示 “找不到 master” 的错误,如下所示:
// www.javascriptcn.com code example 1:X 06 Jul 2021 17:04:34.913 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:35.914 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:36.915 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:37.915 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:38.916 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:39.917 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:40.918 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:41.919 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:42.920 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:43.921 # Could not connect to redis-master:6379 1:X 06 Jul 2021 17:04:44.922 # Sentinel runid is 0f7b0c8d2f7d8701d9f7a3c8a06d3b3b3e2a2a8b 1:X 06 Jul 2021 17:04:44.922 # +slave-reconf-sentinel redis-slave-2 172.23.0.3 6379 @ redis-master 6379 1:X 06 Jul 2021 17:04:44.922 # +slave-reconf-sentinel redis-slave-1 172.23.0.2 6379 @ redis-master 6379 1:X 06 Jul 2021 17:04:44.923 # +sdown master redis-master 172.23.0.4 6379 1:X 06 Jul 2021 17:04:45.923 # +new-epoch 1 1:X 06 Jul 2021 17:04:45.923 # +vote-for-leader 0f7b0c8d2f7d8701d9f7a3c8a06d3b3b3e2a2a8b 1 1:X 06 Jul 2021 17:04:46.924 # +odown master redis-master 172.23.0.4 6379 #quorum 2/2 1:X 06 Jul 2021 17:04:46.924 # Next failover delay: I will not start a failover before Wed Jul 7 00:04:46 2021 1:X 06 Jul 2021 17:04:47.925 # +sdown master redis-master 172.23.0.4 6379
这个错误的原因是,Docker Compose 中的服务名只在容器之间起作用,而在 sentinel 容器内部,这个服务名是无法解析的。因此,当 sentinel 容器启动时,无法连接到 master 节点,从而导致启动失败。
解决方案
为了解决这个问题,我们需要在 sentinel 容器内部映射 master 节点的 IP 地址。具体来说,我们可以在启动 sentinel 容器时,通过环境变量传递 master 节点的 IP 地址,然后在容器内部使用这个 IP 地址来连接 master 节点。例如:
// www.javascriptcn.com code example
redis-sentinel:
image: redis
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
environment:
- REDIS_MASTER_HOST=172.23.0.4
- REDIS_MASTER_PORT=6379这里的 REDIS_MASTER_HOST 参数指定了 master 节点的 IP,而不是使用 Docker Compose 中的服务名。在 sentinel 容器内部,我们可以通过环境变量来获取这个 IP 地址,然后使用它来连接 master 节点。例如,在 sentinel.conf 文件中,我们可以这样配置 master 节点的地址:
sentinel monitor mymaster ${REDIS_MASTER_HOST} ${REDIS_MASTER_PORT} 2这里的 ${REDIS_MASTER_HOST} 和 ${REDIS_MASTER_PORT} 分别表示环境变量 REDIS_MASTER_HOST 和 REDIS_MASTER_PORT 的值。这样,在启动 sentinel 容器时,就可以正确连接 master 节点,从而避免 “找不到 master” 的错误。
示例代码
完整的 Docker Compose 文件和 sentinel.conf 文件示例代码如下:
// www.javascriptcn.com code example
version: '3'
services:
redis-master:
image: redis
command: redis-server --requirepass password --appendonly yes
volumes:
- ./data/master:/data
environment:
- REDIS_PASSWORD=password
redis-slave-1:
image: redis
command: redis-server --requirepass password --slaveof redis-master 6379 --appendonly yes
volumes:
- ./data/slave-1:/data
environment:
- REDIS_PASSWORD=password
redis-slave-2:
image: redis
command: redis-server --requirepass password --slaveof redis-master 6379 --appendonly yes
volumes:
- ./data/slave-2:/data
environment:
- REDIS_PASSWORD=password
redis-sentinel:
image: redis
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
environment:
- REDIS_MASTER_HOST=172.23.0.4
- REDIS_MASTER_PORT=6379
volumes:
redis-master-data:
redis-slave-1-data:
redis-slave-2-data:# sentinel.conf
sentinel monitor mymaster ${REDIS_MASTER_HOST} ${REDIS_MASTER_PORT} 2
sentinel auth-pass mymaster ${REDIS_PASSWORD}在使用这个 Docker Compose 文件启动 redis 集群时,我们可以通过以下命令启动 sentinel 容器:
docker-compose up -d redis-sentinel
这样,sentinel 容器就可以正确连接 master 节点,从而实现高可用性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d104ada941bf7134233118