728x90

Intro

1~2주 전에  "검색엔진에서(특히 ElasticSearch) LSM트리 인덱스가 활용되고 있다."는 특성에 이해가 가지 않아서, LSM트리인덱스 방식에 대해서 정리를 했었다.

[Index]검색엔진에서의 SS테이블/LSM트리인덱스 활용(1)

이전 글은 위의 링크를 참고하면 된다.

 

그러나 결국 해답을 찾지 못했고, 그래서 검색엔진에서도 대표격인  ElasticSearch에 대해서 좀 더 정리해야겠다고 느꼈다. 

 

이번 글은 어떻게 보면 ElasticSearch에 대해 정리한 글이라기 보다는,  ElasticSearch가 어떤 개념인지, 어떤 구조를 지니고 특징을 가졌기에 데이터를 효율적으로 관리(읽고 쓰는 일련의 작업)하기 위한 알고리즘 방식으로 LSM트리 방식을 활용하고 있는지에 대한 의문을 해결하는 것에 집중한 글이다.

 

초반에는 1)ES에 대한 간단한 개념과 가장 핵심인 역색인 구조에 대해서 정리했다. 

그리고 2)ES의 구조에 대해서 파악하고 이 구조를 중심으로 LSM트리알고리즘에 ES의 색인에서 어떻게 활용되고 있는지를 정리했다.

 

결론적으로는 ES에서 데이터를 저장하는 자료 구조가 segment인데, 이 segment에 데이터가 저장되고 삭제되고 관리되는 방식이 LSM트리알고리즘을 활용한 것이었다. 더 자세한 결론은 아래의 글들을 정리하고 한 번더 언급할 예정이다. 

 

ElasticSearch에 대한 좀 더 명확한 글을 읽고자 하시는 분은 이번 글에서 원하는 내용을 얻질 못할 가능성이 크다.

 

ElasticSearch에 대한 간단한 개념 정리

ElasticSearch(이하부터는 ES로 명명)는 텍스트, 숫자, 정형 및 비정형 데이터 등 모든 유형의 데이터를 위한 무료 검색 및 분석 엔진이다. 

공식 사이트에서는 ES가 "분산"과 "개방형"이 특징이며, 간단한 REST API, 분산형, 속도, 확장성으로 유명하다고 정리하고 있다.

 

즉 ES 또한 하나의 데이터베이스로써 모든 유형의 많은 데이터를 저장하고(이에 따라 분산,확장성의 특징이 중요), 이를 필요에 따라 빠르게 검색하여 결과를 도출하는 도구라고 볼 수 있다. 즉 저장한 데이터를 빠르게 검색하는 것 또한 ES의 중요한 역할 중 하나이므로,  ES는 수많은 종류의 컨텐츠를 색인화하여 보관하는 것이 중요하다. 

 

ES는 NoSQL의 일종으로, 분산처리를 통해 실시간으로 빠른 검색이 가능하며, 특히 대량의 비정형 데이터 검색이 가능한 것이 주요한 특징이다.

 

ElasticSearch의 작동방식과 역색인(inverted index)

로그, 웹 애플리케이션 등 다양한 소스로부터 원시데이터가 ES로 흘러들어간다. 즉 다양한 데이터가 수집이 되면, ES에서 색인하여 저장하고, 사용자는 이 데이터에 대해 복잡한 쿼리를 실행하고 집계를 사용해서 데이터를 검색할 수 있게 되는 것이다.

 

ES에서의 핵심은 다양하고 많은 데이터의 색인화이며, 이 색인화는 역색인(inverted index)구조로 이루어진다.

 

역색인 구조란?

일반적으로 색인의 목적은 문서의 위치에 대한 인덱스를 만들어서 빠르게 그 문서에 접근하고자 하는 것이다.

역색인은 반대로 문서내의 주어진 데이터와 유사한 데이터들의 맵핑 정보를 색인해놓는 것이다.

즉 위치를 저장하여 알려주는 색인과 달리 특정 텍스트 키(term)를 담은 문서들을 매핑하여 알려주는 것이다.

 

ElasticSearch의 구조

그렇다면 ES는 어떤 구조로 이루어져 있으며, 이에 따라 데이터가 어떤 논리적/물리적 흐름으로 처리되어 저장되고 검색되는 걸까?

Index

ES의 index는  RDBMS의 database + table의 역할을 한다고 생각하면 된다. ES를 분산환경으로 구성했을 경우 index는 여러 노드에 분산 저장/관리된다. 

Shard

index내부에는 색인된 데이터들이 존재하는데 이 데이터들은 물리적인 공간 즉 shard로 나뉘어서 존재한다. index를 여러 샤드로 나누어 저장하기 때문에 컨텐츠 볼륨의 수평 분할/확장이 가능하고, 작업 또한 여러 샤드에서 수행하기 때문에(병렬화) 성능을 늘릴 수 있는 것이다. 위의 그림에서 알 수 있듯이 ES의 Shard내에는 루씬의 index가 있으며 이는 거의 1:1 대응된다.

 

Segment

세그먼트란 ES에서 문서의 빠른 검색을 위해 설계된 자료구조이다. 위의 그림에서 알 수 있듯이 각 샤드는 다수의 세그먼트로 구성되어 있다. ES에서 데이터(Document : ES에서의 데이터 저장단위, Json오브젝트 하나이다)를 저장하면, ES는 새로 수집된 데이터를 메모리(RAM)에 모아두고, 세그먼트를 생성한다. 새로운 세그먼트를 디스크에 기록한다.

 

