如何将AWS Elasticache Redis集群连接到Spring Boot应用程序?

时间:2019-12-11 15:44:25

标签: amazon-web-services spring-boot redis jedis amazon-elasticache

我有使用Jedis Connection Factory连接到Redis集群的Spring Boot应用程序:

RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
redisClusterConfiguration.setPassword(redisProperties.getPassword());
jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration);

并从application.yml中读取节点列表:

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 300s
    cluster:
      nodes: 127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382

现在我们要切换到Elasticache,因为无论如何我们都在AWS上托管Redis集群。 这将很容易完成。是否可以使用AmazonElastiCache lib。 然后,我们可以使用AWS凭证连接到Elasticache集群,将可用节点放入列表中,然后将其传递给Jedis,而不是在application.yml中对其进行硬编码,例如:

//get cache cluster nodes using AWS api
private List<String> getClusterNodes(){
    AmazonElastiCache client = AmazonElastiCacheClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
    DescribeCacheClustersRequest describeCacheClustersRequest = new DescribeCacheClustersRequest();
    describeCacheClustersRequest.setShowCacheNodeInfo(true);
    List<CacheCluster> cacheClusterList = client.describeCacheClusters(describeCacheClustersRequest).getCacheClusters();
    List<String> nodeList = new ArrayList<>();
    try {
        for (CacheCluster cacheCluster : cacheClusterList) {
            for(CacheNode cacheNode :cacheCluster.getCacheNodes()) {
                String nodeAddr = cacheNode.getEndpoint().getAddress() + ":" +cacheNode.getEndpoint().getPort();
                nodeList.add(nodeAddr);
            }
        }
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    return nodeList;
}

但是DevOps团队表示,他们无法在所有实验室上配置AWS访问,并且有这样做的理由。另外,除了连接到AWS并拉动所有可用群集之外,我们还需要通过URL连接到特定群集。

因此,我尝试将Elasticache集群URL作为独立的和作为application.yml配置中的集群直接传递给Jedis。 在这两种情况下都建立了连接,但是当App尝试写入Elasticache时,它会得到MOVED异常:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.data.redis.ClusterRedirectException: Redirect: slot 1209 to 10.10.10.011:6379.; nested exception is redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 1209 10.10.10.102:6379

据我所知,这意味着App尝试写入Elasticache中的一个节点,但无法连接。

所以问题是,有没有办法仅使用Elasticache群集URL从Spring Boot应用程序连接到Elasticache Redis群集?

我知道如果使用Elasticache Memecache是​​可行的。 而且Jedis驱动程序不是硬性要求。

谢谢。

2 个答案:

答案 0 :(得分:2)

灵感来自于答案,请完成更详细的代码

List<String> nodes = Collections.singletonList("<cluster-host-name>:<port>");
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(nodes);

ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder().closeStaleConnections(true)
            .enableAllAdaptiveRefreshTriggers().build();

ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder().autoReconnect(true)
            .topologyRefreshOptions(topologyRefreshOptions).validateClusterNodeMembership(false)
            .build();
//If you want to add tuning options
LettuceClientConfiguration  lettuceClientConfiguration = LettuceClientConfiguration.builder().readFrom(ReadFrom.REPLICA_PREFERRED).clientOptions(clusterClientOptions).build();

LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
lettuceConnectionFactory.afterPropertiesSet();//**this is REQUIRED**
StringRedisTemplate redisTemplate = new StringRedisTemplate(lettuceConnectionFactory);

答案 1 :(得分:0)

经过一些研究,我们了解到,如果将AWS Elasticache集群端点设置为RedisClusterConfiguration中的一个节点,那么驱动程序(Jedis或Lettuce)就可以连接并找到Elasticache集群中的所有节点。同样,如果其中一个节点发生故障,驱动程序也可以通过其他一些节点与Elasticache群集进行通信。

在进行此升级时,我们也迁移到了Lettuce驱动程序,因为Lettuce是Spring Boot Redis Started中提供的默认驱动程序,并且支持最新的Redis版本。生菜连接也被设计为线程安全的,Jedis也并非如此。

代码示例:

List<String> nodes = Collections.singletonList("****.***.****.****.cache.amazonaws.com:6379");
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(nodes);
return new LettuceConnectionFactory(clusterConfiguration);