Milvus #1 - 아키텍처

2025. 4. 22. 11:32·AI/검색 시스템

개요

Milvus는 컴퓨팅 노드에 대한 스토리지 및 컴퓨팅 분리와 수평적 확장성을 특징으로 하는 공유 스토리지 아키텍처를 채택합니다. Data Plane과 Control plane 분리 원칙에 따라 Milvus는 access layer, coordinator service, worker node, storage의 네 가지 계층으로 구성됩니다. 이러한 계층은 확장 또는 재해 복구와 관련하여 상호 독립적입니다.

 

figure에 따라서 인터페이스는 다음과 같은 카테고리로 분류할 수 있습니다.

  • DDL / DCL: createCollection / createPartition / dropCollection / dropPartition / hasCollection / hasPartition
  • DML / Produce: insert / delete / upsert
  • DQL: search / query

 

 

Access Layer

Stateless Proxy의 그룹으로 구성된 access layer는 시스템의 최전방 계층이자 사용자 엔드포인트입니다. 클라이언트 요청의 유효성을 검사하고 반환되는 결과를 줄입니다. 프록시는 그 자체로 상태 비저장(Stateless)입니다. Nginx, Kubernetes Ingress, NodePort, LVS와 같은 부하 분산 구성 요소를 사용하여 통합 서비스 주소를 제공합니다. Milvus는 대규모 병렬 처리(MPP) 아키텍처를 사용하므로 프록시는 최종 결과를 클라이언트로 반환하기 전에 중간 결과를 집계하고 사후 처리합니다.

 

Coordinator service

Coordinator Service는 Worker nodes에 작업을 할당하고 시스템의 핵심 역할을 합니다. Coordinator Service가 수행하는 작업에는 클러스터 토폴로지 관리, 로드 밸런싱, 타임스탬프 생성, 데이터 선언 및 데이터 관리가 포함됩니다.

코디네이터 유형에는 루트 코디네이터(루트 좌표), 데이터 코디네이터(데이터 좌표), 쿼리 코디네이터(쿼리 좌표)의 세 가지가 있습니다.

Root coordinator (root coord)

Root coordinator는 컬렉션, 파티션 또는 인덱스를 생성하거나 삭제하는 것과 같은 DDL 및 DCL 요청을 처리하고 TSO(타임스탬프 Oracle) 및 타임 티커 발급을 관리합니다.

Query coordinator (query coord)

Query coordinator는 쿼리 노드의 토폴로지와 부하 분산을 관리하고, growing 세그먼트에서 sealed 세그먼트로 핸드오프를 처리합니다.

Data coordinator (data coord)

Data coordinator는 데이터 노드와 인덱스 노드의 토폴로지를 관리하고, 메타데이터를 유지 관리하며, flush, compact, 인덱스 구축 및 기타 백그라운드 데이터 작업을 트리거합니다.

 

Worker nodes

Worker nodes는 Coordinator service의 지시를 따르고 프록시에서 DML 명령을 실행하는 단순 실행자입니다. Worker nodes는 스토리지와 컴퓨팅이 분리되어 있어 상태 비저장(stateless)이 가능하며, 쿠버네티스에 배포하면 시스템 확장 및 재해 복구를 용이하게 할 수 있습니다. 워커 노드에는 세 가지 유형이 있습니다.

Query node

Query node는 증분 로그 데이터를 검색하고 로그 브로커를 구독하여 이를 growing 세그먼트로 전환하고, Object Storage에서 과거 데이터를 로드하고, 벡터와 스칼라 데이터 간에 하이브리드 검색을 실행합니다.

Data node

Data node는 로그 브로커를 구독하여 증분 로그 데이터를 검색하고, 변형 요청을 처리하고, 로그 데이터를 로그 스냅샷으로 패킹하여 Object Storage에 저장합니다.

Index node

Index node는 인덱스를 생성합니다. 인덱스 노드는 메모리에 상주할 필요가 없으며, 서버리스 프레임워크를 사용하여 구현할 수 있습니다.

 

Storage

스토리지는 시스템의 핵심으로, 데이터 지속성을 담당합니다. 메타 스토리지, 로그 브로커, 객체 스토리지로 구성됩니다.

Meta storage

