[Infra] 엘라스틱서치(ElasticsSearch) 정리

업데이트:

엘라스틱서치(elastics search) 정리

관련링크
하둡에 대해 알아보자

0. 엘라스틱서치 기본 개념

  • 검색엔진(search engine): 광활한 웹에서 정보를 수집해 검색 결과를 제공하는 프로그램.
  • 검색시스템(saerch system): 대용량 데이터를 기반으로 신뢰성 있는 검색 결과를 제공하기 위해 검색엔진을 기반으로 구축된 시스템을 통칭하는 용어. 수집기를 이용해 방대한 데이터를 수집하고 이를 다수의 검색엔진을 이용해 색인하고 검색 결과를 UI로 제공함. 시스템 내부의 정책에 따라 관련도가 높은 문서를 검색 결과의 상위에 배치할 수 있으며, 특정 필드나 문서에 가중치를 둬서 검색의 정확도를 높일 수 있다.
  • 검색 서비스(search service): 검색엔진을 기반으로 구축한 검색 시스템을 활용해 검색 결과를 서비스로 제공

검색 서비스 > 검색 시스템 > 검색엔진

엘라스틱서치는 엄밀히 말하자면 검색엔진이다. 그리고 엘라스틱서치를 이용해 검색 시스템을 구축한다. 엘라스틱서치는 내부적으로 루씬을 통해 검색기능을 수행한다.

0-1. 검색 시스템의 구성요소

  • 수집기
    웹사이트, 블로그, 카페등 웹에서 필요한 정보를 수집함. 크롤러라고도 불림. 파일의 경우 수집기가 파일명, 파일내용, 파일경로 등의 정보를 수집하고 저장하면 검색엔진이 저장된 정보를 검색하고, 사용자 질의에 답함.

  • 스토리지
    수집한 데이터를 저장하는 물리적인 저장소. 검색엔진은 색인한 데이터를 스토리지에 보관함.

  • 색인기
    수집한 데이터를 적절한 형태로 변환함. 검색엔진이 수집한 정보에서 사용자 질의와 일치하는 정보를 찾으려면 수집된 데이터를 검색 가능한 구조로 가공하고 저장해야한다. 색인기는 다양한 형태소 분석기를 조합해 정보에서 의미 있는 용어를 추출하고 검색에 유리한 역색인 구조로 데이터를 저장한다.

  • 검색기
    색인된 데이터에서 일치하는 문서를 찾음. 검색기는 사용자 질의를 입력받아 색인기에서 저장한 역색인 구조에서 일치하는 문서를 찾아 결과로 반환한다. 질의와 문서가 일치하는지는 유사도 기반의 검색 순위 알고리즘으로 판단한다.

0-2 엘라스틱서치 vs RDB

엘라스틱서치 관계형 데이터베이스
인덱스(Index) 데이터베이스(Database)
샤드(Shard) 파티션(Partition)
타입(Type) 테이블(Table)
문서(Document) 행(Row)
필드(Field) 열(Column)
매핑(Mapping) 스키마(Schema)
Query DSL SQL

인덱스에는 원하는 만큼의 많은 문서를 저장할 수 있으며 실제로는 물리적인 샤드 형태로 나눠져서 다수의 노드로 분산 저장(수평분할)한다. 엘라스틱서치에서는 인덱스를 생성할 때 기본적으로 5개의 샤드로 데이터가 분산되도록 생성되고 설정에 의해 샤드의 개수를 원하는 만큼 변경할 수도 있다. 샤드는 인덱스의 전체 데이터를 분산해서 가지고 있는 일종의 부분집합이라고 이해하면 된다.

인덱스와 타입의 관계: 과거에는 여러 유형의 문서를 동일한 인덱스에 저장할 수 있도록 타입이라는 개념을 제공했다. 타입을 이용해 한 인덱스 내부에 데이터를 논리적으로 분리해서 사용하는 것이 목적이었으나 다양한 문제로 인해 현재는 폐기 예정됐기 때문에 사용해서는 안된다. 과거에는 인덱스 내부에 여러 개의 타입을 생성하는 것이 가능했지만, 현재는 하나의 인덱스에는 하나의 타입만 생성해야한다(ver 6.0 이후).

