본문 바로가기
Dev/ElasticSearch

[ElasticSearch] 엘라스틱 서치 (1) - 기본 개념 훑어보기

by ssyoni 2022. 9. 29.
반응형

 

'기초부터 다지는 ElasticSearch 운영 노하우' 책을 읽고 정리한 내용입니다.

 

ElasticSearch란?

Lucene 기반의 오픈소스 검색 엔진. Documents 형식의 문서를 저장하고 검색할 수 있으며 데이터를 통해 분석 작업도 가능하다.

> 특징

  • 준 실시간 검색 엔진
    • 실시간에 준하는 수준의 검색 제공
    • json문서를 입력하면 refresh_interval 파라미터 값(default 1s)에 따라 엘라스틱 서치의 데이터 공간인 샤드에 저장되고 쿼리를 통해 검색이 가능해진다.
  • 클러스터 구성
    • 여러대의 컴퓨터 혹은 구성요소들을 논리적으로 결합하여 전체를 하나의 구성요소처럼 사용할 수 있게 하는 기술
    • 클러스터로 구성하면 높은 수준의 안정성과 부하분산을 시킬 후 있음
      • node1에 문제가 생기면 문제의 노드를 제외하고 다른 노드로 클러스터를 유지할 수 있다.
      • 심화는 4장에서 다룸( 4장 프라이머리와 레플리카 샤드)
      • 클러스터를 구성하는 모든 노드는 메시형태로 요청을 주고받음
        • 메시 형태? 모든 구성요소가 서로 논리적으로 연결되어있어서 직접적으로 통신할 수 있는 네트워크 형태 → 부하분산 가능
      • 클러스터 내에 노드가 많아질수록 부하를 분산시킬 수 있음
  • 스키마 리스(schemaless)
    • 문서를 저장하기 전에 문서에 대한 사전 정의가 필요 없음을 의미
      • RDBMS는 사전에 테이블과 필드를 만들어야 데이터를 저장할 수 있다.
    • 문서를 분석해서 스키마를 동적으로 생성
  • Rest API
    • Rest API로 통신하기 때문에 클라이언트 구성이 자유로움
    • curl로 통신하기 때문에 리눅스 환경에서 간편하게 통신 가능

 

> 설치 종류

  • RPM, DEV, tar
    • 각 배포판에 맞는 자바를 설치해주어야 한다.
    • tar로 설치할 경우 실행 커맨드에 -d 옵션을 붙여줘야 한다. (압축 풀고 실행파일만 클릭해도 엘라스틱이 실행되는데 이는 프로세스를 포어그라운드 형태로 실행시킨 것이기 때문에 터미널에서 다른 입력을 하지 못하는 상태이기 때문이다.)
    • tar 설치 같은 경우는 다소 복잡하지만 장점이 있다.
      • RPM, DEB의 경우 정해진 위치에 파일이 들어가지만 tar형 태일 경우 원하는 위치에 파일을 저장할 수 있다.
      • 하나의 서버에서 다수의 ElasticSearch 노드를 띄울 때 RPM, DEB에 비해 설정이 더욱 쉽다.

 

ElasticSearch 기본 동작

<주제>

  1. 문서를 색인, 조회, 삭제
  2. 인덱스 생성, 삭제
  3. 문서를 검색하고 문서 내용 바탕으로 분석

 

> 문서 색인, 조회, 삭제

문서 색인 요청 명령어

//       1)                  2)    3) 4) 
curl -X PUT "localhost:9300/user/_doc/1?pretty" -H 'Content-Type: application/json' -d
{
	"username": "alden.kang"
}
  1. REST API
  2. 인덱스 이름
  3. 타입 이름
  4. 문서 ID
  • 색인 일어나는 과정

  • 스키마가 없으면 스키마를 생성하고 스키마가 있으면 스키마와 색인 요청된 문서의 충돌을 확인한다.⇒⇒ 충돌이 일어난 필드만 제외하고 나머지 필드만 저장하는 옵션이 별도로 있긴 함 중요!! 기존에 정의된 필드의 타입과 다르면 스키마 충돌이라고 판단하고 에러를 출력하고 색인되지 않는다.
  • 동일한 ID를 가진 문서가 있다면 해당 문서를 수정한다.

 

