'Elasticsearch'에 해당되는 글 43건
02. Configuration :: 2015/04/23 17:03
[Environment Variables]
Script 내, Elasticsearch JVM이 시작될 때 넘겨지는 JAVA_OPTS를 포함하고 있다. 그중 가장 중요한 설정은 프로세스의 maximum memory를 다루는 -Xmx와 minimum memory를 다루는 -Xms이다. (일반적으로 더 많은 메모리가 할당될 수록 더 좋다.)
대부분의 경우, JAVA_OPTS를 기본값으로 남겨두는 것이 더 좋다. 그리고 JVM의 설정이나 파라미터를 설정/변경하고자 하는 경우에는 ES_JAVA_OPTS를 사용하라.
ES_HEAP_SIZE 환경 변수는 elasticsearch java process의 heap memory 설정에 사용한다. 별로 추천하고 싶지 않지만, ES_MIN_MEM (default : 256 MB), ES_MAX_MEM (default : 1 GB) 값을 명시적으로 설정할 수 있다. 하지만, ES_HEAP_SIZE를 이용하면 min, max 값 모두 동일한 값을 가지게 된다.
Min, Max 값을 동일하게 설정하고, mlockall (http://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration.html#setup-configuration-memory) 가능하도록 설정하는 것을 추천한다.
[System Configuration]
- File Descriptors (FD)
Elasticsearch를 실행하는 machine의 open files descriptors 숫자를 증가시켜라. 32k나 64k로 설정하는 것을 추천한다.
Process가 얼마나 많은 file을 오픈했는지 테스트하려면 -Des.max-open-files 값을 true로 설정하고 시작하라. Process가 시작 시, 사용할 수 있는 open files 숫자를 표시할 것이다.
아니면, 각각의 node에서 다음과 같은 nodes Info API를 사용하여 max_file_descriptors 값을 얻을 수 있다.
curl localhost:9200/_nodes/process?pretty
- Virtual Memory
Elasticsearch는 index를 저장하는데 hybrid mmapfs / niofs directory (http://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-store.html#default_fs) 를 기본적으로 사용한다. OS의 mmap count에 대한 제한값은 너무 작기 때문에 out of memory exception이 발생한다. Linux에서는 root 계정으로 다음 command를 실행하여 limit값을 증가시킬 수 있다.
sysctl -w vm.max_map_count=262144
이 값을 영구적으로 반영하기 위해서는 /etc/sysctl.conf에 vm.max_map_count 항목을 업데이트하라.
[NOTE]
패키지(.deb, rpm)를 이용하여 Elasticsearch를 설치했다면 자동으로 이 값이 변경되어 있을 것이다. 확인해 보려면 sysctl vm.max_map_count를 실행해 보라.
- Memory Settings
Linux Kernel은 file system cache에 될 수 있으면 많은 메모리를 사용하고 사용하지 않은 application memory, 즉 Elasticsearch process로 인해 swap된 memory를 열심히 swap하려고 한다. Swapping은 성능상, node 안정성 측면에서 아주 좋지 않으므로 피해야 한다.
3가지 옵션이 있다.
- Disable swap
가장 간단한 옵션은 swap을 사용할 수 없도록 하는 것이다. 일반적으로 Elasticsearch는 한 box (서버)안에서 실행되는 유일한 서비스다. 그리고 메모리 사용량은 ES_HEAP_SIZE 환경 변수로 제어할 수 있다. Swap을 사용할 필요가 없다. Linux System에서 실sudo swapoff -a를 실행하여 일시적으로 swap을 사용하지 않도록 할 수 있다. 영구적으로 적용하려면 /etc/fstab file을 편집하여 swap을 포함하고 있는 line들을 주석처리 하면 된다.
- Configure swappiness
두번째 옵션은 sysctl의 vm.swappiness의 값을 0으로 설정하는 것이다. 이것은 kernel이 swap하려고 하는 추세를 감소시키고, 일반적인 환경에서는 swap을 하려고 하지 않는다. 하지만, 긴급상황에서는 여전히 전체 시스템을 swap하려고 할 것이다.
[NOTE]
Kernel version 3.5-rc1과 그 윗버전부터 swappiness를 0으로 하면 swapping을 허용하는 대신에 OOM killer가 process를 죽이려고 할 것이다. 긴급 상황에서 swapping을 허용하려면 swappiness를 1로 설정할 필요가 있다.
- mlockall
세번째 옵션은 Linux/Unix 시스템에서만 사용할 수 있는데, RAM내 process address space를 mlockall을 사용해 Lock하는 것이다. 이것을 사용하면 Elasticsearch의 어떤 메모리도 swap하는 것을 막을 수 있다. config/elasticsearch.yml 파일에 다음 라인을 추가하면 된다.
bootstrap.mlockall: true
Elasticsearch를 시작할 이후, 다음 request를 통해서 mlockall 값을 확인함으로써 성공적으로 적용되었는지를 확인할 수 있다.
curl http://localhost:9200/_nodes/process?pretty
만약 mlockall 값이 false라면 mlockall request가 실패했음을 의미한다. 대부분의 경우에 memory lock 권한이 없는 user가 Elasticsearch를 실행했을 경우에 발생한다. Elasticsearch를 실행하기 전에 root 계정으로 ulimit -1 unlimited를 실행하여 권한을 줄 수 있다.
또 다른 가능성 있는 이유로는 temporary directory (일반적으로 /tmp)가 noexec 옵션으로 mount되었을 경우에 발생한다. 다음과 같이 Elasticsearch를 실행하여 새로운 temp directory를 지정함으로 해결할 수 있다.
./bin/elasticsearch -Djna.tmpdir=/path/to/new/dir
[WARNING]
mlockall은 이용할 수 있는 이상의 메모리를 할당하려고 한다면 JVM이나 shell session에서 빠져나갈 것이다.
- Elasticsearch Settings
Elasticsearch configuration file은 ES_HOME/config 폴더에 있다. 이 폴더에는 2개의 파일이 있는데, elasticsearch.yml은 Elasticsearch의 다른 모듈에 대한 설정이, logging.yml에는 Elasticsearch의 logging에 대한 설정이 있다.
Configuration format은 YAML (http://www.yaml.org/) 이다. 모든 네트워크 기반 모듈들이 바인딩하여 사용하는 주소를 변경하는 예제는 다음과 같다.
network :
host : 10.0.0.4
- Paths
Production의 경우, Data와 Log file의 Path를 변경하고 싶을 것이다.
path:
logs: /var/log/elasticsearch
data: /var/data/elasticsearch
- Cluster name
또한, 다른 node가 자동으로 cluster에 참여할 수 있도록 production cluster name을 주는 것을 잊지 말라.
cluster:
name: <NAME OF YOUR CLUSTER>
- Node name
각각의 node가 hostname을 표시하는데 사용하는 Default node name을 변경하고자 할 경우가 있다. 기본적으로 Elasticsearch는 node가 시작될 때, 3000개의 Marvel Character name 리스트 중에서 Random하게 사용한다.
node:
name: <NAME OF YOUR NODE>
Configuration styles
내부적으로 모든 설정들은 "namespaced" 설정으로 접근할 수 있다. 예를 들어, 위의 설정은 node.name으로 접근할 수 있다. 이것은 다른 형태의 configuration format-JSON과 같은-을 쉽게 지원할 수 있음을 의미한다. Configuration format으로 JSON을 더 선호하면, 간단하게 elasticsearch.yml을 elasticsearch.json으로 변경하고 다음 내용을 추가하면 된다.
{
"network" : {
"host" : "10.0.0.4"
}
}
또한 다음과 같이 ES_JAVA_OPTS나 elasticsearch command에 parameter를 이용하여 외부에서 설정을 쉽게 제공할 수 있다.
$ elasticsearch -Des.network.host=10.0.0.4
또다른 옵션은 es. Prefix 대신에 es.default. Prefix를 사용하는 것이다. 이것은 configuration file내에 명시적인 설정이 없을 경우에만 default 설정을 사용함을 의미한다.
또다른 옵션은 ${…..} notation을 configuration file안에 사용하는 것이다. 다음과 같이 환경 설정 변수를 사용할 수 있다.
{
"network" : {
"host" : "${ES_NET_HOST}"
}
}
Configuration file의 위치는 system property를 사용하여 외부에서 설정할 수 있다.
$ elasticsearch -Des.config=/path/to/config/file
- Index Settings
Cluster에 생성된 index들은 각자 설정을 가질 수 있다. 예를 들어, 다음은 기본적인 파일 시스템 기반 대신에 메모리 기반 index를 생성한다. (포맷은 YAML / JSON 모두 가능하다.)
$ curl -XPUT http://localhost:9200/kimchy/ -d \
'
index :
store:
type: memory
'
Index level 설정은 elasticsearch.yml 파일내 다음과 같이 node level에 설정될 수 있다.
index :
store:
type: memory
이것은 위에 언급된 configuration으로 시작된 특정 node에서 생성된 모든 index는 분명하게 설정되지 않으면 메모리에 index를 저장한다는 것을 의미한다. 다시 말하면, node configuration에 설정된 것이 무엇이건 간에 index level은 재정의가 가능하다는 것이다. 물론, 위의 경우에는 다음과 같은 "collapsed" 설정이 가능하다.
$ elasticsearch -Des.index.store.type=memory
Index level configuration의 모든 것은 각 index module (http://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html) 에 있다.
- Logging
Elasticsearch는 내부의 logging abstraction을 이용하여 log4j 설정을 적용한다. YAML을 사용하여 log4j 설정을 간단하게 적용할 수 있다. (로그 설정 파일은 config/logging.yml 이다.) JSON과 properties 포맷 또한 지원된다. 더 자세한 내용은 log4j document (http://logging.apache.org/log4j/1.2/manual.html) 를 참조하라. 추가로 log4j-extras에서 제공하는 다른 Appender나 logging class도 사용할 수 있다.
01. Installation :: 2015/04/23 15:04
이 섹션에는 elasticsearch를 어떻게 설치하고 실행하는지에 대한 정보가 담겨 있다. 아직 다운로드 하지 않았으면, 다운로드 (http://www.elasticsearch.org/download) 하고 설치 문서 (http://www.elastic.co/guide/en/elasticsearch/reference/current/setup.html#setup-installation) 를 확인하라.
[NOTE]
Elasticsearch 는 apt나 yum을 이용해서 우리의 Repository로부터 설치를 할 수도 있다. Repository (http://www.elastic.co/guide/en/elasticsearch/reference/current/setup-repositories.html) 섹션을 참고하라.
[Installation]
최종 버전을 다운로드하고 압축 해제 후, Elasticsearch는 다음 command로 실행할 수 있다.
$ bin/elasticsearch
*nix 시스템 (Unix, Linux) 상에서는 foreground process로 실행된다. Background process로 실행하려면 다음과 같이 -d switch를 추가하면 된다.
$ bin/elasticsearch -d
*NIX
Elasticsearch shell script를 사용하여 여러 features들을 추가할 수 있다. 첫번째는, 앞서 설명했듯이, foreground / background process로 쉽게 실행할 수 있다.
또다른 특징으로 -X, -D, getopt long style configuration parameter를 script로 직접 전달할 수 있다. JAVA_OPTS나 ES_JAVA_OPTS를 사용하여 모든 설정을 재정의할 수 있다. 예를 들면 다음과 같다.
$ bin/elasticsearch -Xmx2g -Xms2g -Des.index.store.type=memory --node.name=my-node
[Java (JVM) version]
Elasticsearch는 Java를 사용하여 빌드 되었다. 실행하기 위해서는 최소한 Java 7이 필요하다. 단지 Oracle Java와 OpenJDK만 지원된다. 모든 Elasticsearch node와 client에는 동일한 버전의 JVM이 설치되어 있어야 한다.
Java 8 update 20 이상이나 Java 7 update 55 이상 버전을 설치하기를 권장한다. 이전 버전의 Java 7에서는 index corruption과 data loss에 대한 bug가 있다. Elasticsearch는 java 1.5.0으로 알려진 잘못된 버전으로 실행하면 실행되지 않을 것이다.
사용하는 Java의 버전은 JAVA_HOME 환경 변수로 설정할 수 있다.
21. Conclusion :: 2015/04/23 13:28
Elasticsearch는 단순하기도 하고 복잡하기도 한 제품이다. 기본적인 개념이 무엇인지, 내부가 어떻게 생겼는지, REST API를 통해서 어떻게 작업을 수행하는지를 공부했다. 이 tutorial을 통해서 여러분이 Elasticsearch가 무엇인지를 더 잘 이해하고, 더 중요하게, 나머지 다른 굉장한 기능들을 통해 더 많은 시험을 할 수 있는 영감을 줄 수 있기를 바란다.
20. Exploring Your Data - Executing Aggregations :: 2015/04/23 13:24
[Executing Aggregations]
Aggregations는 데이터를 group하고 통계를 추출하는 기능을 제공한다. Aggregation에 대해서는 SQL GROUP BY와 SQL aggregate function과 거의 같다고 생각하는 것이 가장 쉽다. Elasticsearch에서는 하나의 response 안에 hit를 리턴하는 검색과 hit별로 분리된 aggregated result를 동시에 실행하는 기능이 있다. 이것은 굉장히 강력하고 효율적인 기능이다. 여러분은 query와 multiple aggregation을 실행하여 간결하고 간단한 API를 통해서 네트워크의 빈번한 호출을 피하고, 한번에 두개 혹은 하나의 결과를 받아볼 수 있다.
다음 에제는 상태별로 모든 account를 group하고, count 내림차순 정렬된 결과 중에서 top 10개의 state를 리턴하는 것을 보여준다.
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state":
{
"terms": {
"field":
"state"
}
}
}
}'
SQL에서는 위의 aggregation 예제는 다음 개념과 유사하다.
SELECT COUNT(*) from bank GROUP BY state ORDER BY COUNT(*) DESC
응답 결과의 부분적인 내용은 다음과 같다.
"hits" : {
"total" : 1000,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"group_by_state" : {
"buckets" : [ {
"key" : "al",
"doc_count" : 21
}, {
"key" : "tx",
"doc_count" : 17
}, {
"key" : "id",
"doc_count" : 15
}, {
"key" : "ma",
"doc_count" : 15
}, {
"key" : "md",
"doc_count" : 15
}, {
"key" : "pa",
"doc_count" : 15
}, {
"key" : "dc",
"doc_count" : 14
}, {
"key" : "me",
"doc_count" : 14
}, {
"key" : "mo",
"doc_count" : 14
}, {
"key" : "nd",
"doc_count" : 14
} ]
}
}
}
위에서 AL(abama)에 21개의 account, 그 다음으로 TX에 17개의 account, ID에 15개 등등이 있음을 알 수 있다. size=0으로 설정하면 response에서 aggregation 결과만 보고 싶은 경우이기 때문에 search hit을 보여주지 않는다.
다음 예제는 state별로 account balance의 평균을 계산하는 것을 보여준다.
(역시, 내림차순 정렬하여 top 10개만 출력한다.)
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state":
{
"terms": {
"field":
"state"
},
"aggs": {
"average_balance":
{
"avg": {
"field":
"balance"
}
}
}
}
}
}'
어떻게 group_by_state aggregation내에 average_balance aggregation을 연결했는지 주목하라. 모든 aggregation은 이와 같은 공통된 pattern을 가지고 있다. 여러분이 데이터로부터 구하고자 하는 독자적인 요약 정보를 추출하는 aggregation내에 연결된 aggregation을 가질 수 있다. 앞에서 수행한 aggregation에서 내림차순으로 average balance를 정렬해 보자.
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state":
{
"terms": {
"field":
"state",
"order": {
"average_balance":
"desc"
}
},
"aggs": {
"average_balance":
{
"avg": {
"field":
"balance"
}
}
}
}
}
}'
다음 예제는 어떻게 우리가 연령대별로, 성별에 따라 group할 수 있는지, 마지막으로 어떻게 연령대별, 성별에 따른 average account balance를 구할 수 있는지를 보여준다.
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_age":
{
"range": {
"field":
"age",
"ranges": [
{
"from":
20,
"to": 30
},
{
"from":
30,
"to": 40
},
{
"from":
40,
"to": 50
}
]
},
"aggs": {
"group_by_gender": {
"terms": {
"field":
"gender"
},
"aggs": {
"average_balance":
{
"avg": {
"field":
"balance"
}
}
}
}
}
}
}
}'
여기에서 우리가 상세히 다루지 않은 다른 많은 aggregation 기능이 있다. Aggregation reference guide (http://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html) 를 통해서 더 많은 내용을 알 수 있다.
19. Exploring Your Data - Executing Filters :: 2015/04/22 19:02
[Executing Filters]
앞 섹션에서 document score (검색 결과의 _score 필드)에 대해서는 자세히 다루지 않고 넘어 갔었다. Score는 우리가 검색하고자 한 query와 document가 얼마나 match하는지를 측정한 숫자 값이다. Score가 높을수록 더 적합한 document이고, Score가 낮을수록 덜 적합한 document이다.
Elasticsearch의 모든 query는 적합성 score (점수)의 계산을 수행한다. 적합성 점수 (relevance score)가 불필요한 경우에 Elasticsearch는 query-dsl-filter, filter 형태의 또 다른 기능을 제공한다. Filter는 2가지 중요한 이유 때문에, 개념적으로 query를 더 빠르게 수행하도록 최적화 하는 것과 같다.
- Filter는 score 계산을 하지 않기 때문에 query보다 빠르다.
- Filter는 반복되는 검색 결과를 memory에 cache할 수 있기 때문에 query보다 빠르다.
Filter를 이해하기 위해서는, query와 filter를 조합한 filtered Query (http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-filtered-query.html) 에 대해서 먼저 아는 것이 좋다.
예를 들어, range filter를 소개하자면, 값의 range에 따라 document를 filter할 수 있다. 일반적으로 숫자나 날짜별로 filter를 적용하여 사용한다.
다음 예제는 20000과 30000 사이의 balance를 가지는 모든 account를 리턴하는 filtered query를 사용한 것이다. 다른 말로 하자면, 20000 이상 30000 이하의 balance를 가진 account를 찾고 싶은 것이다.
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"filtered": {
"query": {
"match_all": {} },
"filter": {
"range": {
"balance":
{
"gte":
20000,
"lte":
30000
}
}
}
}
}
}'
위 내용을 분석해 보면, filtered query는 query part인 match_all query와 filter part인 range filter를 포함하고 있다. 다른 query로 query part를 대체할 수 있고, 다른 filter로 filter part를 대체할 수 있다. 위의 경우에 range filter는 모든 document들이 range안에 동일하게 들어오기 때문에 완벽하다. 즉, 모든 document가 동일하다.
일반적으로 어떤 filter나 query를 원하는지 결정하는 가장 쉬운 방법은 relevance score (적합성 점수)를 신경 쓰는지 스스로에게 물어보는 것이다. Relevance score (적합성 점수)가 중요하지 않다면 filter를 사용하고, 중요하다면 query를 사용하라. SQL 배경지식이 있다면, query와 filter는 SELECT WHERE 절 개념과 유사하다. 비록 filter가 query보다 조금 더 유사하지만.
게다가, match_all, match, bool, filtered, range query 이외에도 다른 많은 이용할 수 있는 query/filter들이 있다. 여기서는 깊이 다루지 않을 것이다. 어떻게 동작하는지에 대한 기본적인 이해를 하고 있기 때문에, 다른 query/filter를 배우고 시험하면서 이런 지식을 활용하는데 어렵지는 않을 것이다.