ioredis - ClusterAllFailedError: Failed to refresh slots cache
Asked Answered
O

5

18

I'm dealing with a ClusterAllFailedError: Failed to refresh slots cache. issue from ioredis and Elasticache. This is my clustering config

const clusterOptions = {
    enableReadyCheck: true,
    retryDelayOnClusterDown: 300,
    retryDelayOnFailover: 1000,
    retryDelayOnTryAgain: 3000,
    slotsRefreshTimeout: 200000000000000,
    clusterRetryStrategy: (times) => Math.min(times * 1000, 10000),
    dnsLookup: (address, callback) => callback(null, address),
    scaleReads: 'slave',
    showFriendlyErrorStack: true,
    redisOptions: {
        keyPrefix: config.queue.prefix,
        autoResubscribe: true,
        autoResendUnfulfilledCommands: true
    }
}

const redisClientInstance = new Redis.Cluster([{ host: '', port: ''}], clusterOptions);

But trying to access the Redis always results in a Failed refresh slots cache. Anyone else dealt with this issue?

Thank you.

Outfight answered 4/8, 2019 at 23:50 Comment(0)
U
13

The following works for me.

Redis version: 5.0.4 on AWS ElastiCache Clustered with TLS and AUTH enabled.

ioredis version: 4.16.0

Code to connect:

const redis = new Redis.Cluster(
            [{ "host": <ELASTI_CACHE_CONFIGURATION_ENDPOINT> }], {
                dnsLookup: (address, callback) => callback(null, address),
                redisOptions: {
                    tls: true,
                    password: <ELASTI_CACHE_REDIS_AUTH>
                }
            });

When you launch ElastiCache, you will need to specify one or more Subnet Group (generally private Subnets) and the Security Group. When you run the above code from any compute (Lambda, EC2 etc.), you need to ensure the following

  • ElastiCache is reachable from your Compute (Put the compute in a Subnet which can communicate with the Subnet of the ElastiCache in the same VPC. If the compute and Elasticache are on different VPCs, ensure VPC peering enabled between them.)
  • Ensure the Security Group, NACL allows the connection to ElastiCache port (6379 is the default) from your Compute Subnet
  • Finally ensure the Compute can assume an IAM Role(EC2 instance profile, Lambda Role etc) which has appropriate access to ElastiCache. In case you are running on an EC2 instance, make sure your code uses the temporary credentials of the Role assigned in the EC2 instance profile.
Usufruct answered 14/3, 2020 at 14:50 Comment(7)
What is correct VPC, Subnet, Security Group?Raynold
@VinitKhandelwal updates with more details about correct VPC, Subnet, SG etc. Highly recommend going through the documentation.Usufruct
I tried your solution, yet after sometime, it throws error 'ClusterAllFailedError: Failed to refresh slots cache'Raynold
Sadly, this still returns [ioredis] Unhandled error event: ClusterAllFailedError: Failed to refresh slots cache, for redis engine 6.2.5 and 4.16.0 of ioredisWallop
Have you tried by using enableReadyCheck: true in the client configuration?Helmer
Hi, i found some another option here. Works for my aws memorydb cluster with enabled TLS.Scarlettscarp
I have my redis hosted on aws and I am trying to connect to it from a batch job within the same AWS account and I am getting the same error in the question above. Works fine when trying to connect from local system.Intelligible
M
2

I recommend setting your client to debug mode

For ioredis you can do it like so:

DEBUG=ioredis:* node app.js

There might be an error you're not seeing

In my case there was Error: getaddrinfo ENOTFOUND printed before the Failed to refresh slots cache error was thrown

Melentha answered 28/12, 2022 at 14:15 Comment(2)
This is giving me the error 'DEBUG' is not recognized as an internal or external command, operable program or batch fileIntelligible
@Intelligible if you are on Windows the command will be different: set DEBUG=ioredis:* & node app.jsMelentha
C
1

In my case, it seems the slotsRefreshTimeout was the problem. Included the option to increase the timeout and the error is not showing anymore. Here is my connection example:

let client = new Cluster([
    { port: 6379, host: <END_POINT> }
],{
    dnsLookup: (address, callback) => callback(null, address),
    slotsRefreshTimeout: 2000,
    redisOptions: { tls: true }
});

Croatian answered 19/11, 2023 at 14:34 Comment(0)
U
0

This works for me but with small hack as i am using it in typescript, faced issue while passing null to first argument for callback function which expecting NodeJS.ErrnoException and does't want to allow using any type(due to eslint no-explicit-any rule).

I used @ts-expect-error directive above dnsLookup

    // @ts-expect-error this will ignore error
    dnsLookup: (address, callback) => callback(null, address),
Underpart answered 24/7, 2020 at 14:57 Comment(0)
B
0

Before trying any solution here, once verify that you are creating cluster with cluster mode enabled, this thing worked for me!

Here's an attached screenshot.

1

Beefeater answered 10/8, 2022 at 4:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.