Elasticsearch
- Apache Lucene 기반의 Java 오픈 소스 분산 검색 엔진이다.
- 방대한 양의 데이터를 신속하게, 그리고 NRT(거의 실시간)로 저장, 검색, 분석할 수 있다.
- Lucene을 활용한 다른 대표적인 검색 엔진으로는 Solr가 있다.
- 기존의 DB에 저장된 데이터에 대해 검색 및 분석 만을 위해 단독으로 사용되기도 하며,
ELK(Elasticsearch/Logstash/Kibana) 스택으로써 사용되기도 한다.
- Logstash: 다양한 소스(DB, csv 파일 등)의 로그 또는 트랜잭션 데이터를
수집, 집계, 파싱하여 Elasticsearch로 전달한다.
- Elasticsearch: Logstash로부터 받은 데이터를 검색 및 집계하여 필요한 정보를 획득한다.
- Kibana: Elasticsearch의 빠른 검색을 통해 데이터를 시각화 및 모니터링한다.
- ELK는 간단히, 로그 및 데이터 분석할 때 사용하곤 하는 종합 도구이다.
로드 밸런싱이 되어있는 WAS의 흩어진 로그를 한 곳에 모으고
원하는 데이터를 빠르게 검색한 뒤 시각화하여 모니터링하기 위해 사용할 수도 있다.
- 데이터 자체를 저장하는 것은 아니기 때문에 DB를 대체하는 것은 아니다.
검색 엔진에 가깝다.
vs RDB
- RDB에 대해 다음과 같이 대응할 수 있다.
(왼쪽이 Elasticsearch, 오른쪽이 RDB이며 그 개념이 완벽하게 대응한다는 말은 아니다.)
- index : database
- type : table
- field : column
- document : row
- analyze : index
- id : primary key
- mapping : schema
- shard : physical partition
- route : logical partition
- parent/child, nested : relational
- query DSL : SQL
terms
- 클러스터(cluster)
- Elasticsearch에서 가장 큰 시스템 단위를 의미한다.
최소 하나 이상의 노드로 이루어진 노드 집합체이다.
- 서로 다른 클러스터는 데이터의 접근 및 교환을 할 수 없는 독립적 시스템이다.
- 여러 대의 서버가 하나의 클러스터를 구성할 수도 있고,
한 서버에 여러 개의 클러스터가 존재할 수도 있다.
- 노드(node)
- Elasticsearch를 구성하는 하나의 단위 프로세스를 의미한다.
- 클러스터에 포함된 단일 서버로써,
데이터를 저장하거나 클러스터의 indexing 및 검색 기능에 참여한다.
- 역할에 따라 master-eligible, data, ingest 등으로 구분한다.
- master-eligible: 클러스터를 제어하는 마스터로 선택할 수 있는 노드이다.
master node는 index 생성 및 삭제, 클러스터 노드들의 추적 및 관리,
데이터 입력 시 할당할 샤드 선택을 담당한다.
- data: 데이터 CRUD와 관계되는 노드이다.
document가 저장되는 노드임에 따라 shard가 배치되는 노드이다.
CRUD, 색인, 검색, 통계 등 많은 작업을 하여 CPU, 메모리 등의 리소스를 많이 소모한다.
따라서 모니터링이 필요하며, master node와는 분리할 필요가 있다.
- ingest: document를 변환하는 등 사전 처리 파이프라인을 실행하는 역할을 한다.
- coordination only: 사용자의 요청을 받아 round robin 방식으로 분산을 하는 노드이다.
클러스터에 관련된 것은 master node로, 데이터와 관련된 것은 data node로 넘겨준다.
대규모 클러스터에서 이점이 있으며, 로드 밸런싱을 한다고 생각할 수 있다.
- 샤드(shard), 복제(replica)
- Elasticsearch에 국한되는 개념이 아닌, 분산형 DB 시스템에 존재하는 개념이다.
- shard: 데이터를 분산해서 저장한다는 것을 의미한다.
즉, scale out을 위해 하나의 index에 대해 여러 shard로 쪼개어 저장하게 된다.
- index 내부에는 indexing된 데이터들이 존재하는데,
이 데이터들이 하나로 뭉쳐 있지 않고 여러 shard에 나뉘어 저장되는 것이다.
- shard는 기본적으로는 1개이며,
검색 성능 향상을 위해 클러스터 shard 개수를 조정할 수 있다.
- 하나의 shard는 node 내부에서 하나의 lucene 검색 thread이다.
- replica: node를 손실했을 경우를 대비하여 데이터의 신뢰성을 확보하기 위해
primary shard를 복제한다는 것을 의미한다.
- prmiary shard가 원본이며, UPDATE 요청에 대해 가장 우선한다.
- replica shard는 primary shard와 서로 다른 노드에 존재해야 그 의미가 있다.
- 세그먼트(segment)
- Elasticsearch에서 document의 빠른 검색을 위해 설계된 자료 구조로,
shard에 대한 데이터를 가지고 있는 파일이다.
- 각 shard는 다수의 segment로 구성되어 있으므로,
검색 요청을 분산 처리하여 효율적인 검색이 가능하다.
- shard에서 검색 시, 먼저 각 segment를 검색하여 결과를 조합한 후
최종 결과를 해당 shard의 결과로 반환하게 된다.
- segment 내부에 색인된 데이터는 역색인 구조로 저장되어, 검색 속도가 매우 빠르다.
- segment 생성과 관련해서는 in-memory 버퍼 방식을 사용한다.
- 대략적으로 cluster > node > index > (shard > segment >) document 로 볼 수 있다.
mechanism
- 클러스터링 과정
- 여러 개의 노드가 묶여 하나의 클러스터로써 실행된다.
- 이에 따라, 처음 노드에 쌓여 있던 데이터들이 다른 노드로 재배치된다.
즉, shard들은 여러 노드에 분배되어 저장된다. (relocation)
- 이후 replica shard가 생성되어 primary shard와는 서로 다른 노드에 위치한다.
- 대규모의 데이터 검색을 가능하게 하기 위해 필요한 과정이 클러스터링이다.
- 검색 과정
- query phase
- 처음 쿼리 수행 명령(검색 요청)을 받은 노드는
검색 대상이 되는 모든 shard들에게 쿼리를 전달한다.
- 각 shard별로 검색을 수행한 결과 큐를 노드로 리턴한다.
리턴된 결과는 lucene document id와 랭킹 점수를 가지고 있다.
- fetch phase
- 노드는 리턴된 결과를 랭킹 점수 기반으로 정렬한 뒤,
유효한 shard들에게 최종 결과들을 다시 요청한다.
- 결과적으로 전체 내용에 대한 정보가 리턴되어 클라이언트로 전달된다.
- 역색인(inverted indexing) 과정
- 기준이 되는 텍스트를 파싱해서 각 형태소 별로 추출하여
document id에 따라 검색어 사전을 만든다. (tokenizing)
- 대소문자 및 유사어 처리 과정 등의 가공을 거친다. (filtering)
- 최종적으로 검색어가 key, document id가 value인 inverted index 구조가 만들어진다.
- tokenizing과 filtering을 통틀어 text analysis라 한다.
- 검색 과정에서도 검색어에 대해서 filtering 처리를 한다.
- 책으로 비유하자면 맨 앞 페이지의 목차는 index,
맨 뒷 페이지에 키워드마다 찾아볼 수 있는 목차는 inverted index이다.
- 이러한 특징으로 인해 전문 검색(full text search)에서 RDBMS보다 성능이 월등하다.
features
- scale out: sharding을 통해 규모가 수평적으로 늘어날 수 있다.
- 고가용성: replica를 통해 데이터의 안정성을 보장한다.
- shema free: JSON document를 통해 데이터 검색을 수행하므로,
RDB와 같은 schema는 따로 없다.
- restful: 데이터 CRUD는 보통 REST API(HTTP 요청)를 통해 수행하며, 다음과 같이 대응된다.
(왼쪽이 데이터 CRUD, 오른쪽이 이에 대응되는 Elasticsearch restful이다)
- SELECT : GET
- INSERT : PUT
- UPDATE : POST
- DELETE : DELETE
- field 충돌의 이유로 인해, 7.0 버전 이상부터는 한 index에서는 하나의 type만 가질 수 있다.
- Elasticsearch는 in-memory 버퍼를 사용하므로, 쓰기와 동시에 읽기를 할 경우
세그먼트가 생성되기 전까지는 해당 데이터를 검색할 수 없다.
따라서 실시간이 아니라, NRT(거의 실시간)이다.
- (참고로 NoSQL은 실시간 처리가 가능하다.)
- 분산형 시스템임에 따라, 트랜잭션 및 롤백에 필요한 리소스가 많이 든다는 점에서
이에 따른 cost가 크기 때문에 지원하지 않는다.
- UPDATE는 삭제했다가 다시 만드는 형태로, 진정한 UPDATE 방식은 아니다.