Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to configure redis ttl with spring boot 2.0

I am using redis in spring boot 2.0.

I wanted the data stored in redis to be set to TTL.

So I searched to find a way, and I wrote the following example code.

Person.java

@Data
@Builder
@RedisHash("Person")
public class Person implements Serializable {

    @Id
    private Long id;

    private PersonInfo info;
}

PersonInfo.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PersonInfo implements Serializable {

    private String name;

    private Long age;
}

RedisConfig.java

@Configuration
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Value("${spring.redis.expiretime}")
    private Long expireTime;



    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory() {

        log.info("Info -> Lettuce Connection Factory");

        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory();
        lettuceConnectionFactory.setHostName(this.redisHost);
        lettuceConnectionFactory.setPort(this.redisPort);

        log.info("RedisHost  -> " + lettuceConnectionFactory.getHostName());
        log.info("RedisPort  -> " + lettuceConnectionFactory.getPort());
        log.info("ExpireTime -> " + expireTime);

        return lettuceConnectionFactory;
    }


     @Bean
    public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {

        log.info("Info -> Redis Template");

        RedisTemplate redisTemplate = new RedisTemplate();

        redisTemplate.setKeySerializer(new StringRedisSerializer());


        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        return redisTemplate;
    }



    @Bean
    public RedisCacheConfiguration cacheConfiguration() {

        log.info("Info -> Redis Cache Configuration");

        RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(expireTime))
                .disableCachingNullValues()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        cacheConfig.usePrefix();

        log.info("Duration -> " + cacheConfig.getTtl().getSeconds());

        return cacheConfig;
    }


    @Bean
    public RedisCacheManager cacheManager() {

        log.info("Info -> Redis Cache Manager");

        RedisCacheManager rcm = RedisCacheManager
                .builder(this.lettuceConnectionFactory())
                .cacheDefaults(this.cacheConfiguration())
                .build();

        return rcm;
    }
}

PersonRedisRepository

public interface PersonRedisRepository extends CrudRepository<Person, Long> {}

PersonController.java

@RestController
@Slf4j
public class PersonController {

    @Autowired
    private PersonRedisRepository personRedisRepository;



    @PostMapping("/person/{id}")
    public Person createPerson(@PathVariable("id") Long id) {

        log.info("Info -> CreatePerson START ================= ");

        Person person = Person.builder()
                .id(id)
                .info(PersonInfo.builder()
                        .name("Test -> " + id)
                        .age(id + 15)
                        .build()
                )
                .build();

        personRedisRepository.save(person);

        Person getPerson = personRedisRepository.findById(id).get();
        log.info("Info -> getPerson : " + getPerson.toString());

        log.info("Info -> createPerson END   ================= ");

        return getPerson;
    }



    @GetMapping("/person/{id}")
    public Person findPerson(@PathVariable("id") Long id) {

        log.info("Info -> FindPerson START ================= ");

        Person findedPerson = personRedisRepository.findById(id).get();
        log.info("Info -> findedPerson : " + findedPerson.toString());

        log.info("Info -> FindPerson END   ================= ");

       // return findedPerson;
        return null;
    }
}

application.yml

spring:
  # Docker Redis
  redis:
    host: 192.168.99.100
    port: 6379
    expiretime: 100

server:
  port: 8083

I wrote RedisConfig.java and others code and tested it as below.

I'm used Rest Client to request

Request

GET http://localhost:8083/person/7 HTTP/1.1
redis:6379> keys *
1) "Person"
2) "Person:3"
redis:6379> hgetall Person:3
1) "_class"
2) "my.cachemanager.redis.person.domain.Person"
3) "id"
4) "3"
5) "info.name"
6) "Test -> 3"
7) "info.age"
8) "18"
redis:6379> TTL Person:3
(integer) -1

I confirmed that the data was stored in redis via redis-cli. However, I also confirmed that the ttl time was not applied.

How can I apply the TTL to the data stored in Redis?

I would really appreciate your help.

like image 209
이상원 Avatar asked Jun 02 '19 11:06

이상원


4 Answers

You can use @TimeToLive annotation (mentioned in section 8.7 of the documentation. It can be applied to either a property or a method, (should not be applied to both for the same class)

like image 121
RaRa Avatar answered Nov 01 '22 14:11

RaRa


RedisCache Manager can specify expiration times(TTL) when configuring Cache Manager beans use below code:

@Bean
 public RedisCacheManager cacheManager(RedisTemplate<String, Object> 
   redisTemplate) {
 RedisCacheManager redisCacheManager = new 
                          RedisCacheManager(redisTemplate);
// Open the most key prefix with the cache name
redisCacheManager.setUsePrefix(true);
//Here you can set a default expiration time unit in seconds.
redisCacheManager.setDefaultExpiration(redisDefaultExpiration);

// Setting the expiration time of the cache
Map<String, Long> expires = new HashMap<>();
expires.put("person", 1000);
redisCacheManager.setExpires(expires);

return redisCacheManager;

}

like image 2
Rajashekhar Arroju Avatar answered Nov 01 '22 14:11

Rajashekhar Arroju


add this to your config

@EnableRedisRepositories

base on documentation. By default, the key expiry listener is disabled when initializing the application. The startup mode can be adjusted in @EnableRedisRepositories or RedisKeyValueAdapter to start the listener with the application or upon the first insert of an entity with a TTL. See EnableKeyspaceEvents for possible values.

like image 1
Kimbriel Oraya Avatar answered Nov 01 '22 12:11

Kimbriel Oraya


You can create a RedisCacheManagerBuilderCustomizer that provides a fluent API as follows. This allows TTL setting for places using @Cachable. @TimeToLive is useful for @RedisHash data.

@Configuration
public class RedisCacheConfig {

    @Value("${token.accessTokenExpiration}")
    private long accessTokenExpirationInSeconds;


    @Bean
    RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {

        return builder -> builder
            .withCacheConfiguration(CacheNames.ACCESS_TOKEN_TO_ENTRY,
                RedisCacheConfiguration
                    .defaultCacheConfig()
                    .disableCachingNullValues()
                    .entryTtl(Duration.of(accessTokenExpirationInSeconds, ChronoUnit.SECONDS)));
    }

}
like image 1
Archimedes Trajano Avatar answered Nov 01 '22 12:11

Archimedes Trajano