원래 색인이라는 단어는 데이터가 토큰화 되어 저장된 자료구조를 의미하며 Index라는 단어를 번역한 것이다. 엘라스틱서치에서는 인덱스라는 용어를 다소 다르게 사용한다.

표기
Index 색인 데이터
Indexing 색인하는 과정
Indices 매핑 정보를 저장하는 논리적인 데이터 공간
구분 엘라스틱서치 관계형 데이터베이스
대소문자 구분 안함 구분함
스키마 구조화되지 않은 데이터까지 스스로 분석해 자동으로 필드 생성 및 저장 미리 지정해야함.

엘라스틱서치는 기본적으로 HTTP를 통해 JSON 형식의 RESTful API를 이용한다. 또한 엘라스틱서치는 자바로 개발됐지만 여러 가지 프로그램이 언으를 활용할 수도 있다.

엘라스틱서치에서 사용하는 HTTP Method 기능 데이터베이스 질의 문법
GET 데이터 조회(Read) Select
PUT 데이터 생성(Create) Insert
POST 인덱스 업데이터, 데이터 조회 Update, Select
DELETE 데이터 삭제(Delete) Delete
Head 인덱스 정보확인 -

유닉스에서 엘라스틱서치의 REST API를 이용한 curl 명령

curl -X{메소드} http://host:port/{인덱스(Index)}/{타입(Type)}/{문서(Document) id} -d{json 데이터}
API종류 기능
인덱스 관리 API(Indices API) 인덱스 관리
문서 관리 API(Document API) 문서 추가/수정/삭제
검색 API(Search API) 문서 조회
집계 API(Aggregation API) 문서 통계

엘라스틱서치 서버정보 확인

$ curl -XGET http://localhost:9200 

ES와 RDB의 쿼리 비교

//RDBMS
$ select * from user where name like '%가마돈%'

//ES
$ curl -XGET http://localhost:9200/user/_search?q=Name:가마돈

1. 엘라스틱서치 설치와 실행

1-1. 엘라스틱서치 설치

1-2. 엘라스틱서치 실행

$ bin/elasticsearch -d //엘라스틱서치를 백그라운드로 실행

$ bin/elasticsearch -p <파일명> //엘라스틱서치의 프로세스 id를 <파일명>으로 지정된 파일에 저장
  • 로그 기록 장소:

2. 클러스터 운영 관련 정보

마스터 노드(Master Node)
인덱스 생성, 삭제 등 클러스터와 관련된 전반적인 작업 담당. 따라서 네트워크 속도가 빠르고 지연 없는 노드를 마스터 노드로 선정해야 한다. 다수의 노드를 마스터 노드로 설정할 수 있지만 결과적으로 하나의 노드만이 마스터 노드로 선출되어 동작한다.

$ vim elasticsearch.yml
node.master: true
node.data: false
node.ingest: false
search.remote.connect: false

데이터 노드(Data Node)
문서가 실제로 저장되는 노드. 데이터가 실제로 분산 저장되는 물리적 공간인 샤드가 배치되는 노드이기도 하다. 색인 작업은 CPU, 메모리, 스토리지 같은 컴퓨팅 리소스를 많이 소모하기 때문에 리소스 모니터링이 필요함. 데이터 노드는 가능하면 마스터 노드와 분리해서 구성하는 것이 좋다.

$ vim elasticsearch.yml
node.master: false
node.data: true
node.ingest: false
search.remote.connect: false

인제스트노드(Ingest Node)
색인에 앞서 데이터를 전처리하기 위한 노드. 데이터 포맷 변경을 위해 스크립트로 전처리 파이프라인 구성, 실행 가능

$ vim elasticsearch.yml
node.master: false
node.data: false
node.ingest: true
search.remote.connect: false

코디네이팅 노드(Coordinating Node)
데이터 노드, 마스터 노드, 인제스트 노드의 역할을 하지 않고, 들어온 요청을 단순히 라운드로빈 방식으로 분산시켜주는 노드.

$ vim elasticsearch.yml
node.master: false
node.data: false
node.ingest: false
search.remote.connect: false

엘라스틱서치를 분산 환경으로 구성하면 하나의 인덱스가 여러 노드에 분산되어 자장되어 관리된다.

클러스터 정보 확인

