paint-brush
Elasticsearch 업데이트, 삽입, 삭제: 작동 방식과 제한 사항 이해~에 의해@rocksetcloud
4,853 판독값
4,853 판독값

Elasticsearch 업데이트, 삽입, 삭제: 작동 방식과 제한 사항 이해

~에 의해 Rockset12m2024/05/20
Read on Terminal Reader

너무 오래; 읽다

Elasticsearch와 같은 시스템의 경우 엔지니어는 스트리밍 데이터를 효율적으로 수집하기 위해 기본 아키텍처에 대한 심층적인 지식이 필요합니다.
featured image - Elasticsearch 업데이트, 삽입, 삭제: 작동 방식과 제한 사항 이해
Rockset HackerNoon profile picture


소개

실시간 검색 및 분석을 위해 PostgreSQL, MongoDB 또는 DynamoDB와 같은 소스 시스템의 스트리밍 데이터를 다운스트림 시스템으로 관리하는 것은 많은 팀에게 어려운 일입니다. 데이터 흐름에는 업데이트 및 삭제를 포함한 대용량 쓰기가 CPU를 소모하거나 최종 애플리케이션의 성능에 영향을 미치지 않도록 하기 위한 복잡한 ETL 도구와 자체 관리 통합이 포함되는 경우가 많습니다.


Elasticsearch 와 같은 시스템의 경우 엔지니어는 스트리밍 데이터를 효율적으로 수집 하기 위해 기본 아키텍처에 대한 심층적인 지식이 필요합니다. Elasticsearch는 데이터가 자주 변경되지 않아 트랜잭션 데이터를 처리할 때 추가적인 문제를 야기하는 로그 분석을 위해 설계되었습니다.


반면 Rockset은 클라우드 기반 데이터베이스이므로 데이터를 시스템에 가져오는 데 필요한 많은 도구와 오버헤드를 제거합니다. Rockset은 실시간 검색 및 분석을 위해 특별히 제작되었으므로 필드 수준의 변경 가능성을 위해 설계되어 삽입, 업데이트 및 삭제를 처리하는 데 필요한 CPU를 줄입니다.


이 블로그에서는 Elasticsearch와 Rockset이 데이터 수집을 처리하는 방법을 비교 및 대조하고 실시간 분석을 위해 이러한 시스템을 사용하기 위한 실용적인 기술을 제공합니다.

엘라스틱서치

Elasticsearch의 데이터 수집

Elasticsearch에 데이터를 수집하는 방법에는 여러 가지가 있지만, 실시간 검색 및 분석을 위한 세 가지 일반적인 방법을 다룹니다.


  • Logstash JDBC 입력 플러그인을 사용하여 관계형 데이터베이스의 데이터를 Elasticsearch로 수집합니다.

  • Kafka Elasticsearch Service Sink Connector를 사용하여 Kafka에서 Elasticsearch로 데이터 수집

  • REST API 및 클라이언트 라이브러리를 사용하여 애플리케이션에서 Elasticsearch로 직접 데이터를 수집합니다.


Logstash JDBC 입력 플러그인을 사용하여 관계형 데이터베이스의 데이터를 Elasticsearch로 수집합니다. Logstash JDBC 입력 플러그인은 검색 및 분석을 위해 PostgreSQL 또는 MySQL과 같은 관계형 데이터베이스의 데이터를 Elasticsearch로 오프로드하는 데 사용할 수 있습니다.


Logstash는 데이터를 Elasticsearch로 보내기 전에 수집하고 변환하는 이벤트 처리 파이프라인입니다. Logstash는 주기적으로 삽입 및 업데이트를 위해 PostgreSQL 또는 MySQL과 같은 관계형 데이터베이스를 폴링하는 JDBC 입력 플러그인을 제공합니다. 이 서비스를 사용하려면 관계형 데이터베이스는 어떤 변경 사항이 발생했는지 확인하기 위해 Logstash가 읽을 수 있는 타임스탬프 기록을 제공해야 합니다.


