0

I have a Spring boot application which uses Redis for caching. I'm trying to use Redis pipelining to get multiple information in a single call. In my @Configuration class, I have the following configuration for Redis:

@Bean
JedisConnectionFactory jedisConnectionFactory() {
    JedisConnectionFactory factory = new JedisConnectionFactory();
    factory.setHostName("...");
    factory.setPort("...");
    factory.setUsePool(true);
    return factory;
}

@Bean
RedisTemplate< String, Object > redisTemplate() {
    final RedisTemplate< String, Object > template =  new RedisTemplate< String, Object >();
    template.setConnectionFactory( jedisConnectionFactory() );
    template.setKeySerializer( new StringRedisSerializer() );
    template.setHashValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
    template.setValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
    return template;
}

I'm then trying to use pipelining to get multiple values from Redis and put it in a HashMap as below:

@Service
class MyClass{

private HashMap<String, String> cachedEntries = null;

@Autowired 
private RedisTemplate< String, Object > template;
@Autowired
private ObjectMapper mapper;

public HashMap<String, String> getCachedEntries(String key1, String key2){
    if(null == cachedEntries){
        cachedEntries = new HashMap<String, String>();
    }

    RedisCallback<Object> action = new RedisCallback<Object>() {
        @Override
        public Object doInRedis(RedisConnection connection) {
            try{
                cachedEntries.put("value1", template.opsForValue().get(key1).toString());
            } catch(Exception e){}

            try{
                cachedEntries.put("value2", template.opsForValue().get(key2).toString());
            } catch(Exception e){}

            return null;
        }
    };

    try{
        template.executePipelined(action);
    } catch(Exception e){}

}
}

Normally, this works fine and returns the values as expected. However, when my application gets lots of requests, for some reason the app freezes. But when I remove the pipelining, and get the values individually, the app works fine. Why is the app freezing? I'm new to redis pipelining, so my code might not be efficient.

Thanks.

drunkenfist
  • 2,958
  • 12
  • 39
  • 73
  • Spring Data Redis opens a pipeline that just writes data to the socket without actually synchronizing the code. 1. You're living dangerously by ignoring all exceptions. 2. The snippet from above does not benefit from pipelining. Pipelining is useful to perform a bunch of Redis operations and read the results once the pipeline gets synchronized (i.e. the calling 2x `get` and then using the result of `executePipelined` to work with the received data. – mp911de Oct 26 '16 at 20:41
  • @mp911de I have handled the exceptions. I just have not added it to the code here. So how can I get multiple values from Redis with the same command? If I do `template.opsForValue().get(key)` multiple times, isn't it going to be inefficient? How can I have just one connection, and get multiple values together? – drunkenfist Oct 26 '16 at 21:08
  • If performance matters a lot, use `MGET` – mp911de Oct 26 '16 at 21:21
  • But if I use MGET, how will I know which value belongs to which key? If there is a cache miss, there is no way to know which value maps to the key, right? – drunkenfist Oct 28 '16 at 16:03
  • Results are ordered by the requested keys – mp911de Oct 28 '16 at 16:05
  • Thanks. This works. – drunkenfist Nov 01 '16 at 16:03

0 Answers0