status: red, yellow, green

  • green: 클러스터의 모든 샤드가 정상임.
  • yellow: 프라이머리 샤드는 정상적으로 할당 됐으나 일부 레플리카 샤드가 정상적으로 할당되지 않음.
  • red: 일부 프라이머리 샤드가 정상적으로 할당되지 못함.(active_shards_percent_as_number < 50)

클러스터를 재가동할 경우, active_shards_percent_as_number가 처음에 NaN에서 서서히 올라가기 시작한다. 동시에 unassigned_shards는 줄어들기 시작한다.

$ curl http://localhost:9200/_cluster/health?pretty=true
{
  "cluster_name" : "~~~",
  "status" : "green",
  "timed_out" : "false",
  "number_of_nodes" : 6,
  "number_of_data_nodes" : 5,
  "active_primary_shards" : 341,
  "active_shards" : 682,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_milis" : 0,
  "active_shards_percent_as_number" : 100.0
}

2-1. 현재 진행중인 task 확인

참고: task 확인

$ curl http://localhost:9200/_cat/tasks?pretty

혹은 더 자세하게 보고 싶다면 아래와 같이 입력

$ curl http://localhost:9200/_tasks?pretty 

2-2. 현재 ES 노드별 힙(heap) 사용량 확인

참고링크1: 힙 사용량 확인1 참고링크2: 힙 사용량 확인2

$ curl -XGET http://localhost:9200/_cat/nodes?h=heap* 
heap.current heap.percent heap.max 
11.6gb 36 31.8gb
21.8gb 68 31.8gb
19.4gb 61 31.8gb
 6.7gb 21 31.8gb
21.6gb 68 31.8gb
11.9gb 37 31.8gb
$ curl -XGET http://localhost:9200/_cat/nodes?v
ip        heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.2.3.4            62          99  15    2.41    2.29     1.90 mdi       -      node-1
10.2.3.5            50         100  13    3.09    2.26     1.49 mdi       -      node-5
10.2.3.6            46          96  13    1.13    1.13     1.03 mdi       *      node-2
10.2.3.7            94          99  39   17.93    6.19     2.81 i         -      node-4
10.2.3.8            62          98  12    1.68    1.92     1.43 di        -      node-3
10.2.3.9            56          93  12    4.36    2.21     1.44 di        -      node-6 

2-3. 수행중인 task 취소

참고: 수행중인 task 취소

2-4.샤드&레플리카

샤드 & 리플리카편집 색인은 방대한 양의 데이터를 저장할 수 있는데, 이 데이터가 단일 노드의 하드웨어 한도를 초과할 수도 있습니다. 예를 들어 10억 개의 문서로 구성된 하나의 색인에 1TB의 디스크 공간이 필요할 경우, 단일 노드의 디스크에서 수용하지 못하거나 단일 노드에서 검색 요청 처리 시 속도가 너무 느려질 수 있습니다.

Elasticsearch는 이러한 문제를 해결하고자 색인을 이른바 샤드(shard)라는 조각으로 분할하는 기능을 제공합니다. 색인을 생성할 때 원하는 샤드 수를 간단히 정의할 수 있습니다. 각 샤드는 그 자체가 온전한 기능을 가진 독립적인 “색인”이며, 클러스터의 어떤 노드에서도 호스팅할 수 있습니다.

샤딩은 무엇보다도 2가지 이유로 중요합니다.

  • 콘텐츠 볼륨의 수평 분할/확장이 가능해집니다.
  • 작업을 (어쩌면 여러 노드에 위치한) 여러 샤드에 분산 배치하고 병렬화함으로써 성능/처리량을 늘릴 수 있습니다. 샤드가 분산 배치되는 방식 및 그 문서가 다시 검색 요청으로 집계되는 방식의 메커니즘은 모두 Elasticsearch에서 관리하며 사용자에게는 투명하게 이루어집니다.

언제든 오류가 일어날 가능성이 있는 네트워크/클라우드 환경에서는 어떤 이유에서든 샤드/노드가 오프라인 상태가 되거나 사라지게 될 경우에 대비하여 페일오버 메커니즘을 마련하는 것이 매우 유익하고 바람직합니다. 이러한 취지에서 Elasticsearch에서는 색인의 샤드에 대해 하나 이상의 복사본을 생성할 수 있는데, 이를 리플리카 샤드(replica shard), 줄여서 리플리카라고 합니다.

