当前位置: 首页 > 知识库问答 >
问题:

在docker conatiners中连接到以哨兵模式运行的redis主节点时出现问题

桂阳文
2023-03-14

我在docker容器中运行redis,我使用redis sentinel模式。我已经设置了以下配置-

3 redis sentinels nodes
1 redis master node
2 redis slave nodes

我使用Redisson库创建了一个Java客户机来访问Redis。将客户端配置为使用redis-sentinel模式,如下所示-

Config config = new Config();
config.useSentinelServers()
       .setMasterName("redis-master")
       .addSentinelAddress("redis://127.0.0.1:26379")
       .addSentinelAddress("redis://127.0.0.1:26380")
       .addSentinelAddress("redis://127.0.0.1:26381")

RedissonClient client = Redisson.create(config);

这就是我面临的问题。每当我试图通过这个客户机在redis上运行一些命令时,请求都会通过哨兵节点,这会给我当前的redis主节点地址。但是我的java客户机不能直接与redis master通信,因为sentinel节点返回的ip是master节点的internel docker network ip,在docker网络之外无法访问,它失败了,异常如下所示-

Exception in thread "main" org.redisson.client.RedisConnectionException: Unable to connect to Redis server: 172.21.0.2/172.21.0.2:6379
    at org.redisson.connection.pool.ConnectionPool$2$1.operationComplete(ConnectionPool.java:161)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)

如何解决这个问题?我需要在一些不同的网络模式下运行它吗?或者用某种方法将内部docker ip转换为运行docker Conatiners的机器的实际ip?

共有1个答案

东郭俊楠
2023-03-14

我今天也遇到了这个问题,试图为一个测试实例设置这个问题。我最初的撰写文件基于https://blog.alexseifert.com/2016/11/14/using-redis-sentinel-with-docker-compose/,并根据我的需要进行了修改。我可以通过以下方法找到解决办法:1)将端口绑定到我的主机,2)在docker-compose中设置depends_on标志,以及3)将sentinel.conf设置为指向我的主机运行的主机名:https://docs.docker.com/compose/startup-order/

这有点难以解释,但我会尽我所能:您的主/副本将在docker-compose中如下所示:

  redis-master:
    image: redis:5.0.4-alpine
    volumes:
      - <mounted-data-directory>
      - "<local-master-config-directory>/redis.conf:/usr/local/etc/redis/redis.conf"
    ports:
      - "6379:6379"
    command:
      - redis-server
      - /usr/local/etc/redis/redis.conf

  redis-replica:
    image: redis:5.0.4-alpine
    links:
      - redis-master
    volumes:
      - <mounted-data-directory>
      - "<local-replica-config-directory>:/usr/local/etc/redis/redis.conf"
    ports:
      - "6380:6380"
    depends_on:
      - redis-master
    command:
      - redis-server
      - /usr/local/etc/redis/redis.conf
      - --slaveof redis-master 6379

对于我的哨兵,我给了每个Dockerfile和一个sentinel.conf(每个都有不同的端口):Dockerfile:

FROM redis:5.0.4-alpine
RUN mkdir -p /redis
WORKDIR /redis
COPY sentinel.conf .
RUN chown redis:redis /redis/*
ENTRYPOINT ["redis-server", "/redis/sentinel.conf", "--sentinel"]

Sentinel.conf

port 26379
dir /tmp
bind 0.0.0.0
sentinel monitor mymaster <hostname> 6379 2
sentinel down-after-milliseconds mymaster 1000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000

每个sentinel(我有三个)都有一个单独的条目,引用它们的构建上下文,并将sentinel.conf中的端口映射到本地端口。所以在docker-compose中,我的哨兵是这样的:

 # Instance 1
  redis-sentinel:
    build:
      context: <path-to-context>
    links:
      - redis-master
    ports:
      - "26379:26379"
    depends_on:
      - redis-replica

我所做的绝对是一个黑客,我不会在生产中这样做。我很确定docker有一个更好的网络解决方案,我只是不想为我需要测试的东西走得太远。希望这能有所帮助。

 类似资料:
  • 主要内容:哨兵模式原理,哨兵模式应用,sentinel.conf配置项在 Redis 主从复制模式中,因为系统不具备自动恢复的功能,所以当主服务器(master)宕机后,需要手动把一台从服务器(slave)切换为主服务器。在这个过程中,不仅需要人为干预,而且还会造成一段时间内服务器处于不可用状态,同时数据安全性也得不到保障,因此主从模式的可用性较低,不适用于线上生产环境。 Redis 官方推荐一种高可用方案,也就是 Redis Sentinel 哨兵模式,它弥补了主

  • 是Jedis这种客户端连接了哨兵后,得到了主从节点缓存到本地,发起命令之前解析命令是读or写,然后请求具体的节点? 还是sentinel统一解析了命令,再做转发?这个过程有负载均衡吗? 网上大多资料介绍读写分离,大多都只是在说主从复制的事,并没有讲解读写分离的过程。 我怎么就知道这个命令是发到从节点执行了呢?

  • Redis 哨兵(Sentinel)是 Redis 的高可用性(Hight Availability)解决方案:由一个或多个 Sentinel 实例组成的 Sentinel 系统可以监视任意多个主服务器,以及这些主服务器的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。 Sentinel

  • 每一个哨兵都可以连接到我的主人,并可以看到奴隶。它们能够独立地检测主从是否倒下。问题是哨兵们无法探测到对方。 我已经验证了每个哨兵都像预期的那样向通道发布消息,但似乎没有一个哨兵真正从其他哨兵通道接收消息。 我怎么让哨兵们见面?

  • Redis4.x是否兼容使用Sentinels运行TLS?我发现一些线程提到对TLS的支持将被添加到3.2中,但没有任何证实。

  • 下面是我的情况:我有一个现有的主从Redis架构(2个不同的服务器)。 我想添加Redis sentinel,以便能够使用自动故障转移,但我不想在生产中出现任何停机时间。由于sentinel需要知道主服务器,但由于我需要重新启动Redis才能启动sentinel(从而切换主服务器和从服务器),我如何在没有停机时间的情况下做到这一点?