엘라스틱서치에서 샤드는 refresh, flush, optimize API 과정을 통해 관리된다.
엘라스틱서치의 위의 내용은 모두 루씬 내용인데 서로 용어가 다르기 때문에 잘 정리해 둘 필요가 있다.

루씬 엘라스틱서치
flush refresh
commit flush
merge optimize API

루씬에서는 데이터가 in-memory buffer 기반으로 처리된다.
데이터변경사항이 들어오면 segment를 생성하고, 시스템 캐시에 캐시된 후에, 디스크 동기화가 이루어짐.

1. 루씬에서의 flush = 엘라스틱서치의 refresh.
- segment 생성시 커널 시스템 캐시에 세그먼트가 캐시되어 읽기가 가능해진다.
- 루씬의 ReOpen() 함수를 이용해 IndexSearcher에서 읽을 수 있는 상태.
- 일정주기마다 업데이트 된 문서가 ReOpen() 함수로 처리.

- es 클러스터에 존재하는 모든 샤드에서는 기본적으로 1초마다 한번씩 refresh작업이 수행된다.
- 인덱스를 새로고침한다는 의미인데, refresh가되면 새로 추가한 데이터의 검색이 가능해진다.
- 대량 인덱스 시에는 -1로 비활성화해두면 인덱싱할때 이점이 있다.

2. 루씬에서의 commit = 엘라스틱서치의 flush.
- 물리적으로 디스크 기록을 수행하는 fsync() 함수 호출 작업이다.
- flush가 있기 때문에 매번 commit 필요가 없고, 일정 주기로 commit이 수행된다.
- 루씬에서의 flush작업은 디스크로 쓰기가 이루어지기 전이기 때문에, flush작업까지만 되고 시스템에 문제가 발생하면 데이터 유실 발생 가능성이 있다.

- es에서의 flush는 루씬의 commit 작업과 함께 새로운 translog를 시작한다.
- * translog는 루씬에는 없는 내용으로 샤드의 장애복구를 위해 재공 되는 특수한 파일이다.
- * 샤드는 자신에게 일어나는 모든 변경사항을 translog에 먼저 기록하고, 내부 루씬을 호출한다.
- * 시간이 지나면 translog 파일 크기도 증가한다. 루씬에서 commit이 이루어지면 translog에서 commit 지점까지의 내용이 삭제된다.
- * 데이터가 커널 시스템 캐시에 있다 디스크에 동기화 되지 못하고 유실될 가능성을 대비하여 transhlog를 만든 것이다.
- es에서 flush 작업은 default로 5초에 한번씩 수행되고, api를 통해 flush 주기 조절이 가능하나 추천하지 않는다.

3. 루씬의 merge = 엘라스틱서치의 optimize API
- 검색 성능을 높이기 위해 검색 대상이 되는 세그먼트를 병합하여 세그먼트 수를 줄이는 작업이다.

- 검색 대상이 되는 세그먼트 수를 줄이면, 검색 횟수를 줄일 수 있고, 검색 성능이 올라간다.
- commit작업을 동반하기 때문에 비용이 크다. 

- es에서는 forced merge API를 통해 루씬 merge 작업을 강제 수행할 수 있다.
- 파편화된 다수 세그먼트들을 병합한다.
- 강제 수행하지 않더라도, 백그라운드로 주기적으로 수행된다.

elasticsearch에는 fielddata와 doc_values라는 것이 있고, 주요 개념이므로 이해가 필요하다.
더 근본적으로는 루씬의 개념이기 때문에 루씬에서 storedField와 docValue내용을 찾아보는 것이 좋다.

elasticsearch에서 data를 mapping할때에 keyword type과 text type이 있다.
keyword type의 경우 exact매칭에서 사용하고, text type의 경우 analyzed 매칭에 사용된다.
text type의 경우는 형태소 분석을 통해 field를 여러 terms로 나눠서 역인덱싱 과정을 거치게 되고,
keyword type은 그대로 역인덱싱 된다.
* 역인덱스란 키워드가가 어떤 문서에 포함되는지를 저장한다.

검색(search)이라는 것은 "어떤 문서가 이 키워드를 포함하는지가 궁금"하므로 역인덱스된 정보를 통해 검색이 빠른 검색이 가능하다.
그러나 sort, aggregation, accessing field value 와 같은 패턴은 "이 문서에서 이 field value값이 무엇인지"가 관심이므로 역인덱스 정보가 아닌 document를 key로, field정보를 담은 데이터 구조가 필요하다. 그 데이터 구조가 fielddata라는 것이다.

key value
doc1 a:1, b:4, c:7
doc2 a:2, b:5, c:8
doc3 a:3, b:6, c:9

 

그런데 fielddata의 경우 in-memory구조로 작동하기 때문에 많은 heap memory를 소비하게된다. 일단 field가 heap에 로딩되면 그것은 segment의 lifetime동안 남아있게된다. 따라서 비용이 높은 프로세스가된다.

text field를 사용하게 되면 fielddata 데이터 구조를 사용할 수 있는데 위의 설명과 같이 높은 비용때문에 default false로 되어있다.
필요한 경우는 fielddata=true로 옵션을 변경하여 사용하되, memory사용에 주의한다.

keyword field에서는 fileddata의 in-memory에서 동작하는 구조를 개선하여, on-disk data structure인 doc_values 사용이 가능하다.
doc_values는 아래와 같이 column-oriented fashion으로 더욱 유리하게 sort, aggregation 등을 할 수 있다.

key doc1 doc2 doc3
a 1 2 3
b 4 5 6
c 7 8 9


keyword type과 text type은 이렇게 analyzed 되냐 안되냐의 차이뿐 아니라 fielddata, doc_values와 같은 데이터 구조 사용 여부도 달라지므로 적절한 data mapping과 옵션 설정이 중요하다.

 

 

* 위의 설명은 친절한 es 가이드와 루씬내용을 따로 찾아 정리하였습니다.
* es 가이드를 상세히 읽고, 그에 따른 루씬 내용을 찾아보면 이해하기가 좋은 것 같아요.

 

https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html

 

fielddata | Elasticsearch Reference [7.5] | Elastic

Most fields are indexed by default, which makes them searchable. Sorting, aggregations, and accessing field values in scripts, however, requires a different access pattern from search. Search needs to answer the question "Which documents contain this term?

www.elastic.co

 

https://www.elastic.co/guide/en/elasticsearch/reference/current/doc-values.html

 

doc_values | Elasticsearch Reference [7.5] | Elastic

Most fields are indexed by default, which makes them searchable. The inverted index allows queries to look up the search term in unique sorted list of terms, and from that immediately have access to the list of documents that contain the term. Sorting, agg

www.elastic.co

 

+ Recent posts