NoSQL 데이터베이스로서의 Elasticsearch

업데이트: 이 글은 예전에 Found라는 이름으로 제공되었던 호스트형 Elasticsearch 제품에 대한 것입니다. Found는 이제 Elastic Cloud로 알려져 있습니다. 호스트형 Elasticsearch 14일 무료 체험판은 Elastic Cloud에서 사용하실 수 있습니다.

Elasticsearch를 "NoSQL" 데이터베이스로 사용할 수 있을까요? NoSQL은 컨텍스트에 따라 여러 가지 다른 것들을 의미합니다. 흥미롭게도 NoSQL은 사실상 SQL에 관한 것이 아닙니다. 우리는 "아마도!"라는 입장에서 시작하여 Elasticsearch의 다양한 속성과 Elasticsearch이 가장 유연하고 확장 가능하며 성능이 뛰어난 검색 및 분석 엔진 중 하나가 되기 위해 희생해온 속성을 살펴볼 것입니다.

NoSQL 데이터베이스란 도대체 무엇인가?

NoSQL 데이터베이스는 NoSQL을 "차세대 데이터베이스는 주로 비관계형, 분산형, 오픈 소스 및 수평적 확장 가능성 등과 같은 몇 가지 사항을 다루고 있다"고 정의합니다. 다시 말해서, 아주 정확한 정의가 아닙니다.

특별히 SQL에 관한 것도 아닙니다. 예를 들어, Hive의 쿼리 언어는 분명히 SQL에서 영감을 받았습니다. 관계 대신 스트림에서 작동하는 Esper의 쿼리 언어도 마찬가지입니다. 또한, 예전에 이름이 "Postgres"였고 쿼리 언어가 "Quel"이었던 PostgreSQL을 알고 계신가요? 무엇보다도 ORDBMS이지만, 이제는 스키마리스 문서 저장소로 사용할 수 있도록 다양한 기능을 갖추고 있습니다.

NoSQL은 또한 ACID에 관한 것도 아닙니다. Hyperdex는 ACID 트랜잭션을 제공하는 것을 목표로 하는 NoSQL 데이터베이스의 한 예입니다. 확실히 SQL 데이터베이스인 MySQL에서는 ACID가 실제로 무엇을 의미하는지에 대해 그간 모호하게 해석한 바 있습니다.

관계형? 대부분의 NoSQL 데이터베이스는 기존의 관계형 데이터베이스와 같은 의미로 조인하는 것을 지원하지 않으며 이 부분은 사용자의 몫으로 남겨두지만, 이를 지원하는 데이터베이스도 있습니다. 몇 가지 예를 들면, RethinkDB, HivePig 등이 있습니다. 그래프 데이터베이스인 Neo4j는 확실히 관계형을 다루며, 그래프로 관계(즉, 엣지)를 탐색하는 데 탁월합니다. Elasticsearch에는 상위/하위 관계와 조인하는 "쿼리 시"와 중첩된 유형과 조인하는 "색인 시"라는 개념이 있습니다.

분산형? 일부 SQL 데이터베이스는 분산형이고 일부 프로젝트는 NoSQLite와 같은 것을 목표로 하지만, 보다 새로운 차세대 데이터베이스는 어떤 식으로든 분산형인 경향이 있습니다.

요약하자면, NoSQL을 정확하게 정의하거나 간단히 Elasticsearch가 "문서 저장소" 유형의 NoSQL 데이터베이스라고 말하는 것은 의미가 없습니다. 이 글을 쓰고 있는 현재, nosql-database.org에는 20개가 넘는 NoSQL의 목록이 있습니다.

다음 섹션에서는, 몇 가지 중요한 속성을 살펴보고 Elasticsearch가 이러한 속성을 구현하는 방법과 구현하지 않는 방법을 살펴보겠습니다.

트랜잭션 없음

