2

我正在构建一个连接到 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,但是在部署应用程序后,应用程序挂起并且连接事件永远不会触发。和事件似乎无限循环closereconnecting

据我了解,这是集群中节点之间重定向的问题。可能是主/从配置的问题。该错误是 AWS 中的配置问题吗?我需要使用Redis.Cluster对象而不是普通Redis实例吗?修复 MOVED 错误的最佳方法是什么?

4

4 回答 4

5

MOVED错误是直接使用 Redis 客户端和 ElastiCache(Redis 集群模式)的配置端点引起的。这可以通过使用new Redis.Cluster([{ host: <cfg-endpoint>])which is aware about multiple shards 来解决。

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

此外,当您启用加密时,您需要连接到启用了 TLS 的 AWS ElastiCache(tls: {}ioredis 的选项)。

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

于 2020-11-17T08:41:19.347 回答
1

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

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

GET x -MOVED 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 重定向错误。

于 2021-07-02T23:03:47.193 回答
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

于 2021-08-05T14:56:16.827 回答
0
const Redis = require("ioredis");
const connection = await new Redis.Cluster(
        [redisHost,redisPort],
        {
      scaleReads: "all",
      redisOptions: {
        username: redisUserName,
        password: redisPassword,
        enableAutoPipelining: true,
      }
      );

上面的配置解决了我的问题,我正在使用 ioredis 安装的“redis”。

于 2022-01-27T07:03:24.433 回答