ReplyError:连接到 Redis 集群 AWS 后发生 MOVED 错误

问题描述 投票:0回答:5

我正在构建一个连接到 Redis 的 Nodejs 应用程序。我将此与我的本地 redis 实例一起使用。现在,我使用

ioredis
从我的 Nodejs 应用程序连接到 AWS 中 k8s 中的 Redis 集群。这是我所拥有的。

const Redis = require("ioredis");

this.redis = new Redis({
 port: 6379, // Redis port
 host: rhost, // Redis host
 password: password
});

this.redis.on('connect', () => {
 console.log('connected to redis')
})

我似乎已成功连接到集群,日志中打印出消息

connected to redis
。然而,每次我尝试使用我的 redis 对象时,我都会收到 MOVED 错误:

UnhandledPromiseRejectionWarning: ReplyError: MOVED 5011 <ip address>:6379
  at parseError (/node_modules/ioredis/node_modules/redis-parser/lib/parser.js:179:12)
  at parseType (/node_modules/ioredis/node_modules/redis-parser/lib/parser.js:302:14)

该连接在我的本地工作。然而,在 AWS 中却并非如此。我尝试使用

Redis.Cluster
对象而不是
Redis
进行交换,但在部署应用程序后,应用程序挂起并且连接事件永远不会触发。
close
reconnecting
事件似乎无限循环。

根据我的理解,这是集群中节点之间重定向的问题。可能是主/从配置的问题。该错误是 AWS 中的配置问题吗?我是否需要使用

Redis.Cluster
对象而不是普通的
Redis
实例?修复 MOVED 错误的最佳方法是什么?

redis node-redis ioredis
5个回答
12
投票

MOVED
错误是由于直接使用Redis客户端和ElastiCache(Redis集群模式)的配置端点引起的。这可以通过使用
new Redis.Cluster([{ host: <cfg-endpoint>])
来解决,它可以识别多个分片。

否则,请禁用 Redis 集群模式并使用 ElastiCache 集群的主 (主) DNS 名称。即使没有 Redis 集群模式,仍然有故障转移策略(AWS 将在主节点发生故障时替换主节点),并且您可以将节点部署到多个可用区。

此外,当您启用加密时,您将需要连接到启用了 TLS 的 AWS ElastiCache(ioredis 的

tls: {}
选项)。

https://aws.amazon.com/blogs/database/work-with-cluster-mode-on-amazon-elasticache-for-redis/


2
投票

您可以在此处阅读有关 MOVE 错误的更多信息: https://redis.io/topics/cluster-spec#moved-redirection “移动重定向 Redis 客户端可以自由地将查询发送到集群中的每个节点,包括从节点。节点会分析查询,如果可以接受(即查询中只提到了一个键,或者提到的多个键都属于同一个哈希槽),它将查找哪个节点负责该哈希槽钥匙所属的地方。

如果哈希槽由节点提供,则简单地处理查询,否则节点将检查其内部哈希槽到节点映射,并向客户端回复 MOVED 错误,如下例所示:

获取x -已移动 3999 127.0.0.1:6381 该错误包括密钥的哈希槽 (3999) 和可以服务查询的实例的 ip:port。客户端需要向指定节点的IP地址和端口重新发出查询。请注意,即使客户端在重新发出查询之前等待很长时间,并且在此期间集群配置发生更改,如果哈希槽 3999 现在由另一个节点提供服务,则目标节点将再次回复 MOVED 错误。如果联系的节点没有更新信息,也会发生同样的情况。”

ioredis 支持redis 集群。所以你应该像这样创建 Redis 集群:

new Redis.Cluster([{
    host: process.env.REDIS_ENDPOINT, // Configuration endpoint address from Elasticache
    port: process.env.REDIS_PORT
  }]);

ioredis 将处理 MOVE 重定向错误。


1
投票
const Redis = require("ioredis");
const connection = await new Redis.Cluster(
        [redisHost,redisPort],
        {
      scaleReads: "all",
      redisOptions: {
        username: redisUserName,
        password: redisPassword,
        enableAutoPipelining: true,
      }
      );

上述配置解决了我的问题,我正在使用 ioredis 代替“redis”。


0
投票

如果这没有帮助:

const Redis = require('ioredis');

const ioCluster = new Redis.Cluster([redisConfig.redis]);
const slackQueue = new Queue('slack notifications', {
  prefix: '{slack}' ,
  createClient: () => ioCluster
});
const emailQueue = new Queue('email notifications', {
  prefix: '{email}' ,
  createClient: () => ioCluster
});

我会不使用 ioredis 或尝试将 redis 引擎降级到 4.x


0
投票

我也遇到了同样的问题,因为我使用了与 Redis 集群模式不兼容的

new Redis()
实例。 我正在使用最新版本的
[ioredis][1]
包(
5.3.2
)。 为了兼容Redis集群,请尝试以下配置,

//import section
  import { Cluster, Redis } from 'ioredis';

// connection config
   const connection = new Cluster([{
          host: process.env.host,
          port: parseInt(process.env.port),
        }], {
          slotsRefreshTimeout: 2000,
          // dnsLookup: This is needed when the addresses of startup nodes are hostnames instead of IPs.
          dnsLookup: (address, callback) => callback(null, address),
          redisOptions: {
            username: process.env.username,
            password: process.env.password,
            tls: {},
          }
    });

以上解决方案已经过尝试和测试!

© www.soinside.com 2019 - 2024. All rights reserved.