Elasticsearch가 구축된 기반인 Lucene에는 트랜잭션 개념이 있습니다. 반면 Elasticsearch에는 일반적인 의미의 트랜잭션이 없습니다. 제출된 문서를 롤백할 방법이 없으므로 문서 그룹을 제출할 수 없으며 문서 그룹을 모두 색인하거나 아무 것도 색인하지 않거나 둘 중 하나입니다. 그러나 고가의 Lucene 커밋을 수행할 필요 없이 운영의 지속성을 보장하기 위한 로그 선행 기입(write-ahead-log)이 있습니다. 또한 반환하기 전에 작업을 승인해야 하는 복제본 수와 관련하여 색인 작업의 일관성 수준을 지정할 수도 있습니다. 이것은 쿼럼, 즉, \(\lfloor\frac{n}{2}\rfloor + 1\)로 기본 설정됩니다.

기본적으로 초당 한 번씩인 인덱스를 새로 고칠 때 변경 사항의 가시성이 제어되며, 샤드 기반으로 이루어집니다.

낙관적 동시성 제어(Optimistic Concurrency Control)는 제출된 문서의 버전을 지정하여 수행됩니다.

Elasticsearch는 속도를 위해 구축됩니다. 분산형 트랜잭션을 수행하는 데는 많은 작업이 필요합니다. 이를 제공하지 않으면 많은 것들이 더 쉬워집니다. 우리가 읽은 내용이 다소 진부할 수 있고 모든 사람이 동일한 타임라인을 볼 수 있다는 것을 인정함으로써 Elasticsearch는 캐시에서 많은 것을 제공할 수 있습니다. 이는 우리가 좋아하는 놀라운 성능을 위해 가장 중요합니다.

유연한 스키마

Elasticsearch에서는 스키마를 미리 지정할 필요가 없습니다. JSON 문서를 넣으면, 어느 정도 교육에 기반한 추측을 통해 그 유형을 추론하게 됩니다. 숫자, 부울, 타임스탬프와 같은 것들을 잘 처리합니다. 스트링의 경우, 일반적으로 시작하기 좋은 "표준" 분석기를 사용하게 됩니다.

스키마를 지정할 필요가 없다는 점에서 거의 틀림없이 "스키마로부터 자유롭지만", 우리는 그 대신 "유연한 스키마"라고 생각하고 싶습니다. 뛰어난 검색 및/또는 분석 기능을 개발하려면, 정말로 스키마를 조정해야 합니다. Elasticsearch에는 동적 템플릿, 다중 필드 개체 등과 같은 광범위한 강력한 도구 세트가 있습니다. 이에 대한 자세한 내용은 매핑에 대한 글을 참조하세요.

관계 및 제약 조건

Elasticsearch는 문서 지향 데이터베이스입니다. 검색할 전체 오브젝트 그래프가 색인되어야 하므로, 문서를 색인하기 전에 문서를 비정규화해야 합니다. 비정규화를 통해 검색 성능이 향상되고(쿼리 조인이 필요하지 않기 때문에), 더 많은 공간이 사용되지만(여러 번 저장해야 하므로), (모든 변경 사항이 모든 인스턴스에 적용되어야 하므로) 일관성 있는 최신 상태를 유지하는 것이 더욱 어려워집니다. 그러나 한 번만 읽고 쓰는 워크로드에는 매우 적합합니다.

예를 들어, 고객, 주문 및 제품을 포함하는 데이터베이스를 설정했으며 제품 및 사용자의 이름이 지정된 주문을 검색하려고 한다고 해봅시다. 이 문제는 사용자와 제품에 대한 모든 필요한 정보로 주문을 색인하여 해결할 수 있습니다. 그러면 검색이 쉽지만, 제품 이름을 변경하고 싶을 때는 어떻게 될까요? 적절한 정규화가 적용된 관계형 설계에서는 제품을 업데이트하기만 하면 됩니다. 이러한 측면에서는 아주 잘 작동합니다. 비정규화된 문서 데이터베이스를 사용하면, 제품에 대한 모든 주문을 업데이트해야 합니다.

다시 말해, Elasticsearch와 같은 문서 지향 데이터베이스를 사용하면, 우리는 검색에 최적화된 매핑을 설계하고 문서를 저장합니다.

소개할 때 언급했듯이, Elasticsearch에는 상위/하위 관계와 조인하는 "쿼리 시"와 중첩된 유형과 조인하는 "색인 시"라는 개념이 있습니다. 이에 대해서는 앞으로 게시해 드릴 글에서 더 자세히 다루겠습니다. 그 때까지는, Martijn van Groningen의 프레젠테이션 "Elasticsearch를 통한 문서 관계"를 살펴보시기 바랍니다.

