【问题标题】:Using Lettuce with RedisTemplate throws exceptions将 Lettuce 与 RedisTemplate 一起使用会引发异常
【发布时间】:2018-11-24 11:49:24
【问题描述】:

我试图弄清楚为什么生菜在我运行性能测试时给我带来这么多问题,并将其与 Jedis 进行比较。

我正在使用 spring-data-redis 1.8.11.RELEASE 并为接口创建自定义代理 bean,以通过 RedisTemplate 访问 redis。 Redis 在 AWS 中运行,我使用 AWS 提供的集群配置端点作为具有 3 个主节点和 3 个从节点的节点。在性能测试期间没有什么特别的事情发生。我只是调用一个使用 RedisTemplate 从 redis 读取值的服务。

使用 JedisConnectionFactory 时测试总是无异常通过,但是当我切换到 LettuceConnnectionFactory 时,我无法完成任何测试,因为通道初始化总是超时。我将超时时间增加到 30 秒,并像在遇到线程中断异常之前一样调整了关闭计时器。但是,即使是 30 多岁,它仍然会超时。我尝试过使用共享本机连接并且没有和许多不同的超时值,它们都会导致相同的问题。

连接工厂bean的代码:

@Bean
public RedisConnectionFactory lettuceConnectionFactory() {
    RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(Arrays.asList(cacheProps.nodes));
    clusterConfig.setMaxRedirects(6);
    LettuceConnectionFactory factory = new LettuceConnectionFactory(clusterConfig);
    factory.setTimeout(30000);
    factory.setShutdownTimeout(20000);
    return factory;
}

我尝试调整 ClientResources 的线程数,但仍然出现超时错误:

ClientResources res = DefaultClientResources.builder()
            .ioThreadPoolSize(10)
            .computationThreadPoolSize(10)
            .build();

访问Redis的代码只是通过RedisTemplate:

BoundHashOperations<Object, Object, Object> hashOps = redisTemplate.boundHashOps(request.getHashKey());
String data = (String) hashOps.get(request.getSubKey());
long timeout = request.getTtl();
try {
    if (timeout != 0) {
        hashOps.expire(timeout, request.getTimeUnit());
    }
    return mapper.readValue(data, request.getType());
} catch (Exception e) {
    logger.error("Exception for hash value read.", e);
}

测试时出现异常的根本原因:

Caused by: io.netty.channel.ConnectTimeoutException: connection timed out: /x.x.x.x:6379
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe$1.run(AbstractNioChannel.java:216)
at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:120)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:408)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:402)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)

我在这里缺少什么?从我阅读的所有内容来看,似乎每个人都更喜欢生菜,但从我的测试中我看不出为什么。

【问题讨论】:

  • 您是否尝试过上述端点/端口是否接受来自您尝试连接的主机的连接?
  • 是的,确实如此。直到基准测试大约 20% 时它才会开始超时。无论如何,我为连接编写了自己的自定义对象池,现在我没有超时。现在的问题是吞吐量跟不上 Jedis。略低于 40-50 ops/s。

标签: java redis spring-data-redis lettuce


【解决方案1】:

尝试连接池和管道

  private GenericObjectPoolConfig getPoolConfig() {
    GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
    //All below should use the propertysources;
    poolConfig.setMaxTotal(20);
    poolConfig.setMaxIdle(20);
    poolConfig.setMinIdle(0);
    return poolConfig;
  }

  @Bean
  @Primary
  public RedisConnectionFactory redisConnectionFactory() {
    DefaultLettucePool lettucePool = new DefaultLettucePool(redisHost, Integer.valueOf(redisPort).intValue(), getPoolConfig());
    lettucePool.setPassword(redisPass);
    lettucePool.afterPropertiesSet();
    LettuceConnectionFactory clientConfig = new LettuceConnectionFactory(lettucePool);
    clientConfig.afterPropertiesSet();
    return clientConfig;
  }

  @Bean
  public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    return template;
  }

【讨论】:

  • 是的,我可以这样做,但我会反对使用集群支持。我正在连接到集群的 redis。这不使用集群配置和集群客户端。
猜你喜欢
  • 2018-06-01
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多