사용자 도구

사이트 도구


search:elasticsearch

Elastic Search

최대 색인 수

  • Shard 한개(Lucene 인덱스 하나)는 최대 21억건 문서, 2740억건의 고유 term까지만 허용한다.
  • 따라서 데이터 증강량을 판별하여 이에 맞게 Sharding 수준을 정해야한다.

노드 구성

  • node.data=true/false : 실제 색인을 가지고 있는 데이터 노드가 될 수 있는지 여부
  • node.master=true/false : 마스터 노드가 될 수 있는지 여부
  • node.data=false, node.master=false 인 검색 클라이언트 전용노드를 만들어서, 검색 요청을 여기서 받은 뒤에 데이터 노드에 검색을 요청하는 것이 가능하다. 이렇게 하면 실제 색인을 가진 데이터 노드는 클라이언트로부터의 socket 연결을 위한 오버헤드와 메모리 사용량을 줄일 수 있게 된다.

Sharding Routing

  • 만약 Search 를 명확히 특정 Shard 단위로 할 수 있다면 샤딩을 촘촘히 해도 읽기/쓰기 성능이 모두 좋지만
  • Sharding 기준이 명확하지 않아서 여러 Shard 에 걸쳐 Search 를 해야한다면, Shard 를 늘릴 수록
    • 읽기 성능은 저하된다.
    • Write Primary 노드는 여러개로 분산 되므로 Write 성능은 높아진다.

Routing 강제

라우팅을 강제할 수 있다. 라우팅 옵션 없이는 인덱싱 불가.

"mappings": {
  "[indexname]": {
    "_routing": {
      "required": true
    }
  }
}

Cluster 관리

  • host:9200/_cluster/settings?pretty : Cluster 상태 조회
  • host:9200/_cluster/health?pretty : Cluster health check Cluster Health

Docker로 띄우면서 Clustering 할 때

  • Docker로 ES를 띄울 경우 network 설정이 복잡해진다.
  • 가장 쉬운 해결책 : network.host=0.0.0.0으로 하고 docker 실행시 --net=host 옵션을 준다. 하지만 이 경우 보안상 등의 문제가 있을 수 있다고 함.
  • 더 좋은 방법은 docker 를 띄우는 HOST의 IP를 network.publish_host에 직접 바인딩해준다.
    # network.host는 삭제하고, bind_host는 아래와 같이. eth0 는 다른 interface 일 수 있음
    network.bind_host: _eth0:ipv4_ # 혹은 0.0.0.0 도 가능한지 확인할 것.
    
    # elasticsearch 실행시 network.publish_host를 인자로 넘기고,
    --network.publish_host $ES_PUBLISH_HOST
    
    # docker 실행시에 다음 명령으로 해당 Host 서버의 IP값을 넣어준다.
    docker run ... -e ES_PUBLISH_HOST=`hostname -I | awk '{print $1}'`
    
    # AWS EC2 인스턴스에서는 
    docker run ... -e ES_PUBLISH_HOST=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`

Docker로 띄울 때 옵션

Docker run 시에 다음 옵션을 추가해야 한다.

# JVM Heap Swap 방지 설정이 돼 있을 때 아래 옵션을 줘서 실행해야 한다. (bootstrap.mlockall: true)
# --cap-add=IPC_LOCK --ulimit memlock=-1:-1
docker run --cap-add=IPC_LOCK --ulimit memlock=-1:-1 ...
 
# 그렇지 않으면 다음과 같은 오류 발생하고 메모리 설정이 올바로 작동 안함
Unable to lock JVM Memory: error=12,reason=Cannot allocate memory
This can result in part of the JVM being swapped out.
Increase RLIMIT_MEMLOCK, soft limit: 65536, hard limit: 65536
These can be adjusted by modifying /etc/security/limits.conf, for example: 
	# allow user 'someuser' mlockall
	coupang soft memlock unlimited
	coupang hard memlock unlimited
If you are logged in interactively, you will have to re-login for the new limits to take effect.

JVM Heap Dump를 떠야 할 때 대비해서 다음 옵션도 추가

--cap-add=SYS_PTRACE

Linux 설정

환경변수

  • JAVA_OPTS : Java 기본 옵션들
  • ES_HEAP_SIZE : -Xmx, -Xms에 같은 값으로 들어감
  • ES_HEAP_NEWSIZE : -Xmn
  • ES_DIRECT_SIZE : -XX:MaxDirectMemorySize
  • ES_GC_OPTS : Java Garbage Collection 관련옵션
  • ES_GC_LOG_FILE : GC log 파일관련 옵션

최적화

Write Performance

Memory

G1 GC

Disk Size

RollingFileAppender로 변경

  • 로그의 수집 몇 관리가 어려운 경우 차라리 RollingFileAppender를 사용하는게 관리 측면에서 유리함
  • 용량이 증가해서 maxFileSize(byte) 를 초과하면 maxBackupIndex 한도 내에서 파일 이름에 번호를 붙이면서 덮어쓴다.
  file:
    type: rollingFile
    file: ${path.logs}/${cluster.name}.log
    maxFileSize: 104857600
    maxBackupIndex: 10
    layout:
      type: pattern
      conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %.10000m%n"

주의점

  • 한 클러스터에서는 모두 동일 JVM 버전을 사용해야한다. 안 그러면 직렬화가 달라서 문제가 발생할 수 있다.
  • 한 번 Version Upgrade 한 뒤 indexing을 하면 다시 Downgrade 할 수 없다. index를 백업 한 뒤에 업그레이드하라.
  • 2.x 버전에서 Tokenizer Plugin 을 사용할 때, 기본 Tokenizer type 이름과 tokenizer 이름이 다를경우 해당 토크나이저의 설정 정보가 처음에는 올바른 상태로 그리고 다시 한 번은 null 인 상태로 XxxTokenizerFactory 생성자가 한 번 더 호출되는 문제가 있다. 이에 따라 type 이름과 토크나이저 이름을 동일하게 맞춰줘야 했다. 이 경우 생성자가 인덱스당 한 번씩만 호출되었다.

참조

search/elasticsearch.txt · 마지막으로 수정됨: 2023/04/29 14:03 저자 kwon37xi