훈훈훈
Spring Data :: Spring Data Elasticsearch refresh policy 정리 본문
Spring Data :: Spring Data Elasticsearch refresh policy 정리
훈훈훈 2022. 1. 31. 00:09이슈
얼마전에 검색 API 를 호출하면 데이터가 종종 빈 값이 반환되는 이슈가 있었다.
이슈가 발생하는 시점은 Indexer 어플리케이션에서 Elasticsearch 인덱스에 Bulk Insert 할 때 였다. 해당 시점에 데이터를 조회 하였을 때, 데이터가 비어있는 현상을 발견하였다.
이슈가 발생한 원인은 Elasticsearch 는 refresh interval 기능이 존재하기 때문이다.
Elasticsearch 공식문서를 확인해보면 아래와 같이 설명을 하고 있다.
해당 기능은 디폴트로 1s 마다 refresh interval 를 수행하게 되는데, 우리가 Elasticsearch 에서 조회하는 내용은 1s 이전 데이터를 의미한다. 엄밀하게는 지난 30s 동안 한 번 이상의 검색 요청을 받은 인덱스에 대해서만 refresh 가 진행이 된다.
추가로 refresh 가 어떤식으로 진행이 되는지 좀 더 자세히 살펴보자.
해당 내용은 QBOX 의 글을 참고하였다.
데이터가 색인이 되면 샤드 내에 있는 Translog (트랜잭션 로그) 와 인메모리 버퍼에 저장이 된다.
그리고 1s 마다 (디폴트) 주기적으로 인덱스를 refresh 를 할 때, 인메모리 버퍼에 있는 데이터를 새로 생성된 세그먼트에 복사를 하며 그 이후 refresh 한 데이터를 검색할 수 있게 된다고 한다.
Elasticsearch 에서는 refresh 를 컨트롤하기 위해 몇가지 옵션을 제공해주는데 기능적으로 분류를 해보면 아래와 같다.
(1) 디폴트 옵션 (false)
(2) 즉시 새로고침 (true)
(3) 새로고침 될 때까지 기다림 (wait_for)
실시간을 어느정도 보장받기 원한다면, (2) 번 혹은 (3) 번을 선택하는 방법이 있다.
즉시 true(새로고침을 하는 옵션) 은 매 요청마다 즉시 즉시 새로고침을 하기때문에 가장 높은 실시간을 보여줄 수 있겠지만, 매번 refresh 를 즉시 진행해버리기 때문에 높은 리소스를 많이 사용하게 된다.
반면에 wait_for 옵션은 새로고침이 될 때까지 기다리고 응답을 보내주는 정책이다.
이 정책도 높은 실시간을 보여주지만, 즉시 새로고침에 비하면 대기 시간이 길다. 그래도 즉시 refresh 하는 것 보다는 낮은 리소스를 소비한다.
각각 옵션의 장단점이 있지만, 색인 속도를 포기하고 리소스를 적게 소모하는 wait_for 이 많이 사용되는 것 같다.
각 옵션을 비교해보고 사내에서 Bulk 작업을 수행할 때, wait_for 옵션을 지정하는 것으로 정책을 잡았다.
해결 방법
해당 이슈를 해결하기 위해 데이터를 색인할 때 RefreshPolicy 를 wait_for 옵션으로 사용하기로 하였다.
스프링에서는 RefreshPolicy 이름을 약간 다르게 정의한다.
아래 Spring data elasticsearch 에서 제공하는 RefreshPolicy Enum 을 살펴보자.
이름만 보고 추론을 해보면 대충 알 것 같지만, 정확하지는 않기에 좀 더 찾아보니 org.elasticsearch.action.support 패키지에 있는 WriteRequest 인터페이스 내부에 RefreshPolicy EnumType 이 아래와 같이 동일하게 정의 되어 있다.
코드와 주석을 보면 Spring data elasticsearch 에서 정의한 RefreshPolicy Enum 과 이름이 동일한 것을 알 수 있고, 각각 옵션에 대한 설명이 적혀있다.
여기서 왜 동일한 Enum 을 새로 만들어서 사용하는지 의문이 들었다.
유추해보면 Spring data elasticsearch 에서 org.elasticsearch.action.support 패키지에 있는 Enum 을 사용하려고 했지만, WriteRequest 인터페이스 내부에 있는 Enum 이기 때문에 RefreshPolicy Enum 을 가져다가 사용한다면 WriteRequest 인터페이스에 강하게 결합이 되어 ?? 새로 생성을 해서 사용하는 것인가 싶다. 같은 예시로 OpType Enum이 있다.
다시 돌아와서 코드와 주석을 읽어 보면 각각의 타입에 대한 설명은 주석에 잘 명시되어 있다.
이 글에서는 문제가 된 이슈를 해결하기 위해 wait_for 사용하려고 하기 때문에 RefreshPolicy 를 WAIT_UNTIL 으로 세팅하려고 한다.
공식 문서를 참고하여 코드로 작성하면 아래와 같이 할 수 있다.
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.hooon.dataes.repository")
@ComponentScan(basePackages = { "com.hooon.dataes.service" })
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient client() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
ElasticsearchRestTemplate elasticsearchRestTemplate = new ElasticsearchRestTemplate(client());
elasticsearchRestTemplate.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL); // RefreshPolicy 설정
return elasticsearchRestTemplate;
}
}
Spring bean 으로 ElasticsearchOperations 을 등록할 때 refreshPolicy 를 설정할 수 있다.
스프링 공식문서를 읽어보면 refresh policy 값은 반드시 설정하라고 말하고 있다.
(앞으로는 공식 문서를 좀 더 꼼꼼히 읽어봐야겠다..)
# reference
https://qbox.io/blog/refresh-flush-operations-elasticsearch-guide/
https://www.codetd.com/en/article/6497511
https://www.elastic.co/guide/en/elasticsearch/reference/7.16/near-real-time.html#img-pre-refresh
https://www.elastic.co/guide/en/elasticsearch/reference/7.16/docs-refresh.html
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#reference
'Spring Framework > 개념' 카테고리의 다른 글
Spring boot :: Transaction default isolation level 은 어떻게 결정이 될까 (0) | 2022.03.13 |
---|---|
Spring Data :: Spring Data Elasticsearch _class 필드 자동 생성 비활성화 (0) | 2021.11.27 |
Spring Data :: Spring Data Elasticsearch rollover index 정리 (1) | 2021.11.26 |
Spring Cloud :: Spring cloud sleuth 정리 (0) | 2021.11.13 |
Spring boot :: Caffeine cache 정리 (2) | 2021.10.31 |