Storage/Druid
druid 구조
Prower
2022. 7. 26. 00:40
728x90
반응형
# 이 글은 druid 공식문서의 design 파트를 정리한 글입니다.
- druid는 클라우드 서비스에 적용하기 쉬운 분산 구조로 이루어져 있다.
- 이러한 구조 덕분에 몇가지 설정만으로 쉽고 유연하게 스케일 조절도 가능하며, 장애 복구 기능도 제공한다.
전체 구조
출처: https://druid.apache.org/docs/latest/design/architecture.html
드루이드 서비스
- 드루이드는 다음의 서비스로 구성되어 있다.
- coodinator service: 데이터 가용성을 책임지는 서비스
- overlord service: 데이터 적재 작업을 제어
- broker: 외부 클라이언트에서 들어온 쿼리문 제어
- router service: request를 broker, coodinator, overlord에 분산
- historical service: 쿼리가 가능한 데이터 저장
- middlemanger service: 데이터를 적재 작업 담당
druid server
- druid 서비스는 어떤 방식으로든 배포될 수 있지만, 운영상 유연함을 위해 다음의 3개 type의 서버로 나눠 배포하는 것을 추천한다.
- master: coonidator, overlord 서비스 배포
- query: broker, router 서비스 배포
- data: historical, maddlemanger 서비스 배포
외부 의존성
- 드루이드는 다음과 같은 외부 의존성을 갖는다.
deep storage
- 시스템에 적재된 모든 데이터를 저장하는 모든 druid서버에서 접근 가능한 file storage
- cluster 구조에서는 일반적으로 S3, HDFS 같은 분산 데이터 저장소나 mounted filesystem을 사용하여 구성한다.
- 백업: druid process에서 데이터를 이동시킬 때 데이터를 백업하는 용도로도 사용한다.
metadata storage
- 시스템에서 전반적으로 공유되는 metadata 저장하는 storage
- cluster 구조에서는 일반적으로 RDBMS를 사용하여 구성한다.
zookeeper
- internal service discovery, coordination에 사용
저장소의 구조
datasources and segments
- druid의 데이터는 RDMS와 유사한 구조를 가진 datasource에 저장된다.
- 각 datasource는 기본적으로 time에 대해 파티션 되어 있으며, 경우에 따라 다른 필드에 대해서도 파티셔닝이 된다.
- 이렇게 파티션이된 시간 범위를 chunk라 한다.
- chunk 내부에서도 데이터는 segment라고 하는 더 작은 단위로 나눠진다.
https://druid.apache.org/docs/latest/assets/druid-timeline.png
- 정리하자면 위 그림과 같이 segment -> chunk로 구성되며 모두 시간 순서로 정리된다.
commit
- 각 segment는 middlemanager에 의해 생성되며 mutable하고 uncommited 된 상태이다.
- 즉, 변경이 가능한 데이터라는 의미
- 주기적으로, segment 데이터는 commit되어 변경이 불가능한 상태로 deep storage에 저장된다.
indexing and handoff
- indexing: segment가 생성되는 매커니즘
- handoff: 생성된 segment가 publish 되고, 제공되는 매커니즘
indexing 과정
- indexing task가 실행되면, segment에 고유한 id값을 부여하고 segment를 생성한다.
- task는 다음의 2종류가 있다.
- appending task(데이터 추가): append 모드로 실행되어, overlord가 기존의 segment에 새로운 partition을 추가
- overwriting task(데이터 수정): interval을 lock한 상태로, 새로운 버전의 segment를 새로 생성
- indexing task가 realtime으로 실행되면, 생성된 segment는 바로 query로 조회할 수 있다.
- indexing task가 segment로 부터 데이터를 읽는 과정을 끝낸 뒤, deep storage로 publish 한다.
segment identifiers
- 모든 segment는 다음의 로 구성된 id값을 부여받는다.
- datasource name
- time interval
- version number
- partition number
- 부여되는 id: {datasource name}{time interval}{version number}_{partition number}
segment versioning
- version number는 데이터의 변경사항을 버저닝 하는데 사용한다.
- 예를들어, 최초로 append 모드로 기록된 데이터면 1개의 version을 갖는다.
- 만약, 데이터를 overwrite하면 druid는 예전 버전이 아닌 최신으로 기록된 버전을 조회하도록 query를 실행한다.
- overwrite에 의해 새로 생성되는 segment는 같은 time interval, datasource를 갖지만 더 높은 버전의 version number를 부여받는다.
- 그리고 old 버전으로 기록된 segment는 차후에 cluster에 의해 제거된다.
availability and consistency
- druid는 데이터 적재와 쿼리가 나눠져 있는 구조이다.
데이터 적재
- druid는 transaction을 통해 데이터가 all-or-nothing 으로 적재되는 것을 보장한다.
- 적재 method
- druid는 데이터를 적재하는데 다음과 같은 method를 사용한다.
- steaming 적재(kafka, kinesis): segment 단위 스트리밍 방식으로 데이터를 적재. 만약 데이터가 publish 되지 않은 상태에서 적재가 실패할 경우 rollback 가능
- hadoop 기반의 batch 적재: 하나의 task 마다 모든 segment를 single transaction으로 publish
- native batch ingestion: 병렬 모드에서, subtask가 끝난 뒤에 모든 segment 데이터를 single transacion으로 publish
쿼리
- 쿼리가 들어오면 druid broker가 적절한 segment version을 선정하여 segment를 결과에 포함시킨다.
728x90
반응형