首页 文章

Spring Redis模板与Jedis连接工厂,Redis独立配置和多线程

提问于
浏览
1

我在多线程环境中使用Spring Redis模板 . 一个线程将数据保存到Redis中,另一个线程(调度程序)从中获取数据 . JedisConnectionFactory用于redis模板 . 以下是用于获取redis连接的代码段:

JedisConnectionFactory jedisConnectionFactory() {

    JedisConnectionFactory jedisConnectionFactory = null;

    try {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(hostName,
                port);
        jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
    } catch (RedisConnectionFailureException e) {
        LOGGER.error("Connection break with redis " + e.getMessage());
    }

    return jedisConnectionFactory;
}

/**
 * Redis template.
 *
 * @return the redis template
 */
@Bean
public RedisTemplate<String, Object> redisTemplate() {
    final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
    template.setConnectionFactory(jedisConnectionFactory());
    template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
    template.setEnableTransactionSupport(true);
    return template;
}

使用构造函数自动连接获取redis模板的实例,如下所示:

@Autowired
public A(RedisTemplate<String, Object> redisTemplate) {
    this.redisTemplate = redisTemplate;
}

我使用redis模板的“findAll()”方法从Redis获取数据时遇到异常:

org.springframework.data.redis.RedisConnectionFailureException:java.net.SocketException:peer by peer:socket write error;嵌套异常是redis.clients.jedis.exceptions.JedisConnectionException:java.net.SocketException:通过对等方重置连接:套接字写入错误

以下是我的发现:

当TCP套接字要"closing"并且您的代码尚未得到通知时,会发生

  • 连接由对等异常重置 . (对于已关闭的连接,尚未通知findAll的线程) .

  • Redis模板是线程安全的(仅在使用连接池时)并且自己处理连接管理 . 可能会发生这样的情况:当线程将数据保存到redis并关闭连接时,仅在此期间,发生了获取操作并要求数据 . 在这种情况下,服务器可能已发出RST命令,但获取操作可能尚未获取它 .

  • 可以使用Jedis池配置;但是有一些折旧的方法可以在以后导致升级问题 .

请建议使用“JedisConnectionFactory”,“RedisStandAloneConfiguration”和“RedisTemplate”处理多线程的最佳方法 .

1 回答

  • 0

    The cause of this problem was :

    Redis模板是线程安全的,但只有当它使用连接池时;如果未使用连接池,则同时连接调用将导致来自(服务器/客户端)端的RST信号,从而抛出“由对等连接重置”异常 . 因此,如果我们需要使用Redis模板,则创建一个连接池并为池配置设置'maxIdle'和'maxTotal' . 此外,确保系统在任何情况下都不应该停机(睡眠) .

    Code that worked correctly:

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
    
        JedisConnectionFactory jedisConnectionFactory = null;
    
        try {
            RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(hostName,
                    port);
            jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
            jedisConnectionFactory.getPoolConfig().setMaxTotal(50);
            jedisConnectionFactory.getPoolConfig().setMaxIdle(50);
        } catch (RedisConnectionFailureException e) {
            e.getMessage();
        }
    
        return jedisConnectionFactory;
    }
    
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
        template.setEnableTransactionSupport(true);
        return template;
    }
    

相关问题