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.
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)
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;
}
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.
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)));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With