Search code examples
javaredisamazon-elasticachespring-data-redislettuce

Configuring Spring Data Redis with Lettuce for ElastiCache Master/Slave


I have a Elasticache setup with one master and two slaves. I am still not sure how to pass in a list of master slave RedisURIs to construct a StatefulRedisMasterSlaveConnection for LettuceConnectionFactory. I only see support for standaloneConfiguration with single host and port.

LettuceClientConfiguration configuration = LettuceTestClientConfiguration.builder().readFrom(ReadFrom.SLAVE).build();
LettuceConnectionFactory factory = new LettuceConnectionFactory(SettingsUtils.standaloneConfiguration(),configuration);

I know there is a similar question Configuring Spring Data Redis with Lettuce for Redis master/slave

But I don't think it works for ElastiCache Master/Slave setup as currently the above code would try to use MasterSlaveTopologyProvider to discover slave ips. However, slave IP addresses are not reachable. So what's the right way to configure Spring Data Redis to make it compatible with Master/Slave ElastiCache? It seems to me LettuceConnectionFactory needs to take in a list of endpoints and use StaticMasterSlaveTopologyProvider in order to work.


Solution

  • Right now, static Master/Slave with provided endpoints is not supported by Spring Data Redis. I filed a ticket to add support for that.

    You can implement this functionality yourself by subclassing LettuceConnectionFactory, creating an own configuration and LettuceConnectionFactory.

    You would start with something like:

    public static class MyLettuceConnectionFactory extends LettuceConnectionFactory {
    
        private final MyMasterSlaveConfiguration configuration;
    
        public MyLettuceConnectionFactory(MyMasterSlaveConfiguration standaloneConfig,
                LettuceClientConfiguration clientConfig) {
            super(standaloneConfig, clientConfig);
            this.configuration = standaloneConfig;
        }
    
        @Override
        protected LettuceConnectionProvider doCreateConnectionProvider(AbstractRedisClient client, RedisCodec<?, ?> codec) {
            return new ElasticacheConnectionProvider((RedisClient) client, codec, getClientConfiguration().getReadFrom(),
                    this.configuration);
        }
    }
    
    static class MyMasterSlaveConfiguration extends RedisStandaloneConfiguration {
    
        private final List<RedisURI> endpoints;
    
        public MyMasterSlaveConfiguration(List<RedisURI> endpoints) {
            this.endpoints = endpoints;
        }
    
        public List<RedisURI> getEndpoints() {
            return endpoints;
        }
    }
    

    You can find all code in this gist, not posting all code here as it would be a wall of code.