Meta storage는 컬렉션 스키마, 메시지 소비 체크포인트와 같은 메타데이터의 스냅샷을 저장합니다. 메타데이터 저장에는 매우 높은 가용성, 강력한 일관성, 그리고 트랜잭션 지원이 요구되므로 Milvus는 메타 저장소로 etcd를 선택했습니다. Milvus는 서비스 등록 및 상태 점검에도 etcd를 사용합니다.

Object storage

Object storage는 로그의 스냅샷 파일, 스칼라 및 벡터 데이터의 인덱스 파일, 중간 쿼리 결과를 저장합니다. Milvus는 MinIO를 Object storage로 사용합니다. 하지만 객체 스토리지는 액세스 지연 시간이 길고 쿼리 수에 따라 요금이 부과되기 때문에 Milvus는 성능 향상 및 비용 절감을 위해 메모리 또는 SSD 기반 캐시 풀에 콜드-핫 데이터 분리를 구현할 계획입니다.

Log broker

Log broker는 playback을 지원하는 Pub-Sub 시스템입니다. 또한 Worker nodes가 시스템 장애에서 복구될 때 증분 데이터의 무결성을 보장합니다. Milvus 클러스터는 Pulsar를 로그 브로커로 사용하고, Milvus 단독형은 RocksDB를 Log broker로 사용합니다. 또한, Log broker는 Kafka와 같은 스트리밍 데이터 스토리지 플랫폼으로 쉽게 대체될 수 있습니다.

Milvus는 Log broker를 중심으로 구축되었으며 "log as data" 원칙을 따릅니다. 즉, Milvus는 물리적 테이블을 유지하지 않고 로깅 지속성 및 스냅샷 로그를 통해 데이터 안정성을 보장합니다.

 

Log broker는 Milvus의 핵심입니다. 고유한 Pub-Sub 메커니즘을 통해 데이터 지속성과 읽기-쓰기 분리를 담당합니다. 위의 그림은 메커니즘을 단순화하여 나타낸 것으로, 시스템은 로그 시퀀스를 유지 관리하는 Log broker와 Log subscriber의 두 가지 역할로 나뉩니다. 전자는 컬렉션 상태를 변경하는 모든 작업을 기록하고, 후자는 로그 시퀀스를 구독하여 로컬 데이터를 업데이트하고 읽기 전용 복사본 형태로 서비스를 제공합니다. Pub-Sub 메커니즘은 변경 데이터 캡처(CDC) 및 글로벌 분산 배포 측면에서 시스템 확장성을 위한 여지도 제공합니다.

 

 

 

Data Processing

Data Insertion

Milvus에서는 각 컬렉션에 대해 여러 개의 샤드를 지정할 수 있으며, 각 샤드는 가상 채널(vchannel)에 해당합니다. 다음 그림에서 볼 수 있듯이 Milvus는 로그 브로커의 각 vchannel에 물리적 채널(pchannel)을 할당합니다. 들어오는 모든 삽입/삭제 요청은 기본 키의 해시 값을 기반으로 샤드로 라우팅됩니다.

Milvus에는 복잡한 transaction이 없기 때문에 DML 요청의 검증은 프록시로 진행됩니다. 프록시는 루트 코디네이터와 함께 배치되는 타이밍 모듈인 TSO(타임스탬프 오라클)에서 각 삽입/삭제 요청에 대한 타임스탬프를 요청합니다. 이전 타임스탬프가 새 타임스탬프로 덮어쓰여지면서 타임스탬프는 처리되는 데이터 요청의 순서를 결정하는 데 사용됩니다. 프록시는 Data coord에서 일괄적으로 entity 세그먼트와 primary key를 포함한 정보를 검색하여 전반적인 처리량을 높이고 중앙 노드에 과도한 부담을 주지 않습니다.

DML(데이터 조작 언어) 작업과 DDL(데이터 정의 언어) 작업 모두 로그 시퀀스에 기록되지만, DDL 작업은 발생 빈도가 낮기 때문에 하나의 채널만 할당됩니다.

vchannel은 기본 로그 브로커 노드에서 유지됩니다. 각 채널은 물리적으로 나눌 수 없으며, 어떤 노드에서든 접근 가능하지만 동시에 오직 하나의 노드에서만 사용할 수 있습니다. 데이터 ingestion 속도가 병목에 도달하면 두 가지 사항을 고려하세요. 로그 브로커 노드가 과부하되어 확장이 필요한지 여부와 각 노드의 부하 균형을 보장할 만큼 충분한 샤드가 있는지 여부입니다.

 