문서 조회

curl -X GET "localhost:9300/user/_doc/1?pretty"
// 해당 문서의 메타데이터와 함께 조회
{
	"_index": "user",   // 1)
	"_type" : "_doc",   // 2)
	"_id" : "1",        // 3)
	"_version" : 1,
	"_seq_no" : 0,
	"_primary_term" : 1,
	"found" : true,
	"_source" : {       // 4)
		"username" : "alden.kang"
	}
}
  1. 어떤 인덱스에 있는지
  2. 어떤 타입인지
  3. 문서의 ID
  4. 문서의 내용

 

문서 삭제

curl -X DELETE "localhost:9300/user/_doc/1?pretty"
{
	"_index": "user",   
	"_type" : "_doc",   
	"_id" : "1",       
	"_version" : 1,
	"result" : "deleted"   // 1) 정상적으로 삭제
	"_shards" : {
		"total" : 2,
		"successful" : 1,
		"failed" : 0
	}
	"_seq_no" : 0,
	"_primary_term" : 1
}

 

삭제 후 조회 결과

curl -X GET "localhost:9300/user/_doc/1?pretty"
{
	"_index": "user",
	"_type" : "_doc",
	"_id" : "1",
	"found" : false
}

 

> 인덱스 생성 및 조회

인덱스 생성

curl -X PUT "localhost:9300/user/contents?pretty"
{
	"acknowledged" : true,
	"shards_acknowledged" : true,
	"index" : "contents"
}

인댁스 목록 조회 (cat API)

curl -s <http://localhost:9200/_cat/indices?v>
health status index      uuid               pri rep doc.count ...
yellow open  contents  ua0G1ecnStG..  5   1               0 ...

문서 색인

curl -X PUT "localhost:9200/contents/_doc/1?pretty" -H 'Content-Type: application/json' -d'
> {
	>  "title" : "How to use Els",  
	>  "author" : "alden.kang"  
> }  
> '
{
	 "_index" : "contents",  
	 "_type" : "_doc",  
	 "_id" : "1",  
	 "_version" : 1,  
	 "result" : "created",  // 최초 문서 색인시 created
	 "_shards" : {  
	  "total" : 2,  
	  "successful" : 1,  
	  "failed" : 0  
	 },  
	 "_seq_no" : 0,  
	 "_primary_term" : 1  
}

 

문서 수정 후 색인 (동일한 ID 입력)

curl -X PUT "localhost:9200/contents/_doc/1?pretty" -H 'Content-Type: application/json' -d'
> {
	>  "title" : "How to use Els",  
	>  "author" : "alden.kang, benjamin.butn"  
> }  
> '
{
	 "_index" : "contents",  
	 "_type" : "_doc",  
	 "_id" : "1",  
	 "_version" : 2, 1        // 버전 변경 -> 2
	 "result" : "updated",    // 수정 완료 updated
	 "_shards" : {  
		  "total" : 2,  
		  "successful" : 1,  
		  "failed" : 0  
	 },  
	 "_seq_no" : 0,  
	 "_primary_term" : 1  
}

 

스키마 조회

curl -s PUT "localhost:9200/contents/_mappings?pretty
{  ...
  "author" : {  ...  }    
  "title" : {  ......  }  
}

 

동적 스키마 생성

  • 새로운 필드를 생성하면 동적으로 해당 필드가 색인되고 스키마도 추가로 정의된다.
  • 색인할 때 필드의 타입이 맞지 않으면 mapper_parsing_exception : failed to parse field [rating] of type [float] 에러가 발생한다.
  • 스키마 충돌 에러는 로그 수집 시에 로그의 필드 형태가 중간에 바뀔 때 주로 발생하는데 → 해당 로그는 색인이 되지 않아 로그 유실이 발생한다.
  • 즉 스키마 리스라는 것은 스키마가 필요 없다는 것이 아니라, 미리 스키마를 정의하지 않아도 동적으로 정의할 수 있다는 것. 필드 형태는 맞춰주어야 한다.

 

