redis / ioredis

šŸš€ A robust, performance-focused, and full-featured Redis client for Node.js.
MIT License
14.07k stars 1.19k forks source link

Improve Cluster mode documentation, especially in AWS ElastiCache with TLS #1816

Closed rarecrumb closed 7 months ago

rarecrumb commented 10 months ago

It seems very common to have issues connecting to AWS ElastiCache in Cluster mode, with TLS enabled.

@luin can you provide examples showing how to use ioredis to connect to Redis Cluster? Extra helpful if it can actually be tested against AWS ElastiCache in Cluster mode with TLS enabled/disabled, password auth enabled/disabled.

ioredis version: v5.3.2 Redis Cluster Engine version: 7.0.7 - TLS Enabled, no password

  static async createCluster(
    connectionString: ClusterNode[],
    ioRedisClusterOpts?: ClusterOptions
  ): Promise<RedisClient> {
    const opts: ClusterOptions = {
      ...ioRedisClusterOpts,
      clusterRetryStrategy() {
        const delay = Math.min(10 * 50, 2000);
        return delay;
      },
      scaleReads: "slave",
      lazyConnect: true,
      slotsRefreshInterval: 3000,
      slotsRefreshTimeout: 10000,
      enableOfflineQueue: false,
      dnsLookup: (address, callback) => callback(null, address),
      enableReadyCheck: true,
      redisOptions: {
        family: 6,
        tls: {},
      },
    };

    const client = new IORedis.Cluster(connectionString, opts);

    await client.connect();
    return new RedisClient(client);

Errors:

2023-09-12T20:22:37.357Z ioredis:connection error: Error: getaddrinfo ENOTFOUND x.us-east-1-xxx-xxx.xxx.use1.cache.amazonaws.com    
  at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:108:26)    
  at GetAddrInfoReqWrap.callbackTrampoline (node:internal/async_hooks:130:17) 
{  errno: -3007,  code: 'ENOTFOUND',  syscall: 'getaddrinfo',  hostname: 'xxx.us-east-1-xxx-xxx.xxx.use1.cache.amazonaws.com'}

Related issues:

rarecrumb commented 10 months ago

These are the options that finally ended up working for me with ElastiCache with Cluster mode and TLS enabled:

      clusterRetryStrategy() {
        const delay = Math.min(10 * 50, 2000);
        return delay;
      },
      scaleReads: 'slave',
      lazyConnect: true,
      slotsRefreshInterval: 60000,
      slotsRefreshTimeout: 10000,
      enableOfflineQueue: true,
      enableReadyCheck: true,
      redisOptions: {
        tls:
          process.env.NODE_ENV === "production"
            ? {
                checkServerIdentity: (/*host, cert*/) => {
                  // skip certificate hostname validation
                  return undefined;
                },
              }
            : undefined,
        commandTimeout: 5000,
        connectTimeout: 10000,
        lazyConnect: true,
        enableReadyCheck: true,
        enableAutoPipelining: true,
        enableOfflineQueue: true,
        noDelay: true,
        keepAlive: 1000
      }
nrathi commented 8 months ago

@ rarecrumb how do you connect to the cluster when developing locally? I'm trying to tunnel via SSH but not sure if that's messing things up.

blshukla commented 3 months ago

We were facing a similar issue. This answer from Stack Overflow worked well for us - https://stackoverflow.com/questions/76409668/how-to-connect-to-amazon-memorydb-for-redis-from-node-running-in-ec2-ecs

sonthanhdan commented 2 months ago

These are the options that finally ended up working for me with ElastiCache with Cluster mode and TLS enabled:

      clusterRetryStrategy() {
        const delay = Math.min(10 * 50, 2000);
        return delay;
      },
      scaleReads: 'slave',
      lazyConnect: true,
      slotsRefreshInterval: 60000,
      slotsRefreshTimeout: 10000,
      enableOfflineQueue: true,
      enableReadyCheck: true,
      redisOptions: {
        tls:
          process.env.NODE_ENV === "production"
            ? {
                checkServerIdentity: (/*host, cert*/) => {
                  // skip certificate hostname validation
                  return undefined;
                },
              }
            : undefined,
        commandTimeout: 5000,
        connectTimeout: 10000,
        lazyConnect: true,
        enableReadyCheck: true,
        enableAutoPipelining: true,
        enableOfflineQueue: true,
        noDelay: true,
        keepAlive: 1000
      }

thanks @rarecrumb I tried with your config it working fine.