위의 다이어그램은 로그 시퀀스를 작성하는 프로세스에 관련된 네 가지 구성 요소, 즉 프록시, 로그 브로커, 데이터 노드, 개체 스토리지를 요약한 것입니다. 이 프로세스에는 DML 요청 검증, 로그 시퀀스의 Pub-Sub, 스트리밍 로그에서 로그 스냅샷으로의 변환, 로그 스냅샷의 persistence의 4가지 작업이 포함됩니다. 4가지 작업은 서로 분리되어 각 작업이 해당 노드 유형에서 처리되도록 합니다. 동일한 유형의 노드는 동일하게 만들어지고 다양한 데이터 부하, 특히 대규모이고 변동성이 큰 스트리밍 데이터를 수용하기 위해 탄력적이고 독립적으로 확장될 수 있습니다.

 

Index building

인덱스 구축은 인덱스 노드를 통해 수행됩니다. 데이터 업데이트를 위한 빈번한 인덱스 구축을 피하기 위해 Milvus에서는 컬렉션을 세그먼트로 세분화하고 각 세그먼트에 고유한 인덱스를 부여합니다.

Milvus는 각 벡터 필드, 스칼라 필드, 그리고 프라이머리 필드에 대해 인덱스를 생성하는 것을 지원합니다. 인덱스를 생성하는 과정에서 입력과 출력 모두 오브젝트 스토리지를 사용합니다: 인덱스 노드는 세그먼트(오브젝트 스토리지에 있음)로부터 인덱싱할 로그 스냅샷을 메모리로 로드하고, 관련된 데이터와 메타데이터를 역직렬화하여 인덱스를 생성한 후, 인덱스 생성이 완료되면 이를 직렬화하여 다시 오브젝트 스토리지에 저장합니다.

인덱스 구축은 주로 벡터 및 행렬 연산을 포함하므로 연산량과 메모리 사용량이 많은 작업입니다. 벡터는 고차원 특성 때문에 전통적인 트리 기반 인덱스로는 효율적으로 인덱싱할 수 없지만, 클러스터 기반 또는 그래프 기반 인덱스와 같은 이 분야에서 보다 성숙한 기술을 통해 인덱싱할 수 있습니다. 인덱스의 유형과 관계없이, 인덱스 구축은 K-means나 그래프 탐색과 같은 대규모 벡터에 대한 반복적인 계산을 대량으로 수행해야 합니다.

스칼라 데이터의 인덱싱과는 달리, 벡터 인덱스를 구축할 때는 SIMD(single instruction, multiple data) 가속을 최대한 활용해야 합니다. Milvus는 SSE, AVX2, AVX512와 같은 SIMD 명령어 세트를 기본적으로 지원합니다. 벡터 인덱스 구축은 "중단(hiccup)" 현상과 자원 집약적인 특성을 가지기 때문에, Milvus에서는 경제적인 관점에서 탄력성(elasticity)이 매우 중요합니다. 향후 Milvus 릴리스에서는 관련 비용을 줄이기 위해 이기종 컴퓨팅(heterogeneous computing) 및 서버리스 컴퓨팅(serverless computation)에 대한 탐구가 계속될 예정입니다.

또한 Milvus는 스칼라 필터링(scalar filtering)과 기본 필드(primary field) 질의도 지원합니다. Milvus에는 Bloom 필터 인덱스, 해시 인덱스, 트리 기반 인덱스, 역색인(inverted index) 등 쿼리 효율을 향상시키기 위한 내장 인덱스가 있으며, 향후에는 비트맵 인덱스(bitmap indexes)나 러프 인덱스(rough indexes)와 같은 외부 인덱스도 도입할 계획입니다.

 

Data query

데이터 쿼리란, 지정된 컬렉션에서 대상 벡터와 가장 가까운 k개의 벡터를 검색하거나, 대상 벡터로부터 지정된 거리 범위 내에 있는 모든 벡터를 검색하는 과정을 말합니다. 벡터는 해당하는 기본 키(primary key) 및 필드 정보와 함께 반환됩니다.

