@RedisHash @Indexed field ttl not working
Spring Boot에서 @RedisHash + RedisRepository(CrudRepository를 상속받은)를 통해 인메모리 데이터 저장소 redis를 사용하던 중 @Indexed 어노테이션으로 secondary index를 적용한 필드에 대해 ttl(time to live)이 적용되지 않는 현상이 발생하였습니다.
관련 내용을 찾아보니 github issues에서 'Index cleanup happens on the application side and isn't automatically performed by Redis servers.'라는 내용을 찾을 수 있었는데요.
(기본적으로 @RedisHash에서 @Id 어노테이션이 적용된 key에 대해서만 ttl 기능이 동작한다고 합니다.)
@RedisHash를 통한 RedisRepository 방식에서는 Set에서 secondary index 데이터를 삽입 및 제거하며 index를 유지 관리하는데, 이때 index 정리가 수행되기 위해서는 keyspace events가 탐지되어야 하며, keyspace events에 대한 설정이 되어 있어야 한다고 합니다.
@EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
}
그리고 해당 설정은 @EnabledRedisRepository 어노테이션에 enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP 옵션을 설정해 줌으로써 쉽게 적용할 수 있었는데요.
해당 옵션을 설정했을 때 Spring Data Redis에서 Key Events를 수신하게 되며, Key expired events 수신 이후 Set을 정리하게 됩니다.
@Getter
@AllArgsConstructor
@NoArgsConstructor
@RedisHash(value = "coupon", timeToLive = 10)
public class Coupon {
@Id
private String id;
private String name;
@Indexed
private String code;
}
(테스트에 사용한 Coupon Class)
(@Id 어노테이션이 적용된 key에 대해서만 ttl 적용)
해당 옵션을 설정한 이후 데이터가 들어갔을 때 '~:phantom'이라는 키가 추가로 생성된 것을 확인할 수 있었는데요.
@Id 어노테이션이 적용된 필드에 대한 ttl이 만료되어 이벤트가 수신되었을 때 phantom에서 값을 가져와 RedisKeyExpiredEvent를 전파하는 방식이 내부적으로 적용된다고 합니다.
***
아래 참고 자료를 살펴보면 @RedisHash를 사용하는 방식에서 위 내용과 같이 secondary index를 정리하는 방법이 Keyspace 이벤트로 인해 추가적인 오버헤드를 발생시킬 수 있기 때문에, 경우에 따라서는 RedisTemplate을 사용하는 것이 좋다는 내용이 있는데요.
잘 정리된 내용 같아 함께 참고하시면 좋을 것 같습니다.
< keyspace 관련하여 발생한 이슈 >
2023.06.22 - [Programming/Error] - @RedisHash keyspace 사용 시 주의할 점 (RedisKeyValueAdapter)
< 참고 자료 >
https://engineering.salesforce.com/lessons-learned-using-spring-data-redis-f3121f89bff9/
https://github.com/spring-projects/spring-data-redis/issues/2146
< @RedisHash, RedisRepository를 통한 Redis 사용 방법 >
2023.03.07 - [Programming/Web] - (spring boot) RedisRepository 사용하는 방법, @RedisHash
'Programming > Spring Boot' 카테고리의 다른 글
Redisson 분산락을 사용하는 이유와 기본적인 사용 방법 (1) | 2023.06.17 |
---|---|
Spring Boot + PayPal 결제 구현해 보기 (sandbox 테스트 환경) (0) | 2023.06.06 |
양방향 매핑 순환참조 문제 Cannot call sendError() after the response has been committed (0) | 2023.04.28 |
N+1 문제를 해결하기 위한 FetchJoin, 일반 Join과의 차이점은 (0) | 2023.04.22 |
Spring Security + OAuth2 + JWT 소셜 인증 구현(google, kakao, naver) (13) | 2023.04.05 |