javaspring-bootredisspring-data-redislettuce

Is it possible to find keys which are on different shards using Lettuce using Spring Data Redis


I am using Spring Data Redis in my API. I am trying run the following command through Java:

Set<String> union = redisTemplate.opsForSet().union(ids);

which is causing CROSSSLOT Keys in request don't hash to the same slot err since keys I am searching are on different shards.

My Redis db model is having SET datamodel for keys which I am trying to find.

Is there any way Lettuce can find keys across shards and I can avoid this err. My LettuceConnectionFactory is as it is:

@Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setDatabase(database);
        if (StringUtils.isNotBlank(password)) redisStandaloneConfiguration.setPassword(password);

        LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = LettuceClientConfiguration.builder();
        if (useSSl) {
            builder.useSsl();
        }

        LettuceClientConfiguration clientConfiguration = builder
                .commandTimeout(Duration.ofSeconds(redisTimeoutMillis))
                .clientOptions(ClientOptions
                        .builder()
                        .disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
                        .build())
                .build();

        LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfiguration);
        connectionFactory.afterPropertiesSet();

        return connectionFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        return template;
    }

Also, is it possible to avoid union operation and use org.springframework.data.repository.CrudRepository findAllByIds(ids) to get the same output?


Solution

  • After researching a lot, I've found some info on why you are facing this CROSSSLOT error with Redis.

    There is a good explanatory blog here on CROSSSLOT KEYS issue. Please read it.

    From that blog, the following things can be concluded.

    Reason of the error:

    This error occurs when you try to perform an operation that involves multiple keys in a Redis Cluster, but those keys do not belong to the same hash slot.

    Possible solutions suggested that you can take to mitigate the issue:

    Read the blog for information.


    Follow these Github issues given below for reference:

    First of all, don't get mislead with the use of keyword 'Spring OAuth2'. The issue is the same as that you are facing.

    Note: Slot != Shard

    The main thing I want to mention is multiple hashed slots are getting created by keys within the shard and getting them from multiple slots by cross operation is not allowed.

    Now, I guess most probably you are using single node configuration by looking at your code. So, please stop running cluster mode for redis.


    Now, coming to this question

    Also, is it possible to avoid union operation and use org.springframework.data.repository.CrudRepository findAllByIds(ids) to get the same output?

    Yes, it's possible to achieve via Redis-OM for Spring library and Redis Stack Server which comes with enhanced features for Search and Query.

    Official Redis-OM Docs says:

    Redis OM Spring provides powerful repository and custom object-mapping abstractions built on top of the amazing Spring Data Redis (SDR) framework.

    Now, step - by - step process:

    1. Download Redis Stack from here based on the OS.
    2. Extract the downloaded zip and go into bin folder of redis stack and run the executable file redis-stack-server.

    Note: I'm using macOS, Java 17, Spring Boot 2.7.x and Redis 7.2.1 to demonstrate this.

    1. Open two terminals and run the redis-stack-server file and redis-cli file on each terminal respectively.

    2. Now, in CLI mode, Enter the command MONITOR. to start tracking any activities happening on the redis server.

    3. Coming to codebase:

    I took help of their Redis-OM Spring tutorial for hashes for reference.

    You will need to include redis-om-spring and spring-boot-starter-data-redis as dependencies in POM.

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.16</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>test-redis-spring</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>test-redis-spring</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>17</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.redis.om</groupId>
                <artifactId>redis-om-spring</artifactId>
                <version>0.6.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    Startup class:

    @SpringBootApplication
    @EnableRedisEnhancedRepositories
    public class TestRedisSpringApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(TestRedisSpringApplication.class, args);
        }
    
    }
    

    You have to use @EnableRedisEnhancedRepositories to detect presence of the repositories using redis - based model.

    Repository class:

    @Repository
    public interface PersonRepository extends CrudRepository<Person, String> {
    }
    

    Entity class :

    import com.redis.om.spring.annotations.Indexed;
    import lombok.Data;
    import lombok.NonNull;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.redis.core.RedisHash;
    
    @Data
    @RedisHash
    public class Person {
        @Id
        private String id;
    
        @NonNull
        @Indexed
        private String fullName;
    
        @NonNull
        @Indexed
        private String job;
    }
    

    Note: @RedisHash, @Indexed are annotations from Redis-OM lib and it works with Redis Stack Server as it has extensive support for searching and querying which normal Redis Server lacks.

    Custom Redis Configuration which takes guarantee of creating bean of JedisConnectionFactory and thereby providing it to the Redis-OM and it's mandatory to supply that bean.

    @Configuration
    public class CustomRedisConfiguration {
    
        @Bean
        public JedisConnectionFactory jedisConnectionFactory() {
            RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
            redisConf.setHostName("localhost");
            redisConf.setPort(6379);
            JedisClientConfiguration conf = JedisClientConfiguration.builder()
                    .readTimeout(Duration.ofMillis(1000))
                    .connectTimeout(Duration.ofMillis(1000))
                    .build();
            return new JedisConnectionFactory(redisConf, conf);
        }
    
    }
    

    Controller Code :

    @RestController
    @RequestMapping("person")
    public class PersonController {
    
        @Autowired
        private PersonRepository repository;
    
        @PostMapping("save")
        public Person save(@RequestBody Person p) {
            return repository.save(p);
        }
    
        @GetMapping("/find-all-by-ids")
        public List<Person> getAllPersonByIds(@RequestBody List<String> pids) {
            List<Person> list = new ArrayList<>();
            repository.findAllById(pids).forEach(list::add);
            return list;
        }
    }
    

    The server start successfully.

    Logs:

    /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=64359:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/anish/Downloads/test-redis-spring/target/classes:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter-data-redis/2.7.16/spring-boot-starter-data-redis-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter/2.7.16/spring-boot-starter-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.7.16/spring-boot-starter-logging-2.7.16.jar:/Users/anish/.m2/repository/ch/qos/logback/logback-classic/1.2.12/logback-classic-1.2.12.jar:/Users/anish/.m2/repository/ch/qos/logback/logback-core/1.2.12/logback-core-1.2.12.jar:/Users/anish/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.17.2/log4j-to-slf4j-2.17.2.jar:/Users/anish/.m2/repository/org/apache/logging/log4j/log4j-api/2.17.2/log4j-api-2.17.2.jar:/Users/anish/.m2/repository/org/slf4j/jul-to-slf4j/1.7.36/jul-to-slf4j-1.7.36.jar:/Users/anish/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/anish/.m2/repository/org/yaml/snakeyaml/1.30/snakeyaml-1.30.jar:/Users/anish/.m2/repository/org/springframework/data/spring-data-redis/2.7.16/spring-data-redis-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/data/spring-data-keyvalue/2.7.16/spring-data-keyvalue-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/data/spring-data-commons/2.7.16/spring-data-commons-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/spring-tx/5.3.30/spring-tx-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-oxm/5.3.30/spring-oxm-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-aop/5.3.30/spring-aop-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-context-support/5.3.30/spring-context-support-5.3.30.jar:/Users/anish/.m2/repository/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar:/Users/anish/.m2/repository/io/lettuce/lettuce-core/6.1.10.RELEASE/lettuce-core-6.1.10.RELEASE.jar:/Users/anish/.m2/repository/io/netty/netty-common/4.1.97.Final/netty-common-4.1.97.Final.jar:/Users/anish/.m2/repository/io/netty/netty-handler/4.1.97.Final/netty-handler-4.1.97.Final.jar:/Users/anish/.m2/repository/io/netty/netty-resolver/4.1.97.Final/netty-resolver-4.1.97.Final.jar:/Users/anish/.m2/repository/io/netty/netty-buffer/4.1.97.Final/netty-buffer-4.1.97.Final.jar:/Users/anish/.m2/repository/io/netty/netty-transport-native-unix-common/4.1.97.Final/netty-transport-native-unix-common-4.1.97.Final.jar:/Users/anish/.m2/repository/io/netty/netty-codec/4.1.97.Final/netty-codec-4.1.97.Final.jar:/Users/anish/.m2/repository/io/netty/netty-transport/4.1.97.Final/netty-transport-4.1.97.Final.jar:/Users/anish/.m2/repository/io/projectreactor/reactor-core/3.4.32/reactor-core-3.4.32.jar:/Users/anish/.m2/repository/org/reactivestreams/reactive-streams/1.0.4/reactive-streams-1.0.4.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.7.16/spring-boot-starter-web-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.7.16/spring-boot-starter-json-2.7.16.jar:/Users/anish/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.13.5/jackson-databind-2.13.5.jar:/Users/anish/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.13.5/jackson-annotations-2.13.5.jar:/Users/anish/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.13.5/jackson-core-2.13.5.jar:/Users/anish/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.13.5/jackson-datatype-jdk8-2.13.5.jar:/Users/anish/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.13.5/jackson-datatype-jsr310-2.13.5.jar:/Users/anish/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.13.5/jackson-module-parameter-names-2.13.5.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.7.16/spring-boot-starter-tomcat-2.7.16.jar:/Users/anish/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.80/tomcat-embed-core-9.0.80.jar:/Users/anish/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/9.0.80/tomcat-embed-el-9.0.80.jar:/Users/anish/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.80/tomcat-embed-websocket-9.0.80.jar:/Users/anish/.m2/repository/org/springframework/spring-web/5.3.30/spring-web-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-beans/5.3.30/spring-beans-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-webmvc/5.3.30/spring-webmvc-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-context/5.3.30/spring-context-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-expression/5.3.30/spring-expression-5.3.30.jar:/Users/anish/.m2/repository/com/redis/om/redis-om-spring/0.6.0/redis-om-spring-0.6.0.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-starter-aop/2.7.16/spring-boot-starter-aop-2.7.16.jar:/Users/anish/.m2/repository/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.7.16/spring-boot-autoconfigure-2.7.16.jar:/Users/anish/.m2/repository/com/redislabs/jrejson/1.5.0/jrejson-1.5.0.jar:/Users/anish/.m2/repository/redis/clients/jedis/3.8.0/jedis-3.8.0.jar:/Users/anish/.m2/repository/com/google/code/gson/gson/2.9.1/gson-2.9.1.jar:/Users/anish/.m2/repository/org/apache/commons/commons-pool2/2.11.1/commons-pool2-2.11.1.jar:/Users/anish/.m2/repository/com/redislabs/jredisearch/2.2.0/jredisearch-2.2.0.jar:/Users/anish/.m2/repository/org/json/json/20210307/json-20210307.jar:/Users/anish/.m2/repository/com/redislabs/jrebloom/2.2.0/jrebloom-2.2.0.jar:/Users/anish/.m2/repository/com/google/guava/guava/31.1-jre/guava-31.1-jre.jar:/Users/anish/.m2/repository/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar:/Users/anish/.m2/repository/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:/Users/anish/.m2/repository/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar:/Users/anish/.m2/repository/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar:/Users/anish/.m2/repository/com/google/errorprone/error_prone_annotations/2.11.0/error_prone_annotations-2.11.0.jar:/Users/anish/.m2/repository/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar:/Users/anish/.m2/repository/com/github/f4b6a3/ulid-creator/5.0.1/ulid-creator-5.0.1.jar:/Users/anish/.m2/repository/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar:/Users/anish/.m2/repository/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-devtools/2.7.16/spring-boot-devtools-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot/2.7.16/spring-boot-2.7.16.jar:/Users/anish/.m2/repository/org/springframework/boot/spring-boot-configuration-processor/2.7.16/spring-boot-configuration-processor-2.7.16.jar:/Users/anish/.m2/repository/org/projectlombok/lombok/1.18.30/lombok-1.18.30.jar:/Users/anish/.m2/repository/org/springframework/spring-core/5.3.30/spring-core-5.3.30.jar:/Users/anish/.m2/repository/org/springframework/spring-jcl/5.3.30/spring-jcl-5.3.30.jar com.example.testredis.TestRedisSpringApplication
    17:26:44.447 [Thread-0] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@7f476533
    
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::               (v2.7.16)
    
    2023-09-30 17:26:44.842  INFO 27499 --- [  restartedMain] c.e.t.TestRedisSpringApplication         : Starting TestRedisSpringApplication using Java 17.0.8 on Anishs-MacBook-Pro.local with PID 27499 (/Users/anish/Downloads/test-redis-spring/target/classes started by anish in /Users/anish/Downloads/test-redis-spring)
    2023-09-30 17:26:44.843  INFO 27499 --- [  restartedMain] c.e.t.TestRedisSpringApplication         : No active profile set, falling back to 1 default profile: "default"
    2023-09-30 17:26:44.917  INFO 27499 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
    2023-09-30 17:26:44.917  INFO 27499 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
    2023-09-30 17:26:45.425  INFO 27499 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
    2023-09-30 17:26:45.425  INFO 27499 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
    2023-09-30 17:26:45.597  INFO 27499 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 159 ms. Found 1 Redis repository interfaces.
    2023-09-30 17:26:46.004  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'com.redis.om.spring.RedisModulesConfiguration' of type [com.redis.om.spring.RedisModulesConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.009  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'customRedisConfiguration' of type [com.example.testredis.CustomRedisConfiguration$$EnhancerBySpringCGLIB$$5edc0326] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.052  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'jedisConnectionFactory' of type [org.springframework.data.redis.connection.jedis.JedisConnectionFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.127  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'redisTemplate' of type [org.springframework.data.redis.core.RedisTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.135  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'redisModulesClient' of type [com.redis.om.spring.client.RedisModulesClient] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.137  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'redisModulesOperations' of type [com.redis.om.spring.ops.RedisModulesOperations] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.138  INFO 27499 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'keyspaceToIndexMap' of type [com.redis.om.spring.KeyspaceToIndexMap] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2023-09-30 17:26:46.715  INFO 27499 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2023-09-30 17:26:46.727  INFO 27499 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2023-09-30 17:26:46.728  INFO 27499 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.80]
    2023-09-30 17:26:46.811  INFO 27499 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2023-09-30 17:26:46.812  INFO 27499 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1894 ms
    2023-09-30 17:26:47.040  INFO 27499 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
    2023-09-30 17:26:47.720  INFO 27499 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2023-09-30 17:26:47.727  INFO 27499 --- [  restartedMain] c.r.om.spring.RedisModulesConfiguration  : Creating Indexes......
    2023-09-30 17:26:47.735  INFO 27499 --- [  restartedMain] c.r.om.spring.RedisModulesConfiguration  : Found 0 @Document annotated Beans...
    2023-09-30 17:26:47.741  INFO 27499 --- [  restartedMain] c.r.om.spring.RedisModulesConfiguration  : Found 1 @RedisHash annotated Beans...
    2023-09-30 17:26:47.741  INFO 27499 --- [  restartedMain] c.r.om.spring.RedisModulesConfiguration  : Found @RedisHash annotated class: com.example.testredis.Person
    2023-09-30 17:26:47.742  INFO 27499 --- [  restartedMain] c.r.om.spring.RedisModulesConfiguration  : FOUND @Indexed annotation on field of type: class java.lang.String
    2023-09-30 17:26:47.743  INFO 27499 --- [  restartedMain] c.r.om.spring.RedisModulesConfiguration  : FOUND @Indexed annotation on field of type: class java.lang.String
    2023-09-30 17:26:47.792  INFO 27499 --- [  restartedMain] c.e.t.TestRedisSpringApplication         : Started TestRedisSpringApplication in 3.335 seconds (JVM running for 3.879)
    2023-09-30 19:12:53.073  INFO 27499 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2023-09-30 19:12:53.074  INFO 27499 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
    2023-09-30 19:12:53.086  INFO 27499 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 11 ms
    

    I'm creating two data in redis by using the endpoint : http://localhost:8080/person/save

    Screenshot:

    enter image description here

    Redis CLI logs:

    enter image description here

    Now, I will try to get the data from getAllById endpoint: http://localhost:8080/person/find-all-by-ids

    Screenshot:enter image description here

    Redis CLI logs:

    enter image description here

    That's all.