kok202
Elasticsearch 활용 (성능 최적화)

2019. 4. 13. 17:23[공부] 독서/실무 예제 Elasticsearch 검색엔진 활용

하드웨어 관점

CPU  하이퍼 스레딩 포함 32코어 까지 대응. 
32 코어 보다 크면 너무 많은 스레드가 생성되어 OOM 이 발생한다.
CPU 사용률이 60% 이상이면 CPU 확장을 고려해보는 것이 좋다.
RAM  최대 32 GB. 32GM 이상이면 GC 수행시 성능 저하가 염려된다. 
Disk  SSD
네트워크  분산 구조를 지원하므로 클러스터 관점이 더 좋다.

 

 

 


Document 관점
Shard의 크기를 결정하는 기준

1. 데이터 노드의 갯수와 맞춘다. 가장 손쉽게 생각할 수 있는 방법.
2. CPU 코어의 갯수와 맞춘다. ES가 병렬 처리 기반이므로.
3. Document의 데이터 크기 샤드의 물리적인 크기는 50GB 이하인 것이 좋으므로.

인덱싱 처리량을 늘리는 가장 쉬운 방식이 샤드를 늘리는 것.
샤드의 크기는 데이터 노드의 갯수보다는 크고 코어의 갯수보다는 크면 안된다.


Modeling = 맵핑 과정에서 색인과 검색에 대한 요구사항을 반영하여 성능을 하는 방법

_all 필드 풀텍스트 검색 기능을 사용하는 것이 아니라면 disable 하는 것이 좋다. 
CPU 사용량을 줄이고 Disk 의 write 크기도 줄일 수 있으며 인덱스의 크기도 줄일 수 있다.
_source 필드 인덱싱 할 때 자동으로 생성되는 필드. 
검색 용도가 아닌 단순 출력용으로만 사용 한다
모든 필드를 저장하기 때문에 storage 공간이 커질 염려가 있다.
_id 필드 이 필드를 기준으로 도큐먼트를 어드 shard 에 저장할지 결정된다.
특정 샤드로 데이터가 몰리지 않는지 확인해야한다.
_id 필드를 지정하지 않으면 해시 문자열로 가지게 되므로 랜덤하게 배치된다.
_routing 필드 Shard의 저장 기준을 _id 가 아닌 특정 필드 값을 사용하여 도큐면트에 저장되도록 한다.

 

 

 


Operation 관점 (설정 변경)

1. 디스크 확장 path.data 설정으로 여러개의 디스크를 묶어서 사용할 수 있다.
2. 노드의 역할 분배 클러스터 환경에서 각 서버 노드들을 특정 용도에 맞춰 구성하면 성능 개선과 안정성 확보가 가능하다.
1. 로드 벨런서 노드 : 검색 성능 향상
2. 데이터 노드 : 인덱싱 성능 향상
3. 마스터 노드 :  노드 관리 안정성 확보. 고사양 장비가 아니여도 Ok, Quorum 구성을 추천
이외 : https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html
3. Refresh 주기 NRT (Near Real Time)을 지원하려면 refresh time 이 1s 여야한다. 
그런데 너무 자주 refresh 되면 세그먼트 파일이 생성 되므로 성능이 떨어질 수 있다.
4. 스레드 풀 가장 많이 사용되는 스레드 풀 : bulk, index, search. 
스레드 풀의 크기는 core의 갯수 * 2가 적당하다. 
기본값은 core 의 갯수 * 1 이다.
5. Zen discover 노드 간의 통신 을 관리하는 모듈.
Zen discover 방식
1. ping
2. multicast : 모든 요청을 네트워크로 브로드 케스트
3. unicast : 설정된 노드 사이에서만 통신 (추천)
4. master election : master 가 fail 했을 때 알아서 마스터 노드를 선출. fail over
5. fault detection : 일반 노드가 장애가 발생하면 감지하고 장애가 발생한 노드의 샤드를 재할당하도록 한다.
6. JVM 옵션 1. Heap 크기 설정
최대 메모리 크기는 32GB.
너무 크기가 크면 GC 가 오래 걸린다.
index, document, cahce 크기를 고려해야한다.
Heap size = 인덱스 버퍼 크기 * Shard 의 갯수 * 10

2. GC 설정 : 건드리지 않는게 바람직

Quorum 구성 
(마스터 노드의 수 / 2) + 1

 

 

 


검색 속도 향상 관점 
1. Standard Shard의 갯수를 늘린다.
2. Replica shard의 갯수를 늘린다.
3. 쿼리가 항상 같은 노드로 hitting 되지 않도록 한다.
4. 쿼리 결과가 Zero hit 인 쿼리는 검색엔진 요청에 닿지 않도록한다.
5. 쿼리 결과를 캐시한다.
6. Pagination 에 주의한다. 
7. 검색 결과 문서에 접근 할 때 doc['field']를 사용한다. 
8. 검색 결과의 랭킹이 필요없으면 필터를 사용해라.

* Pagination
5개의 샤드를 운영중이고 1페이지당 50개의 문서를 보여준다고 했을 때
1페이지를 보기 위해 가져오는 문서의 갯수 = 5 * 50 * 1
2페이지를 보기 위해 가져오는 문서의 갯수 = 5 * 50 * 2 ...
50페이지를 보기 위해 가져오는 문서의 갯수 = 5 * 50 * 50 
1페이지를 보는 것과 50페이지를 보는 것의 리소스 부담이 같지 않다.

* doc['field']을 쓰는게 좋은 이유
검색 결과 문서에 접근하는 방식은 _source, _field, doc['field'] 총 3가지이다.
_source, _field는 디스크 접근 방식이다. 
doc['field']는 캐시 접근 방식이다.

* 필터와 쿼리 비교

필터 쿼리
필터링 됬거나 안됬거나 Score 계산
Keyword search Full text search
Cache O Cache X

 

bulk 요청에대한 최적화
1. 레플리카, 리프레시 설정을 끈다.
2. 인덱싱할 문서를 읽는다.
3. Bulk 요청을 생성한다.
4. Bulk 요청을 날린다.
5. 최적화 작업 수행
6. 레플리카, 리프레시 설정을 복구한다.

Bulk 요청
요청 크기는 1000~5000개의 도큐먼트나 5~15MB 사이의 물리적 크기 가 좋다.
요청 처리 지연을 위해 timeout 시간을 조정해라.
요청 작업 완료후 인덱스 최적화 작업이 리소스를 엄청 사용하는데 최적화의 대안으로 flush 와 refresh를 사용하면 좋다.