이 수집 접근 방식은 삽입 및 업데이트에 적합하지만 삭제에는 추가 고려 사항이 필요합니다. 이는 Logstash가 OLTP 데이터베이스에서 무엇이 삭제되었는지 확인할 수 없기 때문입니다. 사용자는 삭제된 레코드에 플래그가 적용되고 쿼리 시 데이터를 필터링하는 데 사용되는 일시 삭제를 구현하여 이 제한을 피할 수 있습니다. 또는 관계형 데이터베이스를 주기적으로 스캔하여 최신 기록에 액세스하고 Elasticsearch에서 데이터를 다시 색인화할 수 있습니다.


Kafka Elasticsearch Sink Connector를 사용하여 Kafka에서 Elasticsearch로 데이터를 수집합니다 . 실시간 검색 및 분석을 위해 Kafka와 같은 이벤트 스트리밍 플랫폼을 사용하여 소스 시스템의 데이터를 Elasticsearch로 보내는 것도 일반적입니다.


Confluent와 Elastic은 관리형 Confluent Kafka 및 Elastic Elasticsearch 제품을 모두 사용하는 회사에서 사용할 수 있는 Kafka Elasticsearch Service Sink Connector 출시를 위해 파트너십을 맺었습니다. 커넥터를 사용하려면 추가 도구인 Kafka Connect를 설치하고 관리해야 합니다.


커넥터를 사용하면 Kafka의 각 주제를 Elasticsearch의 단일 인덱스 유형에 매핑할 수 있습니다. 동적 유형 지정이 인덱스 유형으로 사용되는 경우 Elasticsearch는 필드 추가, 필드 제거 및 유형 변경과 같은 일부 스키마 변경을 지원합니다.


Kafka를 사용할 때 발생하는 문제 중 하나는 분석기, 토크나이저 또는 인덱싱된 필드를 수정하려고 할 때 Elasticsearch에서 데이터를 다시 인덱싱해야 한다는 것입니다. 매핑이 이미 정의된 후에는 변경할 수 없기 때문입니다. 데이터 재색인을 수행하려면 원래 인덱스와 새 인덱스에 이중 쓰기를 수행하고 원래 인덱스에서 새 인덱스로 데이터를 이동한 다음 원래 커넥터 작업을 중지해야 합니다.


Confluent 또는 Elastic의 관리형 서비스를 사용하지 않는 경우 Logstash용 오픈 소스 Kafka 플러그인을 사용하여 Elasticsearch로 데이터를 보낼 수 있습니다.


REST API 및 클라이언트 라이브러리를 사용하여 애플리케이션에서 Elasticsearch로 직접 데이터를 수집합니다 . Elasticsearch는 Java, Javascript, Ruby, Go, Python 등을 포함한 지원되는 클라이언트 라이브러리를 사용하여 애플리케이션에서 직접 REST API를 통해 데이터를 수집하는 기능을 제공합니다. 클라이언트 라이브러리를 사용할 때의 과제 중 하나는 Elasticsearch가 수집 로드를 처리할 수 없는 경우 대기열 및 역압을 사용하도록 구성해야 한다는 것입니다. 대기열 시스템이 없으면 Elasticsearch로의 데이터 손실이 발생할 가능성이 있습니다.

Elasticsearch의 업데이트, 삽입 및 삭제

Elasticsearch에는 업데이트 및 삭제를 처리하는 데 사용할 수 있는 업데이트 API 가 있습니다. 업데이트 API는 네트워크 이동 횟수와 버전 충돌 가능성을 줄여줍니다. 업데이트 API는 인덱스에서 기존 문서를 검색하고 변경 사항을 처리한 다음 데이터를 다시 인덱싱합니다. 즉, Elasticsearch는 전체 업데이트나 삭제를 제공하지 않습니다. 따라서 CPU를 많이 사용하는 작업인 전체 문서를 다시 색인화해야 합니다.