이러한 과정을 통해 데이터를 찾고자 할때 검색을 하게되는 세그먼트가 만들어지게 된다. 이 세그먼트 내부에 데이터들이 역색인 방식으로 저장되어 있는 것이다. 

 

실제로 데이터를 샤드에서 검색할 때, 내부적으로는 먼저 각각의 세그먼트들을 검색하여 결과를 조합한 후 최종 결과를 샤드의 결과로 리턴하게 된다.  

 

즉 ES에서 실제로 색인화한 데이터를 저장하는 segment를 관리하는 방식이 LSM트리 방식인 것이다. 

1) 데이터를 수집, RAM과 Disk에 저장하여 세그먼트를 생성하고

2) 1)의 과정을 반복하면서 세그먼트들이 증가하고 성능적, 용량적으로 임계치에 다다르면 

3) 세그먼트 병합을 진행하게 된다.

 

ES의 Segment 방식의 특징

ES는 어떻게 보면 하나의 큰 자료에서 한 번에 찾고자 하는 데이터를 찾는 것이 아닌, 여러개의 자료 즉 세그먼트들에서 데이터를 검색하여 응답하는 것이다. 이렇게 여러개의 Segment를 두고 데이터를 탐색하는 이유는 무엇일까? 어떤 특징을 가지고 있는 것일까?

세그먼트 단위 검색(Per-Segment Search)

검색요청을 받았을 때, 다수의 작은 세그먼트 조각들에서 각각의 결과를 만들어 내고 그 결과들을 통합하여 하나의 결과로 응답하는 방식이 세그먼트 단위 검색이다. 이렇게 다수의 세그먼트로 구성되어 있을 경우, 검색 요청이 분산처리되어 훨씬 효율적인 검색이 가능해지게 된다.

 

그러나 세그먼트의 개수가 너무 많아지면 읽기 성능이 저하될 수 있으므로 백그라운드에서 주기적으로 세그먼트 파일들을 물리적으로 하나의 파일로 병합해주어야 하는데 이 작업이 시스템 자원을 많이 쓰는 부담스러운 작업이다. 따라서 시스템 자원이 여유로울때 시스템에 영향을 주지 않는 선에서 진행해야 한다. 

세그먼트의 불변성

 ES에서 여러 세그먼트를 생성하고 이를 통해 데이터를 관리하는 과정에서 이미 만들어진 세그먼트를 병합하기 이전에는 수정하지 않는다는 불변성이 적용된다.

 

세그먼트의 불변성이란 말그대로 한번 만들어진 세그먼트는 수정되지 않는다는 것이다.

이에 따라 ES에서 데이터가 수집되었는데, 그게 기존에 이미 수집되어 세그먼트로 만들어진 데이터가 수정된 버전이라면,

기존 세그먼트를 수정하는 것이 아니라 새로운 세그먼트를 생성하고, 구 데이터를 담은 기존 세그먼트 내의 구 데이터는 읽지 않음으로 처리하게 된다. 

 

이렇게 불변성이라는 특성을 지니게 된 이유는,  ES에 데이터가 수집될때마다 역색인 구조가 만들어져야 하는데, 매우 빠르게 수집이 되는 상황에서 기존 데이터를 지우고 변경하는 과정이 비효율적이기 때문이다. 실제로 캐시에 데이터를 저장한 경우, 불변하지 않는다면 매번 시스템 캐시를 삭제하고 다시 생성하는 과정을 거쳐야 하기 때문이다. 

따라서 우선은 계속해서 추가 세그먼트를 생성하고, 데이터 탐색 시에 여러 세그먼트를 읽어서 검색 결과들을 통합하고 최종 응답을 출력하는 과정에서 최신 데이터를 응답하는 방식을 택하게 되었다고 볼 수 있다.

 

물론 삭제되어야 하는 구 데이터들과 이를 담은 세그먼트들이 삭제되지 않고 계속해서 남게된다면 성능, 용량상 임계치에 이르게 될테고 이에 따라 세그먼트 병합 시에, 삭제되어야 하는 세그먼트들을 실제로 삭제하여 디스크 용량을 줄이게 된다. 

 

결론

ElasticSearch는 검색엔진인만큼 읽기 연산의 비중이 크며, 그만큼 데이터가 수집되고 변경되는 쓰기 작업 또한 내부적으로 빈번하게 발생한다. 이에 따라서 read workload에만 집중한 것이 아닌, 높은 write workload를 처리할 수 있는 LSM방식을 활용한 것이라는 생각이 들었다. 

 

또한 다수의 세그먼트를 두고 탐색함으로써 읽기 연산에 대한 분산처리도 가능하며 세그먼트의 불변성 또한 적용할 수 있기 때문이다.

 

ElastiSearch가 검색엔진인만큼 빠르게 데이터를 색인화하고 이를 검색하는 과정이 매우 중요한듯하다.

그래서 내부적으로 데이터들을 저장하고 관리하는 segment라는 자료구조가 핵심인 듯했고 언제 한 번  ElasticSearch에 대해 다시 공부를 하게 된다면, Segment에 대해서 더 깊이 정리해봐야겠단 생각이 들었다.

 

 

Reference

 

728x90

+ Recent posts