====== Elastic Search ====== * [[search:elasticsearch:query|ElasticSearch Query]] * http://www.elasticsearch.org/ : built on top of Apache Lucene * [[https://aws.amazon.com/ko/elasticsearch-service/|Amazon Elasticsearch Service]] ===== 최대 색인 수 ===== * 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 [[https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html|Cluster Health]] ===== Docker로 띄우면서 Clustering 할 때 ===== * [[:docker|Docker]]로 ES를 띄울 경우 ''network'' 설정이 복잡해진다. * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html|Install Elasticsearch with Docker | Elasticsearch Reference]] * 가장 쉬운 해결책 : ''network.host=0.0.0.0''으로 하고 docker 실행시 ''%%--%%net=host'' 옵션을 준다. 하지만 이 경우 보안상 등의 문제가 있을 수 있다고 함. * [[http://stevesmashcode.com/devops/Elastic-Search-in-Docker/|How to Setup Elastic Search in Docker Containers]] * 더 좋은 방법은 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 설정 ===== * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html|Virtual memory | Elasticsearch Reference]] sysctl -w vm.max_map_count=262144 * [[linux:performance|Linux Performance]] ===== 환경변수 ===== * ''JAVA_OPTS'' : Java 기본 옵션들 * ''ES_HEAP_SIZE'' : ''-Xmx, -Xms''에 같은 값으로 들어감 * ''ES_HEAP_NEWSIZE'' : ''-Xmn'' * ''ES_DIRECT_SIZE'' : ''-XX:MaxDirectMemorySize'' * ''ES_GC_OPTS'' : [[java:gc|Java Garbage Collection]] 관련옵션 * ''ES_GC_LOG_FILE'' : GC log 파일관련 옵션 ===== 최적화 ===== * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-replication.html|Reading and Writing documents]] * ''index.refresh_interval: 시간s'' : 인덱스를 push 하는 시간이라고 보면 되는데 ''5s'' 형태로 준다. 길수록 CPU 점유율은 떨어지지만 검색에 안나오는 시간도 길어진다. * ''bootstrap.mlockall: true'' : Linux 등에서 ES의 메모리를 swapping 하지 않게 설정 등. * [[https://qbox.io/blog/optimizing-elasticsearch-how-many-shards-per-index|Optimizing Elasticsearch How Many Shards per Index? 최적의 Shard 갯수는]] * 불필요하게 많은 Shard는 메모리와 리소스를 현저히 낭비하게 만든다. * 메모리는 31GB 혹은 32bit Pointer가 될수 있는 max 값. * Shard 는 최대 30GB가 될 정도 수준으로 구성.(Replica 도 계산시 단일 Shard로 쳐서) * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-search-speed.html|Tune for search speed]] * [[https://qbox.io/blog/optimizing-elasticsearch-how-many-shards-per-index|Optimizing Elasticsearch: How Many Shards per Index?]] ===== Write Performance ===== * Sharding 을 하지 않을 경우 모든 Write 요청이 하나의 Primary Data Node로 집중된다. * Sharding 을 하면 각 Shard 별 Data Node로 분할 된다. * Write Thread 는 CPU 갯수만큼 생성된다. 그리고 Queue가 200개 할당된다. * Qeueue 갯수를 넘는 Write/Update 요청이 들어오면 reject 오류가 발생한다. * Write Thread 를 늘리고자 한다면 Scale Up 해서 CPU 갯수를 늘린다. Queue 갯수를 늘리는 것은 미봉책이므로 하지 않는 것이 좋다. * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html|Tune for indexing speed]] * [[https://www.elastic.co/kr/blog/why-am-i-seeing-bulk-rejections-in-my-elasticsearch-cluster|Why am I seeing bulk rejections in my Elasticsearch cluster?]] * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html|Thread Pool]] * [[https://www.datadoghq.com/blog/elasticsearch-performance-scaling-problems/|How to solve 5 Elasticsearch performance and scaling problems]] * [[https://brunch.co.kr/@alden/36|rejected exception의 의미와 조치 방법]] * ''cat threadpool'' GET /_cat/thread_pool ===== Memory ===== * **32GB** 넘기지 말 것. * [[https://brunch.co.kr/@alden/35|ElasticSearch와 Heap 메모리]] ===== G1 GC ===== * G1 GC로 가려면 [[search:lucene|Lucene]] 관련 버그들이 해결된 [[java:10|Java 10]] 이상 버전 권장. * [[https://brunch.co.kr/@alden/45|G1 GC 적용과 JVM Upgrade]] * [[https://medium.com/naukri-engineering/garbage-collection-in-elasticsearch-and-the-g1gc-16b79a447181|Garbage Collection in Elasticsearch and the G1GC – Naukri Engineering – Medium]] * [[https://sematext.com/blog/java-9-elasticsearch-benchmark/|Java 9 Elasticsearch Benchmark: upgrading benefits]] ===== Disk Size ===== * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-disk-usage.html|Tune for disk usage ]] ===== RollingFileAppender로 변경 ===== * 로그의 수집 몇 관리가 어려운 경우 차라리 [[https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/RollingFileAppender.html|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 이름과 토크나이저 이름을 동일하게 맞춰줘야 했다. 이 경우 생성자가 인덱스당 한 번씩만 호출되었다. ===== 참조 ===== * [[http://blog.trifork.com/2013/10/24/how-to-avoid-the-split-brain-problem-in-elasticsearch/|How to avoid the split-brain problem in elasticsearch]] * [[http://www.popit.kr/%ec%97%98%eb%9d%bc%ec%8a%a4%ed%8b%b1%ec%84%9c%ec%b9%98es-%ed%81%b4%eb%9f%ac%ec%8a%a4%ed%84%b0-%ec%9e%ac%ec%8b%9c%ec%9e%91-%ed%98%b9%ec%9d%80-%ec%97%85%ea%b7%b8%eb%a0%88%ec%9d%b4%eb%93%9c-tip/|엘라스틱서치(ES) 클러스터 재시작 혹은 업그레이드 Tip | Popit]] * [[https://blog.frankel.ch/elasticsearch-api-cheatsheet/|ElasticSearch API cheatsheet]] * [[https://www.javacodegeeks.com/2017/03/elasticsearch-java-developers-elasticsearch-java.html|Elasticsearch for Java Developers: Elasticsearch from Java | Java Code Geeks - 2017]] * [[https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-mapping-charfilter.html|Mapping Char Filter | Elasticsearch Reference [6.2] | Elastic]] 특수 문자등의 검색 * [[https://esbook.kimjmin.net/|Elastic 가이드 북 - Elastic 가이드북]] * [[https://aws.amazon.com/ko/premiumsupport/knowledge-center/opensearch-latency-spikes/|Amazon OpenSearch Service의 검색 대기 시간 스파이크 문제 해결]]