내부적으로 Elasticsearch 데이터는 Lucene 인덱스에 저장되며 해당 인덱스는 더 작은 세그먼트로 분류됩니다. 각 세그먼트는 변경할 수 없으므로 문서를 변경할 수 없습니다. 업데이트가 이루어지면 이전 문서는 삭제 대상으로 표시되고 새 문서는 병합되어 새 세그먼트를 형성합니다. 업데이트된 문서를 사용하려면 모든 분석기를 실행해야 하며 이로 인해 CPU 사용량도 늘어날 수 있습니다. 데이터가 지속적으로 변경되는 고객은 인덱스 병합이 전체 Elasticsearch 컴퓨팅 비용의 상당 부분을 차지하는 것을 흔히 볼 수 있습니다.


이미지 1: Elasticsearch 데이터는 Lucene 인덱스에 저장되며 해당 인덱스는 더 작은 세그먼트로 분류됩니다.


필요한 리소스의 양을 고려하여 Elastic에서는 Elasticsearch에 대한 업데이트 수를 제한할 것을 권장합니다. Elasticsearch의 참고 고객인 Bol.com 은 전자상거래 플랫폼의 일부로 사이트 검색을 위해 Elasticsearch를 사용했습니다. Bol.com은 콘텐츠, 가격, 가용성 변경을 포함하여 하루에 약 700,000개의 업데이트를 제공했습니다. 그들은 원래 변경 사항이 발생했을 때 동기화 상태를 유지하는 솔루션을 원했습니다. 그러나 업데이트가 Elasticsearch 시스템 성능에 미치는 영향을 고려하여 15~20분 지연을 허용하기로 결정했습니다. 문서를 Elasticsearch로 일괄 처리하면 일관된 쿼리 성능이 보장됩니다.


Elasticsearch의 삭제 및 세그먼트 병합 문제

Elasticsearch에서는 오래된 문서 삭제 및 공간 회수와 관련된 문제가 있을 수 있습니다.


Elasticsearch는 인덱스에 세그먼트 수가 많거나 세그먼트에 삭제 표시된 문서가 많은 경우 백그라운드에서 세그먼트 병합을 완료합니다. 세그먼트 병합은 문서가 기존 세그먼트에서 새로 형성된 세그먼트로 복사되고 나머지 세그먼트가 삭제되는 경우입니다. 불행하게도 Lucene은 병합해야 하는 세그먼트의 크기를 조정하는 데 능숙하지 않아 잠재적으로 성능과 안정성에 영향을 미치는 고르지 않은 세그먼트를 생성할 수 있습니다.


병합 후 Lucene 세그먼트의 크기가 모두 다른 것을 확인할 수 있습니다. 이러한 고르지 않은 세그먼트는 성능과 안정성에 영향을 미칩니다.



Elasticsearch는 모든 문서의 크기가 균일 하다고 가정하고 삭제된 문서 수에 따라 병합 결정을 내리기 때문입니다. 다중 테넌트 애플리케이션에서 흔히 발생하는 것처럼 이기종 문서 크기를 처리할 때 일부 세그먼트는 다른 세그먼트보다 크기가 더 빠르게 증가하여 애플리케이션의 가장 큰 고객에 대한 성능이 저하됩니다. 이러한 경우 유일한 해결 방법은 대량의 데이터를 다시 색인화하는 것입니다.

Elasticsearch의 복제본 문제

Elasticsearch는 복제를 위해 기본 백업 모델을 사용합니다. 기본 복제본은 들어오는 쓰기 작업을 처리한 다음 해당 작업을 해당 복제본에 전달합니다. 각 복제본은 이 작업을 수신하고 데이터를 로컬에서 다시 인덱싱합니다. 이는 모든 복제본이 동일한 문서를 계속해서 다시 인덱싱하기 위해 비용이 많이 드는 컴퓨팅 리소스를 독립적으로 소비한다는 것을 의미합니다. n개의 복제본이 있는 경우 Elastic은 동일한 문서를 인덱싱하기 위해 CPU의 n배를 소비합니다. 이로 인해 업데이트나 삽입이 발생할 때 다시 색인화 해야 하는 데이터의 양이 늘어날 수 있습니다.