Milvus에서 하나의 컬렉션은 여러 개의 세그먼트(segment)로 분할되며, 쿼리 노드(query node)는 세그먼트 단위로 인덱스를 로드합니다. 검색 요청이 도착하면, 해당 요청은 모든 쿼리 노드에 브로드캐스트되어 병렬 검색이 수행됩니다. 각 노드는 로컬 세그먼트를 필터링하고, 조건에 부합하는 벡터를 검색한 후, 결과를 취합하여 반환합니다.

데이터 쿼리 과정에서 쿼리 노드들은 서로 독립적으로 작동합니다. 각 노드는 오직 두 가지 작업만 담당합니다: 쿼리 코디네이터(query coord)의 명령에 따라 세그먼트를 로드하거나 해제하는 일, 그리고 로컬 세그먼트 내에서 검색을 수행하는 일입니다. 프록시(proxy)는 각 쿼리 노드로부터 반환된 검색 결과를 취합하여 최종 결과를 클라이언트에게 전달합니다.

 

세그먼트는 두 가지 유형이 있습니다: 증분 데이터(incremental data)를 위한 growing 세그먼트와, 이력을 보존하는 sealed 세그먼트입니다. 쿼리 노드는 vchannel을 구독하여 최근 업데이트된 증분 데이터를 growing 세그먼트로 수신합니다. growing 세그먼트가 사전 정의된 임계값에 도달하면, data coord가 이를 sealed 상태로 전환하고 인덱스 구축이 시작됩니다. 이후, query coord가 주도하는 handoff 작업을 통해 증분 데이터가 이력 데이터로 전환됩니다. query coord는 메모리 사용량, CPU 부하, 세그먼트 수 등을 기준으로 sealed 세그먼트를 모든 쿼리 노드에 균등하게 분산시킵니다.

저작자표시 (새창열림)

'AI > 검색 시스템' 카테고리의 다른 글

검색 시스템을 위한 Document Splitting  (1) 2025.01.26
ANN(Approximate Nearest Neighbor) 알고리즘의 이해 #3 DiskANN  (0) 2025.01.26
ANN(Approximate Nearest Neighbor) 알고리즘의 이해 #2 Flat, LSH, IVF, HNSW + SQ, PQ, RPQ  (0) 2025.01.26
ANN(Approximate Nearest Neighbor) 알고리즘의 이해 #1  (0) 2025.01.26
Retrieval 시스템을 위한 MTEB 벤치마크  (2) 2025.01.03
'AI/검색 시스템' 카테고리의 다른 글
  • 검색 시스템을 위한 Document Splitting
  • ANN(Approximate Nearest Neighbor) 알고리즘의 이해 #3 DiskANN
  • ANN(Approximate Nearest Neighbor) 알고리즘의 이해 #2 Flat, LSH, IVF, HNSW + SQ, PQ, RPQ
  • ANN(Approximate Nearest Neighbor) 알고리즘의 이해 #1
pfldy2850
pfldy2850
인공지능의 서비스화와 현실화에 관심이 많은 엔지니어입니다.
  • pfldy2850
    DEV.DY
    Github LinkedIn
  • 전체
    오늘
    어제
    • All (105) N
      • AI (68)
        • 어플리케이션 개발 (11)
        • 모델 인퍼런스 (9)
        • 검색 시스템 (11)
        • MLOps (8)
        • 기술,논문 리뷰 (7)
        • Lecture notes (10)
        • 오픈소스 릴리즈 노트 (12)
      • Infra (4)
        • Kubernetes (1)
        • Service Mesh (1)
        • Service Proxy (1)
        • Storage (1)
      • Data Engineering (4)
        • Spark (3)
        • Kafka (1)
        • Delta Lake (0)
      • 컴퓨터 공학 (2)
        • 소프트웨어 공학 (2)
      • 개발 (16) N
        • ReactJS (8)
        • NodeJS (2)
        • Python (4) N
        • Pytorch (1)
        • git (1)
      • 영어공부 (2)
        • GPT로 영어 회화 공부 (2)
      • 활동 (2)
        • 2017 NDC (2)
      • 기타 (1)
      • 레거시 (6)
        • OS (6)
  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
pfldy2850
Milvus #1 - 아키텍처
상단으로

티스토리툴바