본문 바로가기
TIL/엘라스틱 서치

Elastic Search : Complete Guide to ElasticSearch - 도큐먼트 라우팅

by yeon_zoo 2024. 1. 8.

[도큐먼트 라우팅]

엘라스틱 서치는 어떤 샤드에 어떤 도큐먼트를 담아야 할지 어떻게 알까? 아래의 계산식을 통해서 결정한다. 

shard_num = hash(_routing) % num_primary_shards

primary shard의 수(replica는 고려하지 않음)는 고정되어 있으니 _routing(도큐먼트의 id 같은 값)의 hash 값을 샤드의 수로 mod 연산을 진행하는 것이다. 따라서 해당 id 값을 검색하게 되면 모드 연산을 진행해 탐색해야 할 샤드를 알 수 있다. 이게 엘라스틱 서치의 기본 디폴트 라우팅 전략이다. (커스텀 라우팅 전략을 세우는 것도 가능하다.) 이 방법으로 샤드마다 도큐먼트의 수가 동일하게 유지할 수 있다. id 필드가 아니라 다른 필드를 모드 연산에 이용하고 싶다면 별도로 지정할 수도 있다. 

 

[도큐먼트 읽기 방법]

여기서 말하는 읽기 방법은 search 쿼리가 아니라 하나의 도큐먼트를 읽을 때 사용하는 방법이다.

  1. 먼저 위의 라우팅 방법으로 도큐먼트가 존재하는 Replication Group을 찾는다. 데이터를 읽어올 때는 Primary shard가 아닌 레플리카에서 읽어오게 된다. 
  2. 어떤 레플리카에서 읽은 것인가를 결정하는데 ARS(Adaptive Replica Selection, 현 상태에서 읽어오기 최적인 샤드를 선택하는 로드 밸런서 역할)라는 기술이 사용된다. 
  3. coordinating node가 요청에 대한 응답을 모아 sdk, kibana, 혹은 cli의 클라이언트에게 전달한다. 

 

[도큐먼트 쓰기 방법]

  1. 라우팅 방법으로 도큐먼트를 쓸 Replication Group을 찾는다. 쓰기 연산은 primary shard에서 진행된다. 
  2. primary shard는 요청의 유효성을 검증한다. 요청의 구조나 필드 값들을 검증하는 작업이다. 이후 레플리카에 데이터를 전송하기 전에 먼저 자기 자신에 쓴다. 이 때 성능 개선을 위해서는 레플리카에 병렬적으로 쓰기 연산을 전달할 수도 있다. 

엘라스틱 서치는 분산되어 있고 비동기적인 연산을 많이 수행하기 때문에 잘못될 가능성이 있다. 따라서 실패 경우에 어떻게 진행되는지 알아야 한다. 아래와 같은 실패 경우가 발생할 수 있다. 

primary shard 인 B가 2개의 레플리카에게 도큐먼트 수정 쓰기 연산을 전달했는데 B1에는 쓰기가 잘 전달 됐지만, B2에는 전달되지 않았다. 그리고 나서 샤드 B가 죽게 되었다. 그렇다면 B1과 B2 중에 새로운 primary를 뽑아야 하는데 어떻게 해야할까? ARS에 따라서 도큐먼트를 검색했을 때 수정된 도큐먼트가 조회될 수도, 수정되기 전 도큐먼트가 조회될 수도 있다. 이 때 해결책으로 엘라스틱 서치가 사용하는 것이 primary terms 랑 sequence number이다. 

 

[Primary terms]

  • 오래된 샤드랑 새 프라이머리 샤드를 구분하는 방법이다. 
  • primary 샤드가 몇 번이나 바뀌었는지 세면 된다. 레플리카에 보내지는 쓰기 연산에 현재의 primary term을 보낸다. 이렇게 하면 연산이 전달된 이후로 primary 샤드가 바뀌었는지 아닌지를 레플리카 샤드가 확인할 수 있다. 

[Sequence numbers]

  • 모든 쓰기 연산에 primary term과 함께 존재하게 된다.
  • 적어도 primary 샤드가 바뀌기 전까지 각 쓰기 연산마다 +1 되어 붙는다. (primary 샤드가 +1 씩 더한다)
  • 샤드의 primary 주기 내에 연산의 순서를 알 수 있게 된다. 

위의 두 가지 방법을 이용하면 primary 샤드의 일부 실패나 먹통에도 회복할 수 있다. 하지만 인덱스가 크다면 이 과정 자체는 비싼 과정이 된다. 이를 위해서 엘라스틱 서치는 checkpoint들을 사용한다. 

 

[Global & Local checkpoints]

  • Global checkpoint : 각 복제 그룹마다 존재
    • replication group 내 모든 레플리카 샤드에서 동기화된 쓰기 연산의 seq 넘버를 가지고 있는다.
    • primary 가 죽고 나서 다시 회복되었을 때, 엘라스틱 서치에서는 global checkpoint 이후의 연산에 대해서만 신경쓰면 된다.
  • Local checkpoint : 각 레플리카 샤드마다 존재
    • 실행된 마지막 쓰기 연산의 seq

댓글