Elasticsearch의 대량 API 및 대기열 문제

Elasticsearch에서 업데이트 API를 사용할 수 있지만 일반적으로 대량 API 를 사용하여 빈번한 변경 사항을 일괄 처리하는 것이 좋습니다. 대량 API를 사용할 때 엔지니어링 팀은 시스템 업데이트를 간소화하기 위해 대기열을 생성하고 관리해야 하는 경우가 많습니다.


대기열은 Elasticsearch와 독립적이며 구성 및 관리가 필요합니다. 대기열은 Elasticsearch에 미치는 영향을 제한하기 위해 특정 시간 간격(예: 15분) 내에 시스템에 대한 삽입, 업데이트 및 삭제를 통합합니다. 큐잉 시스템은 애플리케이션 안정성을 보장하기 위해 삽입 속도가 높을 때 스로틀을 적용합니다. 대기열은 업데이트에 유용하지만, 데이터 전체를 다시 색인화해야 하는 많은 데이터 변경 사항이 있는 시기를 판단하는 데에는 적합하지 않습니다. 이는 시스템에 많은 업데이트가 있는 경우 언제든지 발생할 수 있습니다. 대규모로 Elastic을 실행하는 팀에서는 매일 대기열을 관리하고 조정하는 전담 운영 구성원을 두는 것이 일반적입니다.

Elasticsearch에서 재인덱싱

이전 섹션에서 언급했듯이 업데이트가 많거나 인덱스 매핑을 변경해야 하는 경우 데이터 재인덱싱이 발생합니다. 재인덱싱은 오류가 발생하기 쉽고 클러스터를 중단시킬 가능성이 있습니다. 더욱 무서운 점은 재색인이 언제든지 발생할 수 있다는 것입니다.


매핑을 변경하려는 경우 재인덱싱이 발생하는 시간을 더 효과적으로 제어할 수 있습니다. Elasticsearch에는 새 인덱스를 생성하는 reindex API와 새 인덱스가 생성될 때 가동 중지 시간이 없도록 보장하는 Aliases API가 있습니다. 별칭 API를 사용하면 새 인덱스가 생성될 때 쿼리가 별칭 또는 이전 인덱스로 라우팅됩니다. 새 인덱스가 준비되면 별칭 API는 새 인덱스에서 데이터를 읽도록 변환됩니다.


별칭 API를 사용하면 새 인덱스를 최신 데이터와 동기화하는 것이 여전히 까다롭습니다. Elasticsearch는 하나의 인덱스에만 데이터를 쓸 수 있기 때문입니다. 따라서 새 인덱스와 이전 인덱스에 이중으로 쓰도록 데이터 파이프라인 업스트림을 구성해야 합니다.

로켓세트

Rockset의 데이터 수집

Rockset은 내장된 커넥터를 사용하여 데이터를 소스 시스템과 동기화합니다. Rockset의 관리형 커넥터는 각 데이터 소스 유형에 맞게 조정되어 2초 이내에 데이터를 수집하고 쿼리할 수 있습니다. 이렇게 하면 대기 시간이 추가되거나 15분마다 마이크로 배치로만 데이터를 수집할 수 있는 수동 파이프라인이 방지됩니다.


높은 수준에서 Rockset은 OLTP 데이터베이스, 데이터 스트림, 데이터 레이크 및 웨어하우스에 대한 내장 커넥터를 제공합니다. 작동 방식은 다음과 같습니다.


OLTP 데이터베이스에 대한 내장 커넥터 Rockset은 OLTP 데이터베이스의 테이블을 초기 스캔한 다음 CDC 스트림을 사용하여 최신 데이터와 동기화를 유지하며 데이터가 생성된 후 2초 이내에 쿼리에 사용할 수 있게 됩니다. 소스 시스템.


