본문 바로가기

Elasticsearch

[elasticsearch] preference 사용해야 하는 이유 / 방법 및 예제 알아보기

반응형

 

Elasticsearch search query를 날릴 때

Preference 옵션을 주어야하는 이유 그리고 그 방법 알아보기 

 

 

  Preference 란 ?  

search query를 날릴 때, elasticsearch는 디폴트로 예비 후보 nodes과 shards 중 랜덤하게 요청을 보낸다. (이 설명으로 유추해보면 primary로는 보내지 않는 것 같다.) 이 때 어떠한 shard 또는 Replica를 query search에 사용할지 유저가 "선호"를 미리 설정할 수 있는 것이 Preference option이다. 

 

 

 

  Preference를 사용하지 않으면 ?   ==>  query 결과가 매번 다르게 된다.  

똑같은 쿼리로 검색 시에 데이터의 결과 정렬이 달라질 수 있다. 검색 결과의 정렬은 es score 순으로 매번 쿼리의 score 결과가 다르다면 유저 입장에서 일관적이지 않은 데이터를 접하게 된다. 

 

원인 : 

이 문제는 만약 replicas를 가지고 있다면 언제나 생길 수 있는 문제이다. elasticsearch는 데이터를 조회해올 때 Shard 단위로 요청을 보내는데 이 때 랜덤으로 shard를 골라 요청을 보낸다. 이렇게 되면 같은 쿼리로 두 번 요청을 했을 때 첫 번째 쿼리의 결과를 조회하기 위해 선택된 shard와 두 번째 쿼리를 위해 선택된 shard가 다르게 될 수 있다. 

 

그런데 모든 shard는 다 똑같은 데이터를 가지고 있지 않나 ?? 할 수 있는데 여기에 es의 특징과 관련한 연쇄결과(?)가 생겨서 그렇다. elasticsearch에서 문서를 delete or update하면 예전 도큐먼트 (Old Document)는 바로 즉시 index에서 사라지는 것이 아니고 일단 "deleted" 라고 마크가 달리게 된다. (그리고 update되거나 새로 쓰이는 도큐먼트는 새로 생성되는 구조) 그리고 이렇게 "나 삭제 되었어~" 마크가 달린 데이터들은 이 Old document가 속한 segment가 머지되는 때에 디스크에서 아예 사라지게 된다. 

 

중요한 포인트는 여기서 마크가 달린 아이들이 영구 삭제되기 전에도 "index statistics" 통계에 잡힌다는 것이다. 각각의 shard가 segment를 머지하는 시기가 다르기 때문에 primary shard가 대량의 deleted documents를 제거하는 merge했다고 하면 다른 shards 들은 아직 marked deleted documents 가 남아있어 통계 결과가 달라지게 되고 이는 score 점수 산정에 영향을 미치게 된다. 

 

때문에 Elasticsearch에서 권하는 방식인 preference를 사용해서 ( 이 때 user의 session id 나 userId이나 유저가 가진 고유한 S값을 사용) 일정한 결과를 반환받을 수 있다.

 

즉, 매 쿼리마다 동일하게 fixed한 결과를 가져오기 위해?  ==> Preference option을 사용하면 된다. 

 

 

 

 

<Elasticsearch의 preference 옵션의 종류와 설명>

 

 

 

  Elasticsearch Preference Example   

kibana

curl localhost:9200/_search?preference=randomstringvalue -d '
{
    "query": {
        "match": {
            "title": "howdoyoudo"
        }
    }
}
'

node.js 

  return client
    .search({
      _source: FIELDS,
      index: TEST_INDEX,
      size: _.isNumber(pageSize) === false ? 20 : pageSize,
      body,
      preference: userId || 'randomString',
    })
    .catch(error => {
		console.log('ERROR=', error);
    });

 

 


 

 

References : 

https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-search.html#search-preference

https://velog.io/@khj2872/Elasticsearch-preference-query-parameter

https://www.elastic.co/guide/en/elasticsearch/reference/8.0/consistent-scoring.html

반응형