이 게시물은 추천 시스템에서 Milvus를 사용하는 Kingsoft Office Software의 WPS 엔지니어링 팀에서 제공한 글입니다. Milvus 2.2.16에서 2.5.16으로 업그레이드하는 동안 검색 지연 시간이 3배에서 5배까지 증가했습니다. 이 문서에서는 이 문제를 조사하고 해결한 방법을 안내하며, 비슷한 업그레이드를 계획 중인 커뮤니티의 다른 사용자들에게 도움이 될 수 있습니다.
Milvus를 업그레이드한 이유
저희는 생산성 소프트웨어를 구축하는 WPS 엔지니어링 팀의 일원으로 온라인 추천 시스템에서 실시간 유사도 검색을 위한 벡터 검색 엔진으로 Milvus를 사용하고 있습니다. 우리의 프로덕션 클러스터에는 평균 768개의 차원으로 수천만 개의 벡터가 저장되어 있습니다. 데이터는 16개의 쿼리 노드에서 제공되었으며, 각 포드는 16개의 CPU 코어와 48GB의 메모리로 제한되어 구성되었습니다.
Milvus 2.2.16을 실행하는 동안 이미 비즈니스에 영향을 미치고 있는 심각한 안정성 문제가 발생했습니다. 쿼리 동시성이 높을 때 planparserv2.HandleCompare 에서 널 포인터 예외가 발생하여 프록시 구성 요소가 패닉 상태에 빠지고 자주 다시 시작될 수 있었습니다. 이 버그는 동시 접속자가 많은 시나리오에서 매우 쉽게 트리거되었으며 온라인 추천 서비스의 가용성에 직접적인 영향을 미쳤습니다.
대상 클러스터는 동일한 Milvus 버전 또는 최신 버전을 실행해야 합니다. 2.2의 백업은 2.5로 로드할 수 있지만 그 반대는 불가능합니다.
대상은 Milvus 2.4 이상이어야 합니다. 이전 복원 대상은 지원되지 않습니다.
저희 경로(2.2.16에서 백업, 2.5.16에 로드)는 두 가지 규칙을 모두 충족했습니다.
다음에서 백업 ↓ \ 복원 대상 →
2.4
2.5
2.6
2.2
✅
✅
✅
2.3
✅
✅
✅
2.4
✅
✅
✅
2.5
❌
✅
✅
2.6
❌
❌
✅
Milvus 백업 작동 방식
Milvus 백업은 Milvus 인스턴스 전반에서 메타데이터, 세그먼트 및 데이터의 백업과 복원을 용이하게 합니다. 백업 및 복원 프로세스의 유연한 조작을 위해 CLI, API, gRPC 기반 Go 모듈과 같은 노스바운드 인터페이스를 제공합니다.
Milvus Backup은 소스 Milvus 인스턴스에서 컬렉션 메타데이터와 세그먼트를 읽어 백업을 생성합니다. 그런 다음 소스 Milvus 인스턴스의 루트 경로에서 컬렉션 데이터를 복사하여 백업 루트 경로에 저장합니다.
백업에서 복원하려면 Milvus 백업은 백업의 컬렉션 메타데이터 및 세그먼트 정보를 기반으로 대상 Milvus 인스턴스에 새 컬렉션을 만듭니다. 그런 다음 백업 루트 경로에서 대상 인스턴스의 루트 경로로 백업 데이터를 복사합니다.
백업 실행
전용 구성 파일인 configs/backup.yaml 을 준비했습니다. 주요 필드는 아래와 같으며 민감한 값은 제거되어 있습니다:
milvus:
address: 1.1.1.1# Source Milvus address
port: 19530# Source Milvus port
user: root # Source Milvus username (must have backup permissions)
password: <PASS> # Source Milvus user password
etcd:
endpoints: “2.2.2.1:2379,2.2.2.2:2379,2.2.2.3:2379”# Endpoints of the etcd cluster connected to Milvus
rootPath: “by-dev”# Prefix of Milvus metadata in etcd. If not modified, the default is by-dev. It is recommended to check etcd before proceeding.
minio:
# Source Milvus object storage bucket configuration
storageType: “aliyun”# support storage type: local, minio, s3, aws, gcp, ali(aliyun), azure, tc(tencent), gcpnative
address: ks3-cn-beijing-internal.ksyuncs.com # Address of MinIO/S3
port: 443# Port of MinIO/S3
accessKeyID: object storage AK>
secretAccessKey: object storage SK>
useSSL: true
bucketName: “”
rootPath: “file”# Root directory prefix under the source object storage bucket where the current Milvus data is stored. If Milvus is installed using Helm Chart, the default prefix is file. It is recommended to log in to the object storage and verify before proceeding.
# Object storage bucket configuration for storing backup data
backupStorageType: “aliyun”# support storage type: local, minio, s3, aws, gcp, ali(aliyun), azure, tc(tencent)
backupAddress: ks3-cn-beijing-internal.ksyuncs.com # Address of MinIO/S3
backupPort: 443# Port of MinIO/S3
backupAccessKeyID:
backupSecretAccessKey:
backupBucketName:
backupRootPath: “backup”# Root path to store backup data. Backup data will be stored in backupBucketName/backupRootPath
backupUseSSL: true # Access MinIO/S3 with SSL
crossStorage: “true”# Must be set to true when performing cross-storage backup
그런 다음 이 명령을 실행했습니다:
# Create a backup using milvus-backup
./milvus-backup create --config configs/backup.yaml -n backup_v2216
milvus-backup핫 백업은 핫 백업을 지원하므로 일반적으로 온라인 트래픽에 거의 영향을 미치지 않습니다. 리소스 경합을 피하려면 사용량이 많지 않은 시간에 실행하는 것이 더 안전합니다.
백업 확인
백업이 완료된 후 백업이 완료되고 사용 가능한지 확인했습니다. 주로 백업의 컬렉션 수와 세그먼트 수가 소스 클러스터의 컬렉션 수와 일치하는지 확인했습니다.
./milvus-backup list --config configs/backup.yaml
# View backup details and confirm the number of Collections and Segments
./milvus-backup get --config configs/backup.yaml -n backup_v2216
일치했으므로 업그레이드로 넘어갔습니다.
헬름 차트로 업그레이드하기
수천만 개의 벡터가 있는 세 가지 주요 버전(2.2 → 2.5)을 이동하는 것은 너무 위험했습니다. 대신 새 클러스터를 구축하고 데이터를 마이그레이션했습니다. 이전 클러스터는 롤백을 위해 온라인 상태를 유지했습니다.
새 클러스터 배포
헬름으로 새로운 Milvus 2.5.16 클러스터를 배포했습니다:
# Add the Milvus Helm repository
: helm repo add milvus https://zilliztech.github.io/milvus-helm/
helm repo update
# Check the Helm chart version corresponding to the target Milvus version
: helm search repo milvus/milvus -l | grep 2.5.16
milvus/milvus 4.2.582.5.16 Milvus is an open-source vector database built ...
# Deploy the new version cluster (with mmap disabled)
helm install milvus-v25 milvus/milvus
–namespace milvus-new
–values values-v25.yaml
–version 4.2.58
–wait
주요 구성 변경 (values-v25.yaml)
성능 비교를 공정하게 하기 위해 새 클러스터를 가능한 한 이전 클러스터와 유사하게 유지했습니다. 이 워크로드에 중요한 몇 가지 설정만 변경했습니다:
Mmap 비활성화 (mmap.enabled: false): 권장 워크로드는 지연 시간에 민감합니다. Mmap을 활성화하면 필요할 때 일부 데이터를 디스크에서 읽을 수 있으며, 이로 인해 디스크 I/O 지연이 추가되어 지연 시간이 급증할 수 있습니다. 데이터가 메모리에 완전히 유지되고 쿼리 지연 시간이 더 안정적으로 유지되도록 이 기능을 해제했습니다.
쿼리 노드 수: 이전 클러스터와 동일하게 16개로 유지됨.
리소스 제한: 각 파드에는 여전히 이전 클러스터와 동일하게 16개의 CPU 코어가 있습니다.
메이저 버전 업그레이드를 위한 팁:
기존 클러스터를 업그레이드하는 대신 새 클러스터를 구축한다. 메타데이터 호환성 위험을 피하고 깨끗한 롤백 경로를 유지할 수 있습니다.
마이그레이션하기 전에 백업을 확인하세요. 데이터가 새 버전의 형식으로 바뀌면 쉽게 되돌릴 수 없습니다.
전환하는 동안 두 클러스터를 모두 계속 실행하세요. 트래픽을 점진적으로 전환하고 완전히 확인된 후에만 이전 클러스터를 해제하세요.
Milvus-백업 복원을 사용하여 업그레이드 후 데이터 마이그레이션하기
milvus-backup restore 을 사용하여 백업을 새 클러스터에 로드했습니다. 밀버스-백업의 용어에서 "복원"은 "백업 데이터를 대상 클러스터에 로드"하는 것을 의미합니다. 대상은 동일한 Milvus 버전 또는 최신 버전을 실행해야 하므로 이름과 상관없이 복원은 항상 데이터를 앞으로 이동합니다.
복원 실행
복원 구성 파일인 configs/restore.yaml 은 새 클러스터와 해당 클러스터의 스토리지 설정을 가리켜야 했습니다. 주요 필드는 다음과 같습니다:
# Restore target Milvus connection information
milvus:
address: 1.1.1.1# Milvus address
port: 19530# Milvus port
user: root # Milvus username (must have restore permissions)
password: <PASS> # Milvus user password
etcd:
endpoints: "2.2.2.1:2379,2.2.2.2:2379,2.2.2.3:2379"# Endpoints of the etcd cluster connected to the target Milvus
rootPath: "by-dev"# Prefix of Milvus metadata in etcd. If not modified, the default is by-dev. It is recommended to check etcd before proceeding.
minio:
# Target Milvus object storage bucket configuration
storageType: “aliyun”# support storage type: local, minio, s3, aws, gcp, ali(aliyun), azure, tc(tencent), gcpnative
address: ks3-cn-beijing-internal.ksyuncs.com # Address of MinIO/S3
port: 443# Port of MinIO/S3
accessKeyID:
# Object storage bucket configuration for storing backup data
backupStorageType: “aliyun”# support storage type: local, minio, s3, aws, gcp, ali(aliyun), azure, tc(tencent)
backupAddress: ks3-cn-beijing-internal.ksyuncs.com # Address of MinIO/S3
backupPort: 443# Port of MinIO/S3
backupAccessKeyID:
backupSecretAccessKey:
backupBucketName:
backupRootPath: “backup”# Root path to store backup data. Backup data will be stored in backupBucketName/backupRootPath
backupUseSSL: true # Access MinIO/S3 with SSL
crossStorage: “true”# Must be set to true when performing cross-storage backup
먼저 새 클러스터에서 잘못된 데이터를 정리한 다음 기본 복원을 실행했습니다. 세그먼트 분포가 균형을 되찾고 검색 지연 시간이 정상으로 돌아왔으며 문제가 사라졌습니다.
다음번에는 다르게 처리할 것
이 사례에서는 실제 문제인 고르지 않은 세그먼트 분포를 찾는 데 너무 오랜 시간이 걸렸습니다. 다음과 같이 하면 더 빨리 찾을 수 있었을 것입니다.
세그먼트 모니터링 개선
Milvus는 표준 Grafana 대시보드에서 컬렉션당 세그먼트 수, 행 분포 또는 크기 분포를 노출하지 않습니다. Attu와 etcd를 수동으로 파헤쳐야 했기 때문에 속도가 느렸습니다.
추가하면 도움이 될 것입니다:
각 쿼리 노드가 로드한 세그먼트 수와 그 행 수 및 크기를 보여주는 Grafana의 세그먼트 분포 대시보드
노드 전반의 세그먼트 행 수가 임계값 이상으로 치우칠 때 트리거되는 불균형 경보
마이그레이션 비교 보기, 사용자가 업그레이드 후 이전 클러스터와 새 클러스터 간의 세그먼트 분포를 비교할 수 있습니다.
표준 마이그레이션 체크리스트 사용
행 수를 확인한 결과 문제가 없다고 판단했습니다. 그것만으로는 충분하지 않았습니다. 마이그레이션 후 완전한 유효성 검사도 포함되어야 합니다:
스키마 일관성. 필드 정의와 벡터 차원이 일치하는가?
세그먼트 수. 세그먼트 수가 급격하게 변경되지는 않았는지?
세그먼트 잔액. 세그먼트 전반의 행 수가 합리적으로 균일한가요?
인덱스 상태. 모든 인덱스가 finished?
지연 시간 벤치마크. P50, P95 및 P99 쿼리 지연 시간이 이전 클러스터와 비슷하게 보이나요?
로드 밸런스. 쿼리 노드의 CPU 사용량이 포드 간에 고르게 분산되어 있나요?
자동화된 검사 추가
이 유효성 검사를 PyMilvus로 스크립트화하여 프로덕션에 적용하기 전에 불균형을 포착할 수 있습니다:
from pymilvus import connections, utility, Collection
defcheck_segment_balance(collection_name: str):
"""Check Segment distribution balance"""
collection = Collection(collection_name)
segments = utility.get_query_segment_info(collection_name)
# Group statistics by QueryNode
node_stats = {}
for seg in segments:
node_id = seg.nodeID
if node_id notin node_stats:
node_stats[node_id] = {"count": 0, "rows": 0}
node_stats[node_id]["count"] += 1
node_stats[node_id]["rows"] += seg.num_rows
# Calculate balance
row_counts = [v["rows"] for v in node_stats.values()]
avg_rows = sum(row_counts) / len(row_counts)
max_deviation = max(abs(r - avg_rows) / avg_rows for r in row_counts)
print(f"Number of nodes: {len(node_stats)}")
print(f"Average row count: {avg_rows:.0f}")
print(f"Maximum deviation: {max_deviation:.2%}")
if max_deviation > 0.2: # Raise a warning if deviation exceeds 20%print("⚠️ Warning: Segment distribution is unbalanced and may affect query performance!")
for node_id, stats insorted(node_stats.items()):
print(f" Node {node_id}: {stats['count']} segments, {stats['rows']} rows")
# Usage example
connections.connect(host=“localhost”, port=“19530”)
check_segment_balance(“your_collection_name”)
기존 도구 더 잘 활용하기
몇 가지 도구는 이미 세그먼트 수준 진단을 지원합니다:
버드워처: Etcd 메타데이터를 직접 읽고 세그먼트 레이아웃과 채널 할당을 표시할 수 있습니다.
Milvus 웹 UI(v2.5+): 세그먼트 정보를 시각적으로 검사할 수 있습니다.
Grafana + Prometheus: 실시간 클러스터 모니터링을 위한 사용자 정의 대시보드 구축에 사용 가능
Milvus 커뮤니티를 위한 제안 사항
Milvus를 몇 가지 변경하면 이러한 종류의 문제 해결이 더 쉬워질 것입니다:
매개변수 호환성에 대한 보다 명확한 설명milvus-backup 문서에 --use_v2_restore 같은 옵션이 버전 간 복원 중에 어떻게 작동하는지, 그리고 이로 인해 발생할 수 있는 위험을 명확하게 설명해야 합니다.
복원 후 더 나은 확인 기능 추가restore 작업이 완료된후도구에서 세그먼트 분포에 대한 요약을 자동으로 인쇄해 주면 도움이 될 것입니다.
잔액 관련 메트릭 노출프로메테우스메트릭에 세그먼트 잔액 정보가 포함되어 사용자가 직접 모니터링할 수 있어야 합니다.
쿼리 계획 분석 지원MySQLEXPLAIN 과유사하게Milvus에는 쿼리가 실행되는 방식을 보여주고 성능 문제를 찾는 데 도움이 되는 도구가 있으면 유용할 것입니다.
결론
요약하자면
단계
도구/방법
키 포인트
백업
밀버스-백업 생성
핫 백업이 지원되지만 백업은 신중하게 확인해야 합니다.
업그레이드
헬름으로 새 클러스터를 빌드한다.
Mmap을 비활성화하여 I/O 지터를 줄이고 리소스 설정을 이전 클러스터와 동일하게 유지한다.
마이그레이션
밀버스-백업 복원
use_v2_restore에 주의한다. 버전 간 복원에서는 명확하게 이해하지 않는 한 기본값이 아닌 로직을 사용하지 않는다.
회색 롤아웃
점진적인 트래픽 이동
단계적으로 트래픽을 이동합니다: 5% → 25% → 50% → 100%, 이전 클러스터는 롤백을 위한 준비 상태 유지
문제 해결
Grafana + 세그먼트 분석
CPU와 메모리만 보지 마세요. 세그먼트 잔액과 데이터 분포도 확인하세요.
수정
잘못된 데이터를 제거하고 다시 복원
잘못된 플래그를 제거하고 기본 로직으로 복원하면 성능이 정상으로 돌아옵니다.
데이터를 마이그레이션할 때는 데이터가 존재하고 정확한지 여부만 고려할 것이 아니라 그 이상을 고려하는 것이 중요합니다. 데이터가 어떻게배포되는지도 주의해야 합니다.
세그먼트 수와 세그먼트 크기는 Milvus가 쿼리 작업을 노드 간에 얼마나 균등하게 분배하는지를 결정합니다. 세그먼트가 불균형하면 소수의 노드가 대부분의 작업을 수행하게 되고 모든 검색이 이에 대한 비용을 지불하게 됩니다. 버전 간 업그레이드는 복원 프로세스가 원래 클러스터와 다르게 세그먼트를 재구축할 수 있기 때문에 추가적인 위험을 수반합니다. --use_v2_restore 같은 플래그는 행 수만으로는 표시되지 않는 방식으로 데이터를 조각화할 수 있습니다.
따라서 버전 간 마이그레이션에서 가장 안전한 접근 방식은 특별한 이유가 없는 한 기본 복원 설정을 그대로 사용하는 것입니다. 또한, 문제를 조기에 발견하려면 CPU와 메모리를 넘어 기본 데이터 레이아웃, 특히 세그먼트 분포와 균형에 대한 인사이트가 있어야 합니다.
Milvus 팀의 참고 사항
이 경험을 Milvus 커뮤니티와 공유해 주신 WPS 엔지니어링 팀에 감사의 말씀을 드립니다. 이와 같은 글은 실제 제작 과정에서 얻은 교훈을 포착하여 비슷한 문제에 직면한 다른 사람들에게 유용하기 때문에 가치가 있습니다.
팀에서 공유할 만한 기술 교훈, 문제 해결 사례 또는 실제 경험이 있다면 여러분의 의견을 듣고 싶습니다. Slack 채널에 가입하여 문의해 주세요.
또한 자체적으로 문제를 해결하고 있다면 동일한 커뮤니티 채널을 통해 Milvus 엔지니어 및 다른 사용자와 소통할 수 있습니다. 백업 및 복원, 버전 간 업그레이드, 쿼리 성능에 대한 도움을 받으려면 Milvus 업무 시간을 통해 일대일 세션을 예약할 수도 있습니다.
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.