데이터 스트림에 대한 내장 커넥터 Kafka 또는 Kinesis와 같은 데이터 스트림을 통해 Rockset은 Kafka 또는 Kinesis에서 튜닝이 필요하지 않은 풀 기반 통합을 사용하여 새로운 주제를 지속적으로 수집합니다.


데이터 레이크 및 웨어하우스에 대한 내장 커넥터 Rockset은 업데이트를 지속적으로 모니터링하고 S3 버킷과 같은 데이터 레이크에서 새로운 객체를 수집합니다. 일반적으로 팀은 실시간 분석을 위해 데이터 레이크의 데이터와 실시간 스트림을 결합하기를 원합니다.

Rockset의 업데이트, 삽입 및 삭제

Rockset은 여러 시스템에서 병렬로 데이터를 효율적으로 인덱싱하도록 최적화된 분산 아키텍처를 갖추고 있습니다.


Rockset은 문서 분할 데이터베이스 이므로 문서를 분할하여 여러 필드를 다른 컴퓨터로 보내는 대신 전체 문서를 단일 컴퓨터에 기록합니다. 이로 인해 업데이트 및 삭제를 위한 기본 키 _id를 기반으로 삽입할 새 문서를 추가하거나 기존 문서를 찾는 것이 빠릅니다.


Elasticsearch와 유사하게 Rockset은 인덱스를 사용하여 쿼리 시 데이터를 빠르고 효율적으로 검색합니다. 그러나 다른 데이터베이스나 검색 엔진과 달리 Rockset은 열 저장소, 검색 인덱스 및 행 저장소를 결합한 인덱스인 Converged Index 에서 수집 시 데이터를 인덱싱합니다. 수렴형 인덱스는 필드의 모든 값을 일련의 키-값 쌍으로 저장합니다. 아래 예에서는 문서와 해당 문서가 Rockset에 어떻게 저장되어 있는지 확인할 수 있습니다.


Rockset의 Converged Index는 필드의 모든 값을 검색 인덱스, 열 저장소 및 행 저장소에 일련의 키-값 쌍으로 저장합니다.


내부적으로 Rockset은 돌연변이를 사소한 것으로 만드는 고성능 키-값 저장소인 RocksDB를 사용합니다 . RocksDB는 다양한 키에 걸쳐 원자적 쓰기 및 삭제를 지원합니다. 문서의 name 필드에 대한 업데이트가 들어오는 경우 인덱스당 하나씩 정확히 3개의 키를 업데이트해야 합니다. 문서의 다른 필드에 대한 인덱스는 영향을 받지 않습니다. 즉, Rockset은 매번 전체 문서에 대한 인덱스를 업데이트하는 주기를 낭비하는 대신 효율적으로 업데이트를 처리할 수 있습니다.


중첩된 문서와 배열은 Rockset의 최고 수준 데이터 유형이기도 합니다. 즉, 동일한 업데이트 프로세스가 여기에도 적용되므로 Rockset은 JSON 및 Avro와 같은 최신 형식으로 저장된 데이터에 대한 업데이트에 적합합니다.


Rockset 팀은 또한 실시간 분석 워크로드의 일반적인 패턴인 높은 쓰기 및 과도한 읽기를 처리하기 위해 RocksDB에 대한 여러 가지 사용자 정의 확장을 구축했습니다. 이러한 확장 중 하나는 쿼리 계산과 인덱싱 계산을 RocksDB Cloud에 완전히 분리하는 원격 압축 입니다. 이를 통해 Rockset은 읽기를 방해하는 쓰기를 방지할 수 있습니다. 이러한 향상된 기능 덕분에 Rockset은 고객의 요구 사항에 따라 쓰기 작업을 확장할 수 있으며 백그라운드에서 변형이 발생하는 경우에도 쿼리에 사용할 수 있는 새로운 데이터를 제공할 수 있습니다.

Rockset API를 사용한 업데이트, 삽입 및 삭제

Rockset 사용자는 기본 _id 필드를 사용하거나 특정 필드를 기본 키로 지정할 수 있습니다. 이 필드를 사용하면 문서 또는 문서의 일부를 덮어쓸 수 있습니다. Rockset과 Elasticsearch의 차이점은 Rockset이 전체 문서를 다시 색인화할 필요 없이 개별 필드의 값을 업데이트할 수 있다는 것입니다.


Rockset API를 사용하여 컬렉션의 기존 문서를 업데이트하려면 패치 문서 엔드포인트에 요청하면 됩니다. 업데이트하려는 각 기존 문서에 대해 _id 필드와 문서에 적용할 패치 작업 목록을 지정하기만 하면 됩니다.


Rockset API는 또한 애플리케이션 코드에서 컬렉션에 데이터를 직접 삽입할 수 있도록 문서 추가 엔드포인트를 공개합니다. 기존 문서를 삭제하려면 제거하려는 문서의 _id 필드를 지정하고 Rockset API의 문서 삭제 엔드포인트에 요청하면 됩니다.

Rockset에서 복제본 처리

Elasticsearch와 달리 Rockset에서는 단 하나의 복제본만 RocksDB 원격 압축을 사용하여 인덱싱 및 압축을 수행합니다. 이는 특히 내구성을 위해 여러 복제본을 사용하는 경우 인덱싱에 필요한 CPU 양을 줄여줍니다.

Rockset에서 재인덱싱 중

Rockset에서 수집 시 수집 변환을 사용하여 원시 소스 데이터에 적용할 원하는 데이터 변환을 지정할 수 있습니다. 나중에 수집 변환을 변경하려면 데이터를 다시 인덱싱해야 합니다.


즉, Rockset은스키마 없는 수집을 지원하고 모든 데이터 필드의 값을 동적으로 유형화합니다. 데이터나 쿼리의 크기와 모양이 변경되더라도 Rockset은 계속해서 성능을 유지하며 데이터를 다시 인덱싱할 필요가 없습니다.


Rockset은 다시 인덱싱할 필요 없이 수백 테라바이트의 데이터로 확장할 수 있습니다. 이는 Rockset의 샤딩 전략으로 돌아갑니다. 고객이 가상 인스턴스에 할당하는 컴퓨팅이 증가하면 샤드의 하위 집합을 섞어 클러스터 전체에 더 나은 분산을 달성함으로써 더 병렬화되고 더 빠른 인덱싱 및 쿼리 실행이 가능해집니다. 결과적으로 이러한 시나리오에서는 재인덱싱이 발생할 필요가 없습니다.

결론

Elasticsearch는 데이터가 자주 업데이트, 삽입 또는 삭제되지 않는 로그 분석을 위해 설계되었습니다. 시간이 지남에 따라 팀에서는 Elasticsearch 사용을 확대해 왔으며, 종종 Elasticsearch를 보조 데이터 저장소로 사용하고 지속적으로 변화하는 트랜잭션 데이터에 대한 실시간 분석을 위한 인덱싱 엔진을 사용합니다. 이는 특히 실시간 데이터 수집을 최적화하고 상당한 양의 관리 오버헤드를 수반하는 팀의 경우 비용이 많이 드는 노력이 될 수 있습니다.


반면 Rockset은 실시간 분석을 위해 설계되었으며 생성 후 2초 이내에 새로운 데이터를 쿼리할 수 있도록 설계되었습니다. 이 사용 사례를 해결하기 위해 Rockset은 내부 삽입, 업데이트 및 삭제를 지원하고 컴퓨팅 비용을 절감하며 문서 재인덱싱 사용을 제한합니다. Rockset은 또한 커넥터 및 수집의 관리 오버헤드를 인식하고 실시간 커넥터를 클라우드 서비스에 통합하는 플랫폼 접근 방식을 취합니다.


전반적으로 실시간 분석을 위해 Elasticsearch에서 Rockset으로 마이그레이션 한 회사는 컴퓨팅 비용만 44% 절감했습니다. 며칠 만에 Elasticsearch에서 Rockset으로 전환하는 엔지니어링 팀의 물결에 동참하세요. 지금 무료 평가판을 시작해 보세요.