Harshana Harshana - 4 months ago 79
Java Question

Redis max-active configuration value for SpringBoot project

I have implement redis for a Spring boot application.

What value should I have to enter for below configuration in application.properties?

# <!-- Maximum active connections to Redis instance -->
spring.redis.pool.max-active=8


It was by default 8 in the documentation.

Then, I set it to 1 and test with multiple invocations which hits redis repo. Although I am expect a error saying, redis connections are not available, I did not get any error.

What am I missing here?

Update question:

I have below code sample to add a value to redis.

public void setEnroll(String key, TranscodeStatus enrollment) {
final String hashKey = String.valueOf(Hashing.MURMUR_HASH.hash(key));
this.stringRedisTemplate.expire(key, 30, TimeUnit.MINUTES);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("setEnroll:thread interrupt");
}
HashOperations<String, String, String> ops = this.stringRedisTemplate.opsForHash();
if (!this.stringRedisTemplate.hasKey(key)) {
String json = convertEnrollment(enrollment);
ops.put(key, hashKey, json);
}
}


I add sleep for 10 second and invoke above code again while first invocation thread in sleep. The spring.redis.pool.max-active set to 1. What I am try to achive is a redis pool not available exception when the second thread hits the stringRedisTemplate.expire line of code becuase the only 1 connection available is using the first thread.

When use below StringRedisTemplate would be singleton right?

@Autowired
private StringRedisTemplate stringRedisTemplate;


Inside StringRedisTemplate I see below two constructors,

/**
* Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
* and {@link #afterPropertiesSet()} still need to be called.
*/
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setValueSerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
setHashValueSerializer(stringSerializer);
}

/**
* Constructs a new <code>StringRedisTemplate</code> instance ready to be used.
*
* @param connectionFactory connection factory for creating new connections
*/
public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
setConnectionFactory(connectionFactory);
afterPropertiesSet();
}


Since connection pool is available, I believe Spring invoke the second constructor right?
StringRedisTemplate(RedisConnectionFactory connectionFactory)

So I think because StringRedisTemplate release its redis connection soon after execute
this.stringRedisTemplate.expire(key, 30, TimeUnit.MINUTES);
, that is why I dont see a connection out of exception even another thread try to access expire method while main thread is in sleep know.

Are those my above points are correct? Also how can I produce a connection not available exception.

Answer

In Short

It depends on what you're planning to do.

Explanation

A good value is 50% to 100% of the number of maximal concurrent requests within your application. The Redis connection is leased only for the duration of Redis operations in non-transactional mode.

You need to have commons-pool2 on your classpath the pooling setting to take effect. Earlier versions of Jedis/Spring Boot did not require commons-pool2.

When using Spring Data Redis with enabled @Transactional, the connection is bound from the first Redis access until the transaction is committed/rolled back.

If the number of max concurrent Threads seems unreasonably high and you don't use transactions/blocking operations, then you might want to take a look on the lettuce driver integration. lettuce requires only one connection but it comes at the cost of more dependencies, and you need to configure the RedisConnectionFactory on your own.

Comments