Category Archives: Big Data

Elasticsearch 성능 설정 항목

Segment Merging

SSD를 사용한다면 indices.store.throttle.max_bytes_per_sec을 기본값인 20mb/s에서 100~200MB/S으로 상향 조정한다.

 

refresh_interval과 마찬가지로, 트랜스로그가 플러쉬되는 주기가 짧을수록 생성되는 세그먼트 수도 줄어든다. 

index.translog.flush_threshold_sizeindex.translog.flush_threshold_ops를 상향 조정한다.

  • index.translog.flush_threshold_size
    – 기본값: 512mb
  • index.translog.flush_threshold_ops
    – 기본값: unlimited

 

출처

 

 

Indexing

indices.memory.index_buffer_size

노드에 할당된 전체 메모리 중 색인 프로세스에 할당할 메모리 량(기본값: 10%)

 

indices.memory.index_buffer_size을 비율로 지정한 경우 아래 설정 가능

  • min_index_buffer_size
    – 기본값: 48mb
  • max_index_buffer_size
    – 기본값: unbounded

 

출처

 

 

Filter Cache

indices.cache.filter.size

노드에 할당된 전체 메모리 중, 필터 검색 결과를 캐싱할 메모리 량(기본값: 10%).

LRU(Least Recently Used) 메모리 회수(eviction) 정책을 따름

 

출처

Memory
Elasticsearch가 사용할 메모리는  $ES_HEAP_SIZE 파라미터 등으로 할당.
노드의 가용 메모리 중 50%를 넘지 않아야 한다.
Elasticsearch는 내부적으로 루씬을 사용하며, 루씬은 파일시스템 캐시(filesystem cache)를 활용한다.
한번 생성된 세그먼트는 삭제/병합되지 않는 한 변경이 없으므로, OS가 자주 쓰이는 세그먼트를 파일시스템 캐시에 유지할 가능성이 높다. 따라서 OS의 파일시스템 캐시를 위해 가용 메모리 중 50%는 OS를 위해 남겨둔다.
32GB 이하를 할당한다.
32GB를 넘는 경우, 객체에 대한 포인터를 저장하기 위해 4바이트가 아닌 8바이트 포인터를 사용하며, 이는 메모리 낭비를 유발한다.
출처
Fielddata Memory
indices.fielddata.cache.size
LRU 필드데이터를 삭제하지 않고 fielddata에 유지할 수 있는 최대 메모리 량.
새로운 필드에 대한 검색 요청이 들어오면, 인덱스의 모든 문서에서 해당 필드의 값을 fielddata에 추가.
최종 fielddata 크기가 indices.fielddata.cache.size보다 크면, LRU 메모리 회수 정책을 따름
 
기본값은 unbounded다.
  • 필드데이터에 추가된 필드 값들은 절대로 메모리에서 삭제되지 않음. 
  • 메모리가 indices.breaker.fielddata.limit(기본값: 60%)까지 쌓이면, 새로운 세그먼트의 필드데이터는 메모리로 로드되지 않게되고, 검색되지 않게 됨.
  • 이를 방지하려면, indices.fielddata.cache.size를 설정하여 LRU 필드데이터들을 삭제하고 새로운 필드데이터를 추가할 수 있도록 해야 함.
    indices.fielddata.cache.size: 40%
최상의 방법은 메모리 증설 하는 것. LRU 필드데이터를 삭제하고, 디스크에서 새로운 필드데이터를 추가하는 작업이 반복되면
  • 무거운 DISK I/O가 발생하고
  • 무거운 GC가 발생
NEVER
indices.fielddata.cache.expire는 절대로 설정하지 말 것!!!
 
Fielddata Circuit Breaker
새로운 필드에 대한 검색 요청이 들어오면, 먼저 인덱스의 모든 문서에서 해당 필드의 값을 fielddata에 추가한 후, 변경된 fielddata의 사이즈를 검사한다.
따라서 indices.breaker.fielddata.limit(기본값: 60%)을 설정했더라도, 새로운 검색 요청으로 인해 추가되는 fielddata의 사이즈가 40%를 넘게 되면 노드의 힙 메모리 사이즈 범위를 벗어나게 되고, 결국은 OutOfMemoryException이 발생하여 노드가 장애 상태에 빠진다.
이를 방지하기 위해 Elasticsearch에서는 fielddata circuit breaker를 설정할 수 있다.
indices.breaker.fielddata.limit
fielddata 메모리 최대량(기본값: 60%)
indices.breaker.request.limit
검색 요청으로 인해 추가될 fieldaata 메모리 예측 최대량(기본값: 40%)
indices.breaker.total.limit
indices.breaker.fielddata.limit + indices.breaker.request.limit(기본값: 70%)
검색 요청이 들어 왔을 때 각 circuit breaker는 설정값을 넘는지 검사 후, 초과하는 경우 예외를 리턴한다.
하지만 OutOfMemoryException는 발생하지 않으므로, 노드가 장애 상태에 빠지게 되는 일은 방지할 수 있다.
출처

 

elasticsearch rolling restart

elasticsearch 클러스터 운영시, 플러그인을 추가하거나 버전 업그레이드와 같은 이유로 클러스터 전체를 재기동해야 하는 상황이 있다.

하지만 전체 서비스는, 특히 검색 서비스는 사용할 수 있도록 한 채, 클러스터 전체를 재기동하기 위해서는 각 노드를 하나씩 재기동해야 하며 이를 rolling restart라고 부른다.

이때 단순히 노드를 하나씩 재기동하기 전에 반드시, 인덱스 재할당(index rebalance or index allocation)을 disable 해야 한다.

실제로 해당 노드에 장애가 발생한 경우라면, 인덱스가 균등하게 분포하도록 인덱스가 재할당되는 것이 맞다.

하지만 운영상의 이유로 관리자가 수작업으로 노드를 하나씩 재기동하는 경우라면, 짧은 시간만 노드가 shutdown될 것이며, 이 경우에는 인덱스 재할당이 불필요하다.

비교) 하둡 commissin / decommission

하둡 HDFS의 경우 노드를 추가/제거할 때 commission / decommission 작업을 하여 데이터 노드의 데이터를 밸런싱하는 작업을 수행한다.

 

각 노드를 중지하기 전에, 클러스터의 인덱스 재할당을 disable 하려면 cluster.routing.allocation.enable을 none으로 변경한다.

 

각 노드를 재기동한 후에는, 클러스터의 인덱스 재할당을 enable 한다.

 

밸런싱 작업이 끝난 후, 클러스터의 상태가 녹색불이 뜬 후 나머지 노드도 동일한 방식으로 재기동한다.

 

아래는 elasticearch rolling restart를 위한 스크립트(https://gist.github.com/lamchakchan/aac7089dfc3daab3ce59)를 약간 수정한 스크립트다.

 

참고자료