이처럼 리플리카를 만드는 복제는 무엇보다도 2가지 이유로 중요합니다.

샤드/노드 오류가 발생하더라도 고가용성을 제공합니다. 따라서 리플리카 샤드는 그 원본인 기본 샤드와 동일한 노드에 배정되지 않습니다. 모든 리플리카에서 병렬 방식으로 검색을 실행할 수 있으므로 검색 볼륨/처리량을 확장할 수 있습니다. 요약하자면 각 색인은 여러 개의 샤드로 분할할 수 있습니다. 또한 하나의 색인은 복제하지 않거나(리플리카 없음) 1회 이상 복제할 수 있습니다. 복제되면 각 색인은 기본 샤드(복제 원본 샤드)와 리플리카 샤드(기본 샤드의 복사본)를 갖습니다. 샤드 및 리플리카의 수는 색인별로, 색인 생성 시점에 정의할 수 있습니다. 색인이 생성된 다음 언제라도 탄력적으로 리플리카의 수를 변경할 수 있으나, 샤드 수는 사후 변경이 불가합니다.

기본적으로 Elasticsearch의 각 색인은 기본 샤드 5개, 리플리카 1개를 갖습니다. 따라서 클러스터에 최소한 2개의 노드가 있다면 색인은 기본 샤드 5개, 리플리카 샤드 5개(완전한 리플리카 1개)를 가지므로 색인당 총 10개의 샤드가 존재하게 됩니다.

3. 엘라스틱서치 사용 관련 정보

3-1. 멀티 테넌시(Multi Tenancy)

관계형 디비에서 다른 데이터베이스의 데이터를 검색하려면 별도의 컨넥션을 생성해야하는 것과 달리 엘라스틱서치에서는 데이터를 검색할 때 서로 다른 인덱스의 데이터를 바로 하나의 질의로 묶어서 검색하고 여러 검색 결과를 하나의 출력으로 도출 할 수 있다. 이를 멀티 테넌시(Multi Tenancy)라고 한다.

3-3. 엘라스틱서치 템플릿(template) 확인

엘라스틱 서치의 템플릿(template)은 RDBMS의 스키마와 같은 것이라고 생각하면 편하다.

  • 사용법
curl 'http://localhost:9200/{인덱스명}/_mapping?pretty'
  • 사용 예(abcde라는 인덱스의 템플릿을 싶을때)
curl 'http://localhost:9200/abcde/_mapping?pretty'
  • abcd 라는 인덱스 확인
curl localhost:9200/abcd/
  • abcd 라는 인덱스 삭제
curl -XDELETE http://localhost:9200/abcd
  • 초기에 템플릿 포함해서 abcd 라는 인덱스 생성
  • 쉘 스크립트를 하나 만드는게 좋은듯
curl -XPUT http://localhost:9200/abcd/ -d '
{
  "order": 0,
  "template": "abcd",
  "setting": {},
  "mapping": {
      "_default_": {
          "properties": {
                  
                  실제 필드들~~~~
          
          }
      }
   }
}'

3-4. 메타 필드(Meta Fields)

메타필드 설명
_index 해당 문서가 속한 인덱스의 이름을 담고 있다.
_type 해당 문서가 속한 매핑의 타입 정보를 담고 있다.
_id 문서를 식별하는 유일한 키값. 한 인덱스에서 색인된 문서마다 서로 다른 키값을 가짐. RDB 에서의 PRIMARY KEY라고 보면 될 듯. 이 값은 int, long, 상관없이 무조건 string으로 저장된다.
_uid 특수 목적 식별키. “#” 태그를 이용해 _type과 _id 값을 조합해 사용함. 하지만 내부적으로 사용되기 때문에 조회시 검색되진 않음.
_source 문서의 원본 데이터를 제공함.
_all 색인에 사용된 모든 필드의 정보를 가진 메타 필드.
_routing 특정 문서를 특정 샤드에 저장하기 위해 사용하는 메타필드.

3-5. 작업 순서

수집코드 수정 -> (cerebro)인덱스 템플릿 생성 -> (cerebro)인덱스 생성 -> (es)데이터 수집 -> 키바나(management -> index pattern 추가) -> 키바나에서 데이터 잘 들어오는지 확인

참고자료: 엘라스틱서치 실무 가이드