Skip to content

JedisClusterConnectionHandler.initializeSlotsCache can result in two entries for a single redis instance #1229

@roblg

Description

@roblg

Expected behavior

It seems like JedisCluster should always have exactly one Jedis instance per redis server. It should compute its lists of nodes from cluster slots (or cluster nodes -- I forget which one is recommended now), and it shouldn't add the start nodes, since they should already be in the list anyway.

(i.e., I think the behavior would be correct if these lines were removed from JedisClusterConnectionHandler line ~50:

    for (HostAndPort node : startNodes) {
      cache.setNodeIfNotExist(node);
    }

Actual behavior

JedisClusterConnectionHandler.initializeSlotsCache initializes the slots cache by querying the redis server, and also adds whatever startNodes it was given. If the start nodes were given as hostnames, this will result in two entries for each start node: one for the host name, and one for the IP address reported by cluster slots. Queries against the cluster continue to work, but iterating over the nodes in the cluster (e.g., for aggregating per-node stats) also includes these bogus entries.

Steps to reproduce:

Our setup:

  1. Two redis instances running on separate machines, named redis-1 and redis-2
  2. Java application running on a third machine: jobs-1. Specifies cluster start nodes as redis-1:6379, redis-2:6379.
  3. Iterate through pool nodes with:
for (JedisPool pool : cluster.getClusterNodes().values()) {
    try (Jedis jedis = pool.getResource()) {
        // do stuff
    } catch (Exception e) {
        // we hit this exception any time `pool.getResource()` returns one of the "phantom" nodes w/ hostname instead of IP 
    }
}

We have a workaround that allows us to specify per-machine hostnames (we just us InetAddress to do a DNS lookup of the IP before we send it to jedis), BUT it would be really nice to be able to pass the host name of a load-balancer pool to Jedis for service discovery. It could make an initial query to that machine, learn all the node info from cluster slots, and that way we wouldn't need any hard-coded IP address or machine names in our configuration.

If this seems like a reasonable approach, LMK and I'll attempt a PR.

Thanks!

Redis / Jedis Configuration

Jedis version:

2.8.0

Redis version:

3.0.x

Java version:

8.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions