아키텍처

아키텍처 (Architecture)

Druid는 클라우드 친화적이고 운영하기 쉬우도록 설계된 분산 아키텍처를 가지고 있어요. 서비스를 독립적으로 구성하고 확장할 수 있으며, 한 컴포넌트의 장애가 다른 컴포넌트에 즉시 영향을 주지 않는 향상된 내결함성을 갖추고 있어요.

출처: 문서

본문

Druid는 클라우드 친화적이고 운영하기 쉽도록 설계된 분산 아키텍처를 가지고 있어요. 클러스터 운영을 최대한 유연하게 하기 위해 서비스를 독립적으로 구성하고 확장할 수 있어요. 이 설계는 향상된 내결함성을 포함해요 — 한 컴포넌트의 장애가 다른 컴포넌트에 즉시 영향을 주지 않아요.

다음 다이어그램은 Druid 아키텍처를 구성하는 서비스, 서버 전체에서의 일반적인 배치, 그리고 쿼리와 데이터가 이 아키텍처를 통해 흐르는 방식을 보여줘요.

다음 섹션은 이 아키텍처의 컴포넌트를 설명해요.

Druid 서비스

Druid에는 여러 유형의 서비스가 있어요:

  • Coordinator — 클러스터의 데이터 가용성을 관리해요.
  • Overlord — 데이터 ingestion 워크로드의 할당을 제어해요.
  • Broker — 외부 클라이언트의 쿼리를 처리해요.
  • Router — 요청을 Broker, Coordinator, Overlord로 라우팅해요.
  • Historical — 쿼리 가능한 데이터를 저장해요.
  • Middle Manager와 Peon — 데이터를 ingestion해요.
  • Indexer — Middle Manager + Peon task 실행 시스템의 대안으로 제공돼요.

웹 콘솔의 Services 탭에서 서비스를 볼 수 있어요.

Druid 서버

Druid 서비스는 선호에 따라 배포할 수 있어요. 배포의 용이성을 위해, 이를 세 가지 서버 유형 — Master 서버, Query 서버, Data 서버 — 으로 구성하는 것을 권장해요.

Master 서버

Master 서버는 데이터 ingestion과 가용성을 관리해요. 새 ingestion 작업을 시작하고 Data 서버의 데이터 가용성을 조정하는 역할을 담당해요.

Master 서버는 운영을 Coordinator와 Overlord 서비스로 나눠요.

Coordinator 서비스

Coordinator 서비스는 Data 서버의 Historical 서비스를 감시해요. 특정 서버에 segment를 할당하고, Historical 간에 segment가 잘 균형 잡히도록 보장하는 역할을 담당해요.

Overlord 서비스

Overlord 서비스는 Data 서버의 Middle Manager 서비스를 감시하며 Druid로의 데이터 ingestion을 제어해요. Middle Manager에 ingestion task를 할당하고 segment publishing을 조정하는 역할을 담당해요.

Query 서버

Query 서버는 사용자와 클라이언트 애플리케이션이 상호작용하는 엔드포인트를 제공하고, 쿼리를 Data 서버나 다른 Query 서버로 라우팅해요(선택적으로 Master 서버 요청을 프록시하기도 해요).

Query 서버는 운영을 Broker와 Router 서비스로 나눠요.

Broker 서비스

Broker 서비스는 외부 클라이언트에서 쿼리를 받아 Data 서버로 전달해요. Broker가 하위 쿼리에서 결과를 받으면 그 결과를 병합해 호출자에게 반환해요. 보통 Data 서버의 Historical이나 Middle Manager 서비스를 직접 쿼리하기보다 Broker를 쿼리해요.

Router 서비스

Router 서비스는 Broker, Overlord, Coordinator 앞에서 통합 API 게이트웨이를 제공해요.

Router 서비스는 또한 데이터 로드, 데이터소스·task 관리, 서버 상태·segment 정보 확인을 위한 UI인 웹 콘솔도 실행해요.

Data 서버

Data 서버는 ingestion 작업을 실행하고 쿼리 가능한 데이터를 저장해요.

Data 서버는 운영을 Historical과 Middle Manager 서비스로 나눠요.

Historical 서비스

Historical 서비스는 시스템에 오래 있어 커밋된 스트리밍 데이터를 포함해 히스토리컬 데이터의 저장과 쿼리를 처리해요. Historical 서비스는 deep storage에서 segment를 내려받고 이 segment에 대한 쿼리에 응답해요. 쓰기는 받지 않아요.

Middle Manager 서비스

Middle Manager 서비스는 클러스터로의 새 데이터 ingestion을 처리해요. 외부 데이터 소스에서 읽어 새 Druid segment를 게시하는 역할을 담당해요.

Peon 서비스

Peon 서비스는 Middle Manager가 생성하는 task 실행 엔진이에요. 각 Peon은 별도 JVM을 실행하며 단일 task를 실행하는 역할을 담당해요. Peon은 항상 자신을 생성한 Middle Manager와 같은 호스트에서 실행돼요.

Indexer 서비스 (선택적)

Indexer 서비스는 Middle Manager와 Peon의 대안이에요. task마다 별도 JVM 프로세스를 fork하는 대신, Indexer는 단일 JVM 프로세스 안에서 task를 개별 스레드로 실행해요.

Indexer는 MiddleManager + Peon 시스템보다 설정과 배포가 쉽고 task 간 리소스 공유를 더 잘 지원하도록 설계되었으며, 이는 스트리밍 ingestion에 도움이 될 수 있어요. Indexer는 현재 실험적으로 지정되어 있어요.

보통 다음 중 하나만 배포해요: MiddleManager, Kubernetes를 이용한 MiddleManager-less ingestion, 또는 Indexer. 이 중 두 개 이상을 배포하지는 않아요.

서비스 공동 배치 (Colocation)

서버 유형별로 Druid 서비스를 공동 배치하면 대부분의 클러스터에서 하드웨어 리소스를 더 잘 활용하는 결과를 얻을 수 있어요.

매우 큰 규모의 클러스터에서는 리소스 경합을 피하기 위해 Druid 서비스를 분리해 개별 서버에서 실행하는 것이 바람직할 수 있어요.

이 섹션에서는 서비스 공동 배치와 관련된 지침과 구성 파라미터를 설명해요.

Coordinator와 Overlord

Coordinator 서비스의 워크로드는 클러스터의 segment 수에 따라 증가하는 경향이 있어요. Overlord의 워크로드도 segment 수에 따라 증가하지만, Coordinator보다는 정도가 덜해요.

segment 수가 매우 많은 클러스터에서는 Coordinator의 segment 균형 워크로드에 더 많은 리소스를 제공하기 위해 Coordinator와 Overlord 서비스를 분리하는 것이 합리적일 수 있어요.

druid.coordinator.asOverlord.enabled 속성을 설정하면 Coordinator와 Overlord 서비스를 단일 통합 서비스로 실행할 수 있어요.

자세한 내용은 Coordinator Operation을 참고하세요.

Historical과 Middle Manager

ingestion 또는 쿼리 부하가 높을수록 CPU와 메모리 경합을 피하기 위해 Historical과 Middle Manager 서비스를 별도 호스트에 배포하는 것이 합리적일 수 있어요.

Historical 서비스는 memory-mapped segment를 위한 여유 메모리가 있으면 유리해요. 이것도 Historical과 Middle Manager 서비스를 분리 배포하는 또 다른 이유가 될 수 있어요.

외부 의존성

내장 서비스 유형 외에도 Druid에는 세 가지 외부 의존성이 있어요. 이들은 기존 인프라가 있다면 그것을 활용하도록 설계되었어요.

Deep storage

Druid는 시스템에 ingestion된 모든 데이터를 저장하는 데 deep storage를 사용해요. deep storage는 모든 Druid 서버가 접근할 수 있는 공유 파일 저장소예요. 클러스터 배포에서는 보통 S3나 HDFS 같은 분산 객체 저장소 또는 네트워크 마운트 파일시스템이에요. 단일 서버 배포에서는 보통 로컬 디스크예요.

Druid는 다음 목적으로 deep storage를 사용해요:

  • ingestion한 모든 데이터를 저장합니다. 저지연 쿼리를 위해 Historical 서비스에 로드되는 segment도 백업 목적으로 deep storage에 유지돼요. 또한 deep storage에만 있는 segment는 deep storage에서의 쿼리에 사용될 수 있어요.
  • Druid 서비스 간에 백그라운드에서 데이터를 전송하는 방법으로 사용합니다. Druid는 segments라는 파일에 데이터를 저장해요.

Historical 서비스는 데이터 segment를 로컬 디스크에 캐시하고, 그 캐시뿐 아니라 인메모리 캐시에서도 쿼리를 서비스해요. Historical 서비스의 디스크 segment는 Druid가 유명한 저지연 쿼리 성능을 제공해요.

또한 deep storage에서 직접 쿼리할 수 있어요. deep storage에만 존재하는 segment를 쿼리하면, Historical 서비스를 확장하지 않고도 더 많은 데이터를 쿼리할 수 있는 대신 일부 성능을 희생하게 돼요.

저장소 크기를 결정할 때 다음을 염두에 두세요:

  • deep storage는 Druid에 ingestion하는 모든 데이터를 담을 수 있어야 해요.
  • Historical 서비스의 디스크 저장소는 쿼리를 실행하기 위해 로드하려는 데이터를 수용할 수 있어야 해요. Historical 서비스의 데이터는 자주 접근하고 저지연 쿼리를 실행해야 하는 데이터여야 해요.

deep storage는 Druid의 탄력적이고 내결함성 있는 설계의 중요한 부분이에요. 모든 Data 서버를 잃고 다시 프로비저닝해도 Druid는 deep storage에서 부트스트랩해요.

자세한 내용은 Deep storage 페이지를 참고하세요.

Metadata storage

metadata storage는 segment 사용 정보와 task 정보 같은 다양한 공유 시스템 메타데이터를 보유해요. 클러스터 배포에서는 보통 PostgreSQL이나 MySQL 같은 전통적인 RDBMS예요. 단일 서버 배포에서는 보통 로컬 저장된 Apache Derby 데이터베이스예요.

자세한 내용은 Metadata storage 페이지를 참고하세요.

ZooKeeper

내부 서비스 발견, 조정(coordination), 리더 선출에 사용돼요.

자세한 내용은 ZooKeeper 페이지를 참고하세요.

더 알아보기 (Learn more)

자세한 내용은 다음 주제를 참고하세요:

  • Storage components — Druid의 데이터 저장에 대해 알아봐요.
  • Segments — segment 파일에 대해 배워요.
  • Query processing — Druid가 쿼리를 처리하는 방식의 개요를 살펴봐요.