微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ReplyError:连接到Redis Cluster AWS

如何解决ReplyError:连接到Redis Cluster AWS

我正在构建连接到Redis的Node.js应用。我在本地的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错误的最佳方法是什么?

解决方法

MOVED错误是由直接使用Redis客户端和ElastiCache(Redis群集模式)的配置端点引起的。这可以通过使用知道多个分片的new Redis.Cluster([{ host: <cfg-endpoint>])或通过禁用Redis群集模式(单个分片)并使用主(主)dns名称来解决。

即使没有Redis群集模式,也仍然存在故障转移策略(AWS在发生故障时将替换主节点),并且您可以将节点部署到多个可用区中。

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

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

,

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

如果哈希槽由节点提供,则查询被简单处理,否则节点将检查其内部哈希槽到节点映射,并以 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 重定向错误。

,

如果这没有帮助:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。