또한 대부분의 관계형 데이터베이스에서는 일관성이 있는 것과 일관성이 없는 것을 정의하기 위해 제약 조건을 지정할 수 있습니다. 예를 들어, 참조 무결성 및 고유성이 적용될 수 있습니다. 계정 이동의 합계가 양수 등이어야 할 수 있습니다. 문서 지향 데이터베이스는 이 작업을 수행하지 않는 경향이 있으며, Elasticsearch도 마찬가지입니다.

강건성

데이터베이스는 특히 권위 있는 기록 시스템인 경우 강건해야 합니다. 이상적으로는, 값비싼 쿼리를 취소할 수 있어야 하며, 여러분이 요청하지 않는 한 데이터베이스가 작동을 중지하지 않도록 해야 합니다.

안타깝게도 Elasticsearch(및 그 구성 요소)는 현재 OutOfMemory 오류를 잘 처리하지 못합니다. 프로덕션의 Elasticsearch, 메모리 부족으로 인한 작동 중단에서 이 문제를 더 자세히 다룹니다. Elasticsearch에 충분한 메모리를 제공하고 프로덕션 클러스터에서 알 수 없는 메모리 요건이 있는 검색을 실행하기 전에 주의하는 것이 대단히 중요합니다.

Elasticsearch가 성숙해짐에 따라 이 기능이 개선될 가능성이 높지만, Elasticsearch는 메모리가 풍부하다는 가정 하에 속도를 위해 구축된다는 점을 기억하는 것이 중요합니다.

분산형

추가로, 프로덕션의 Elasticsearch, 네트워킹도 참조하세요.

Elasticsearch를 만들기 전에, Shay Banon은 Compass를 연구했습니다. 이를 분산형 검색 엔진으로 전환하는 것이 어렵다는 것을 깨달은 그는 처음부터 새로 시작하여 Elasticsearch를 만들었습니다1. Elasticsearch는 범용 하드웨어의 방대한 양의 데이터를 처리할 수 있도록 분산되고 쉽게 확장할 수 있도록 설계되었습니다.

Elasticsearch는 분산형 시스템에서 사용하고 시작하는 것이 놀라울 정도로 쉽지만, 분산형 시스템은 복잡합니다. 프로덕션의 Elasticsearch, 네트워킹에서 이 문제를 조금 더 다루므로, 여기서는 간단한 요약만 소개하겠습니다.

분산형 시스템의 본질은 잘못될 수 있는 수많은 것들을 의미합니다. 이와 같이, 서로 다른 데이터베이스 시스템은 서로 다른 강점에 초점을 맞춥니다. 일부(또는 대부분)의 경우에 오류가 있음에도 불구하고 어떤 데이터베이스 시스템은 강력한 보장을 위해 노력하고, 어떤 데이터베이스 시스템은 항상 사용 가능하도록 노력합니다. 게다가, 문제가 발생할 때 데이터베이스 시스템이 어떠해야 한다고 주장하는 내용은 Kyle Kingsbury네트워크 파티션의 위험성에 대한 탁월한 시리즈에서 탐구한 것처럼 실제로 이러한 문제에 대한 대처가 아닌 경우가 태반입니다. 간단히 말해서, 그는 분산형 데이터베이스가 아무 문제가 없을 때는 잘 작동하지만, 대부분의 경우 엄청나게 많은 실패할 수 있는 방법들에 시달리며 어려움을 겪는다는 것을 발견했습니다.

일관성, 가용성 및 파티션 허용성 측면에서, Elasticsearch는 CP 시스템이며 "일관성"에 대한 정의는 상당히 약합니다. 읽기 전용 워크로드가 있는 경우, Elasticsearch를 사용하면 쿼럼이 필요하지 않은 "최소 마스터 노드" 요건을 완화하여 AP 동작을 수행할 수 있습니다. 그러나 일반적으로 클러스터의 노드 대부분을 사용할 수 있어야 합니다. 이 다수가 없는 잘못 구성된 클러스터, 즉 "스플릿 브레인"이 있는 클러스터에 쓰면 복구할 수 없는 데이터 손실이 발생할 수 있습니다. 이는 Elasticsearch에만 국한된 것이 아닙니다.