> 문서 검색

검색의 종류는 query와 filter 두 가지가 있다.

 

모든 데이터를 검색하는 풀 스캔 쿼리

curl -X PUT "localhost:9200/books/_search?q=*&?pretty"
{
	"took" : 27,           // 1)
	"time_out" : false,
	"_shard" : {
		"total" : 5,         // 2)
		"successful" : 5,
		"skipped" : 0,
		"failed" : 0
	},
	"hits" : {
		"total" : 10        // 3)
			...
	}
}
  • q = * : 모든 단어 검색
  1. 검색에 소요된 시간
  2. 검색에 참여한 샤드 개수
  3. 검색 결과 개수

⇒ 각각 3ms 소요, 5개 샤드가 참여, 10개의 검색 결과

 

특정 키워드로 검색

curl -X PUT "localhost:9200/books/_search?q=elasticsearch&?pretty"
{
	...
}

 

> 문서 분석

Aggregation

  • search API 기반으로 진행
  • 검색 작업을 바탕으로 분석작업을 말한다.

예제)

등록한 책에서 topics에 어떤 단어가 가장 많이 나오는지

curl -X GET "localhost:9200/books/_search?pretty" -H 'Content-Type: application/json' -d '
> {
>   "size" : 0,
>   "aggs" : {
>     "group_by_status" : {
>       "terms" : {
>         "field" : "topics.keyword"
>       }
>     }
>   }
> }
> '
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    ...
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "WebServers",
          "doc_count" : 3
        },
        {
          "key" : "Hadoop",
          "doc_count" : 2
        },
        {
          "key" : "Chef",
          "doc_count" : 1
        },
        ...
}

 

토픽 별로 평균 몇 개의 리뷰가 생성되어있는지

curl -X GET "localhost:9200/books/_search?pretty" -H 'Content-Type: application/json' -d '
> {
>   "size" : 0,
>   "aggs" : {
>     "group_by_status" : {
>       "terms" : {
>         "field" : "topics.keyword"
>       },
>       aggs" : {
>         "average_reviews" : {
>           "avg" : {
>             "field" : "reviews"
>           }
>         }
>       }
>     }
>   }
> }
> '
{
  "took" : 12,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    ...
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "WebServers",
          "doc_count" : 3,
          "average_revies" : {
            "value" : 8.555555
          }
        },
        {
          "key" : "Hadoop",
          "doc_count" : 2,
          "average_revies" : {
            "value" : 13.0
          }
        },
        {
          "key" : "Chef",
          "doc_count" : 1,
          "average_revies" : {
            "value" : 14.0
          }
        },
        ...
  • 시각화 툴로 분석할 때 주의할 점
    • 분석작업은 경우에 따라 많은 양의 힙 메모리를 필요로 함
    • 특히 분석 작업을 하기 위해 데이터 시간 범위를 지나치게 크게 잡으면 ElasticSearch 클러스터 전체가 응답 불가에 빠질 수 있다.

 

> 모니터링

  1. Head 모니터링은 클러스터 전반적인 동작 상태를 확인하기에 용이하지만 성능 지표 등의 자세한 정보는 확인하기 어렵다.
  2. 프로메테우스 모니터링은 다량의 클러스터를 운영하고 있을 때 구축하기 수월하지만 확인할 수 있는 정보량이 X-Pack 모니터링에 비해 상대적으로 적다.
  3. X-Pack 모니터링은 모니터링 시스템 중 가장 많은 정보를 확인할 수 있지만, 6.3 이전 버전의 경우 Basic 라이선스를 해마다 갱신해야 함. 그리고 클러스터 규모가 클수록 모니터링 데이터를 기록하기 위한 인텍스의 색인이 필요해서 색인 성능에 영향을 줄 수 있다.
반응형

댓글