본문 바로가기

elasticsearch

elasticsearch indexing Performance Tips ( 엘라스틱서치)

반응형

그저 원문 번역만 가지고서는 답이 안나오는 듯하니..


현재 ES 를 테스트 하다 보니 index reject 가 거의 100% 나는 나는 문제가 하나 있다.

이래저래 모니터링을 하기 시하고 있는 와중에 인덱싱 성능 향상을 위한 팁이 있는거 같아 내용을 정리해 보고자 한다.


일단 검색을 어떻게 사용하느냐에 따라 많이 달라 질 수 있겠지만 현재 직면한 문제는 검색성능이 아닌 인덱싱 성능에 대해서 문제가 있다.

예를 들어 검색횟수가 적고 어느정도 시간이 오래 걸려도 크게 문제가 없는 업무 / 사용자일 경우이다.


이런 경우에 몇 가지 팁을 공유 하고자 한다.

(사이트 가이드를 보니 해당 팁은 1.3버전 이상에서만 적용하라고 한다. )


과학적인 성능테스트

1. single node, single shard, no replica 상태로 테스트해라.

2. 100% 기본 설정아래에서의 테스트를 기록해 놔라. 이렇게 하면 기준이 되는 측정치를 가늠할 수 있다.

3. 30분 이상의 긴 시간에서 테스트를 해라. 몇몇 이벤트(segment merging, GC 등) 는 금방 발생하지 않기 때문에 시간이 길게 잡고 테스트하는게 좋다.

4. 기본 설정에서 하나씩 바꾸면서 테스트를 해라. 이렇게 해야지 성능 향상에 대한 옵션 변경의 영향이 정확하고 성능 향상이 되면 해당 옵션을 적용한 상태로 다음 테스트를 진행 하는게 좋다.

bulk request 사용

실제 데이터에 따라 달라 질 순 있겠지만 대략 하나의 bulk 요청 당 5~15M정도의 사이즈로 시작하는게 좋다. 알아두어야 할 점은 이 부분은 실제 사이즈라는 점이다. Document 의 수는 중요한 척도가 아니다. 


예를 들어 같은 1000 개의 문서라도 1kb 짜리면 총 1MB 밖에 안되지만 100kb 짜리라고 하면 100MB 가 된다.

이 부분은 상당한 영향을 미칠 수 있는 부분으로 node 에서 메모리에 적재 될 수 있는 부분이기 때문에 중요하다.

다양한 모니터링 툴(Marvel 이나...이건 유료니까..-_-, iostat, top, ps 등) 로 병목이 생기는 부분을 확인해야 한다. 만약 EsRejectedExecutionException 이 발한다면 해당 클러스터 구성은 더이 상 상태를 유지 하기 어렵다. 이럴 경우 데이터의 양을 줄이거나, 디스크를 SSD 로 변경하거나 node 를 추가하거나 해야 한다.

데이터를 수집할 때, 모든 노드에 적절하게 돌아가면서 bulk request 가 요청 되는지 확인을 해야 한다. 노드에서 데이터를 처리하는 동안 모든 요청을 메모리에 저장해야 하기 때문에 모든 요청이 하나의 노드에서만 처리되도록 하면 안된다.


저장소

요즘엔 일반적으로 disk 가 병목현상의 주요 원인이며 ES 는 특히 disk 를 많이 사용하기 때문에 디스크가 좋을 수록 좀 더 안정 되게 서비스 할 수 있다. 아래 몇 가지 최적화를 위한 방법을 참고하자.


* SSD 를 사용해라.

* RAID0 구조를 사용해라.

* 여러개의 드라이브를 사용하는게 좋다. (path.data 에서 설정 할 수 있음)

* NAS를 쓰지 말아라.

* EC2 를 사용중이라면 EBS를 조심해라. EBS 가 SSD 를 지원한다고 하더라도 로컬스토리지보다 종종 느릴 수 있다.

Segments and Merging

Segment 머징 작업은 많은 연산이 필요하고 Disk I/O 도 많이 잡아 먹는다. 머지 작업은 긴 시간이 걸리는 작업이기 때문에 백그라운드에서 진행이 된다. 일반적으로 이 백그라운드 작업은 문제가 없다. 하지만 가끔 머징 작업이 밀리게 되면 자동으로 인덱싱 요청을 싱글쓰레드로 변경한다. 이 작업은 머지가 가능하기 전에 엄청나게 많은 세그먼트가 생성되는 것을 방지하기 위함으로 서버로그를 보면 "now throttling indexing" 이라는 메세지를 출력한다.


이런 현상의 발생 기준이 되는 값을 설정으로 변경 할수 있는데 기본값은 20Mb/s 이다. 이 정도면 일반 디스크에서는 문제 없으나 SSD 를 사용할 경우 값을 올리는게 좋다 ( 100~200정도)

PUT /_cluster/settings {

"persistent" {

"indices.store.throttle.max_bytes_per_sec" : "100mb"

}

}


검색보다 벌크 인덱싱이 중요할 경우 merge throttling 을 모두 끌 수 있다. 만약 이 옵션을 끄게 되면 disk사용가능한 만큼 인덱싱이 빨라진다고 한다.

PUT /_cluster/settings {

"transient" : {

"indices.store.throttle.type" : "none"

}

}


만약 별크인덱싱이 끝나고 다시 원복하려면 "none" 값을 "merge" 로 변경하면 된다.


만약 spinning media disk 를 사용한다면 "index.merge.scheduler.max_thread_count : 1 " 옵션을 추가해야 한다. 

일반 디스크는 일반적으로 I/O 병렬처리 성능이 더 안 좋기 때문에 쓰레드 갯수를 줄이는게 좋다. 이 옵션은 한번에 max_thread_count+2 쓰레드가 작업하도록 허용하며 1로 세팅할경우 3개의 쓰레드 까지 허용한다. 


추가적인 것들

위에 언급한 것들 이외에 아래 내용도 숙지하고 있는걸 추천한다.
* 만약 실시간 검색이 필요하지 않다고 하면 index.refresh_interval 값을 30s 로 낮추는거에 대해서도 고려해 볼만 하다. 만약 대량으로데이터를 들이 부어야 한다면 -1 로 셋팅하여 갱신을 안하도록 한 후 다시 원복하는 방법도 있다.
* 만약 대량의 데이터 입력한다면 index.number_of_replicas : 0 으로 설정하는 것도 방법이다. 




반응형