확장 측면에서, 인덱스는 하나 이상의 샤드로 나뉩니다. 이는 인덱스를 만들 때 지정되며 변경할 수 없습니다. 따라서 인덱스는 예상되는 성장에 비례하여 샤드로 분할되어야 합니다. Elasticsearch 클러스터에 노드가 더 많이 추가되면, 샤드를 재할당하고 이동하는 작업이 잘 진행됩니다. 따라서 Elasticsearch는 확장이 매우 쉽습니다.

보안

추가로, 프로덕션의 Elasticsearch, 보안도 참조하세요.

Elasticsearch에는 인증 또는 승인을 위한 기능이 없습니다. Elasticsearch 클러스터에 연결할 수 있는 사람이면 누구나, 특히 Elasticsearch의 강력한 스크립팅 기능이 활성화된 경우, "슈퍼 사용자" 권한을 갖는 것으로 간주해야 합니다.

요약

설명된 제한 사항으로 인해 큰 문제가 발생하지 않으면 Elasticsearch를 기본 저장소로 사용할 수 있습니다. 한 가지 좋은 예는 Logstash를 사용하는 경우입니다. Logstash는 로그를 관리하고 Elasticsearch로 데이터를 수집할 수 있는 훌륭한 도구이며, 만일의 경우를 대비하여 다른 곳에 보관할 수도 있습니다. Logs는 한 번 쓰고 여러 번 읽기가 가능합니다(WORM). 업데이트도 필요 없고, 트랜잭션도 필요 없으며, 무결성 제약 조건도 없습니다.

풀텍스트 검색 ACID 트랜잭션이 제공되는 Postgres와 같은 시스템은 어떨까요? (다른 예로는 MySQL, MongoDB, Riak 등의 풀텍스트 기능이 있습니다.) Postgres로 기본 검색을 구현할 수 있지만, 가능한 성능과 기능 양쪽 모두에서 큰 차이가 있습니다. 트랜잭션 섹션에서 언급한 것처럼, Elasticsearch는 다중 버전 동시성 제어 및 기타 복잡한 작업에 대한 걱정 없이 "치트" 및 많은 캐싱을 수행할 수 있습니다. 검색은 텍스트에서 키워드를 찾는 것 이상의 기능을 제공합니다. 도메인별 지식을 적용하여 적절한 정확도 모델을 구현하고, 전체 결과 공간에 대한 개요를 제공하며, 맞춤법 검사 및 자동 완성과 같은 작업을 수행하는 것입니다. 그것도 언제나 빠르게 말입니다.

Elasticsearch는 일반적으로 다른 데이터베이스에 추가하여 사용됩니다. 제약 조건, 정확성 및 강건성에 더 중점을 두고 쉽게 트랜잭션으로 업데이트할 수 있는 데이터베이스 시스템에는 마스터 레코드가 있으며 이 레코드는 비동기식으로 Elasticsearch에 푸시됩니다. (또는 Elasticsearch의 "리버" 중 하나를 사용하는 경우, 풀(Pull)됨) 동기화 상태를 유지하는 것은 앞으로 게시할 글에서 자세히 다루겠습니다. 여기 Found에서는 일반적으로 정확한 데이터를 위해 PostgreSQL과 ZooKeeper를 사용하며, 우리는 멋진 검색을 위해 이를 Elasticsearch로 피드합니다.

다른 모든 것과 마찬가지로, 한 번에 완벽한 해결책은 없으며, 모든 것에 들어맞는 단 하나의 데이터베이스도 없습니다. 아마도 언제나 그럴 가능성이 높으니, 여러분의 저장소의 강점과 약점을 알아두시기 바랍니다!

참고 자료

Banon, Shay: compass와 elasticSearch의 미래https://thedudeabides.com/articles/the_future_of_compass


  1. Shay Banon, compass와 elasticSearch의 미래https://thedudeabides.com/articles/the_future_of_compass.