If both Lettuce and Jedis exist on the classpath, LettuceConnectionConfiguration and JedisConnectionConfiguration will be created, but actually JedisConnectionConfiguration is not necessary. It is recommended to add redis client type configuration, for example: spring.redis.client.type=jedisspring.redis.client.type=lettuce

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class })
@ConditionalOnProperty(name = "spring.redis.client.type", havingValue = "jedis", matchIfMissing = true)
class JedisConnectionConfiguration extends RedisConnectionConfiguration {
      //...
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisClient.class)
@ConditionalOnProperty(name = "spring.redis.client.type", havingValue = "lettuce", matchIfMissing = true)
class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
     //...
}

Comment From: wilkinsona

If both Lettuce and Jedis are on the classpath, Lettuce should win. LettuceConnectionConfiguration will define its redisConnectionFactory bean and the equivalent bean in JedisConnectionConfiguration should then back off as it is @ConditionalOnMissingBean(RedisConnectionFactory.class).

If you have both Lettuce and Jedis on the classpath, there's no easy way to use Jedis and a property could help with that (and would align with what we've done for JDBC datasources). I'm not sure what you mean by "JedisConnectionConfiguration is invalid" though. Could you expand on that a bit please?

Comment From: brucelwl

@wilkinsona 1. If both Lettuce and Jedis are on the classpath, Lettuce should win. But now it seems that i can't specify the reids client type 2. if Lettuce win,JedisConnectionConfiguration is not necessary to register in the spring container

Comment From: wilkinsona

if Lettuce win,JedisConnectionConfiguration is not necessary to register in the spring container

This could be addressed by moving the @ConditionalOnMissingBean(RedisConnectionFactory.class) from the @Bean method to the class.

If both Lettuce and Jedis are on the classpath, Lettuce should win. But now it seems that i can't specify the reids client type

Thanks. I understand what you're suggesting now.

Comment From: onobc

@wilkinsona I was going to head out on this unless you plan on doing so.

My intention is to add the client type property and use that to choose the connection factory as suggested above. That also brings up a question for RedisProperties. There is a clientName property currently. Should we add another clientType or go ahead and split into its own property object -> client.name client.type. ?

Comment From: snicoll

I am having second though about this one. As far as I remember, Jedis in in maintenance mode and Lettuce is the recommended choice. There are a number of things the user could do for this particular problem:

  • If Jedis is brought by a dependency, they can fine tune their build to exclude the unwanted dependency
  • They can exclude the Lettuce auto-configuration

I know we've considered dropping support for Jedis at some point. If that's still the target, I don't think exposing a property for it makes sense.

Paging @mp911de for more feedback.

Comment From: onobc

In light of that info about Jedis, it does not seem like more effort should be added in this area.

they can fine tune their build to exclude the unwanted dependency

One technique that has worked for me is to leverage Gradle capabilities to force users to choose between a set of "mutually exclusive" dependencies.

Comment From: snicoll

@brucelwl can you please expand a bit on your use case? Why do you have both lettuce and jedis on the classpath? If you prefer Jedis, wouldn't it be better to exclude lettuce?

Comment From: brucelwl

@brucelwl can you please expand a bit on your use case? Why do you have both lettuce and jedis on the classpath? If you prefer Jedis, wouldn't it be better to exclude lettuce?

If the whole project is developed by the team itself, we can select only one client type. However, sometimes we use toolkits developed by other teams. If they use lettuce and we use jedis, and we usejedis native client instead of RedisTemplate, For us, switching from jedis to lettuce is not a simple dependency change. It may involve changes in the underlying code implementation. However, we may not be able to take a greater risk and hope that the two clients will coexist

Comment From: snicoll

It looks like you’d like Spring Boot to configure both lettuce and Jedis in your app. Is this correct?

Comment From: brucelwl

It looks like you’d like Spring Boot to configure both lettuce and Jedis in your app. Is this correct?

I hope springboot auto configure can support specifying redis client types when both Jedis and Lettuce are on the classpath

Just like spring boot, it supports specifying the DataSource type.

At present, we do have both Lettuce and Jedis in our project, but at this time, we can't choose jedis as the underlying dependency of RedisTemplate or RedisConnectionFactory

Comment From: snicoll

I have to assume the answer to my question is no. If you can’t exclude lettuce from the classpath and you want to configure jedis, you could exclude LettuceAutoConfiguration. Can you please try that?

Comment From: brucelwl

I have to assume the answer to my question is no. If you can’t exclude lettuce from the classpath and you want to configure jedis, you could exclude LettuceAutoConfiguration. Can you please try that?

This solution is feasible, but I hope that springboot can simplify the implementation, and the implementation is the best as @wilkinsona and @bono007 replies

Comment From: onobc

I was going to suggest that using the property form for auto-config exclusion

spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration

would be the same mechanism (setting a property) and have the same effect as setting the proposed property

spring.redis.client.type=jedis 

with the caveat that it's not straightforward that those mean the same thing.

However, I went to verify this approach and realized that there is no LettuceAutoConfiguration. RedisAutoConfiguration imports both Lettuce and Jedis configuration. Exclusion ends w/ the following:

java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
    - org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration

Comment From: snicoll

Just like spring boot, it supports specifying the DataSource type.

I don't think that's a valid analogy. As we've indicated above, Jedis is not being actively maintained these days and it's not unlikely we would deprecate its support and ultimately remove it from Spring Boot in a future release. Introducing now a property that makes it look like it's actively supported (like the connection pools are) is misleading to our users. We've actually discussed this at our team meeting last week and are in agreement not to introduce this property if there is a reasonable way to opt-out from Lettuce.

However, I went to verify this approach and realized that there is no LettuceAutoConfiguration. RedisAutoConfiguration imports both Lettuce and Jedis configuration.

Thanks @bono007, I overlooked this part when I suggested to exclude the lettuce auto-configuration. We'll have to discuss this one some more then.

Comment From: brucelwl

@snicoll I want to know why springboot does not support jedis in a future release. It seems that jedis is better than lettuce in the case of cluster topology changes

Comment From: onobc

@snicoll it would be low effort for me to move the connection configs to 1st class auto-configs and break the manual imports from RedisAutoConfiguration. That would allow the suggested workaround.

Comment From: mp911de

It seems that jedis is better than lettuce in the case of cluster topology changes

Care to elaborate @brucelwl? Jedis provides no mechanism to react to topology changes other than MOVED redirections. Spring Data Redis uses is required to use topology cache that expires after 100ms (by default) which leads to topology polling every 100ms causing a severe load on Redis Clusters.

Lettuce allows for periodic and adaptive topology refresh with a much more fine-grained level of control.

Comment From: brucelwl

@mp911de Thank you for your reply

Comment From: snicoll

We've discussed this one more time and introducing a JedisAutoConfiguration and LettuceAutoConfiguration so that users that prefer Jedis while having Lettuce on the classpath feels way more invasive than introducing a property so we'll do that.

Comment From: snicoll

Closing in favour of PR #22569