샤드 수명 주기
샤드 수명 주기 (Shard Lifecycle) (edge-edge-api-shard-lifecycle)
Edge 샤드(Edge Shard)는 로컬 디스크의 디렉터리를 기반으로 해요. 샤드의 수명 주기는 다음과 같아요:
- 생성(Create):
EdgeShard.create(Python) 또는EdgeShard::new(Rust)로 새 샤드를 만들거나,load로 기존 샤드를 로드해요. - 사용(Use): 샤드를 사용해 데이터를 업데이트하고 쿼리해요.
- 플러시 및 닫기(Flush and Close): 보류 중인 변경 사항을 디스크에 플러시하고, 샤드를 닫아 리소스를 해제해요.
샤드는 해당 디렉터리의 파일을 소유하므로, 주어진 디렉터리에는 한 번에 하나의 EdgeShard만 열 수 있어요.
새 Edge 샤드 만들기 (Create a New Edge Shard)
제공된 구성을 사용해 path에 새 Edge 샤드를 만들어요.
@staticmethod
def create(path: str, config: EdgeConfig) -> EdgeShard
pub fn new(path: &Path, config: EdgeConfig) -> OperationResult<EdgeShard>
| 파라미터 | 설명 |
|---|---|
path |
샤드 디렉터리 경로. 이미 세그먼트 데이터를 포함하고 있으면 안 돼요. |
config |
새 샤드의 구성. 필수. |
반환값 새 EdgeShard 인스턴스.
샤드의 세그먼트 디렉터리에 세그먼트가 이미 포함되어 있으면 생성이 실패해요. 이미 데이터를 보유한 디렉터리를 열려면 대신 load를 사용해 주세요.
구성은 샤드 디렉터리 안의 edge_config.json에 저장되므로, 나중에 load를 호출하면 다시 전달하지 않아도 복구할 수 있어요. 쓰기 전 로그(write-ahead log) 동작은 config.wal_options를 따르며, 설정하지 않으면 기본적으로 32 MiB 세그먼트를 사용해요. 사용자 정의 WAL 크기를 참고해 주세요.
기존 Edge 샤드 로드하기 (Load an Existing Edge Shard)
path의 기존 파일에서 Edge 샤드를 열어요.
@staticmethod
def load(path: str, config: Optional[EdgeConfig] = None) -> EdgeShard
pub fn load(path: &Path, config: Option<EdgeConfig>) -> OperationResult<EdgeShard>
| 파라미터 | 설명 |
|---|---|
path |
기존 샤드 디렉터리의 경로. |
config |
구성 재정의. 생략하면 샤드의 저장된 구성이 사용돼요. |
반환값 로드된 EdgeShard 인스턴스.
디렉터리에 세그먼트가 없고 로드하거나 유추할 수 있는 구성도 없으면 로드가 실패해요.
변경하더라도 저장된 세그먼트에 영향을 주는 파라미터는 즉시 적용되지 않아요. 기존 세그먼트는 옵티마이저가 실행되면서 새 값으로 수렴해요.
경로와 구성 검사하기 (Inspect the Path and Configuration)
Rust 전용
샤드의 디렉터리와 현재 해석된 구성을 반환해요.
pub fn path(&self) -> &Path
pub fn config(&self) -> parking_lot::RwLockReadGuard<'_, EdgeConfig>
config는 복사본이 아니라 읽기 가드(guard)를 반환하므로, 이를 통해 구성을 변경할 수 없고 가드는 신속히 해제해야 해요. 라이브 샤드의 구성을 변경하려면 set_hnsw_config, set_vector_hnsw_config 또는 set_optimizers_config를 사용해 주세요.
샤드 내용에 대한 메타데이터를 반환해요.
def info(self) -> ShardInfo
pub fn info(&self) -> OperationResult<ShardInfo>
ShardInfo는 다음 필드를 담아요. 카운트는 세그먼트 전체에 걸쳐 합산되며, 포인트는 최적화되기 전에 둘 이상의 세그먼트에 존재할 수 있으므로 points_count와 indexed_vectors_count는 근사치이며 고유 포인트 수보다 높게 읽힐 수 있어요:
| 필드 | 유형 | 설명 |
|---|---|---|
segments_count |
int |
샤드 내 세그먼트 수. |
points_count |
int |
저장된 포인트의 근사 수. |
indexed_vectors_count |
int |
벡터 인덱스에 추가된 벡터의 근사 수. |
payload_schema |
필드 이름 → PayloadIndexInfo 맵 |
샤드의 페이로드 인덱스. |
indexed_vectors_count가 points_count보다 훨씬 낮으면 세그먼트가 아직 최적화를 기다리고 있다는 뜻이에요. optimize를 참고해 주세요.
보류 중인 변경 사항 플러시하기 (Flush Pending Changes)
쓰기 전 로그와 모든 세그먼트를 디스크에 저장해요.
def flush(self) -> None
pub fn flush(&self) -> OperationResult<()>
반환값 Python에서는 아무것도 없어요. Rust에서는 성공 시 Ok(()), WAL 또는 세그먼트를 플러시할 수 없으면 오류를 반환해요.
flush는 WAL과 세그먼트 잠금이 풀릴 때까지 블록돼요. update 또는 optimize가 진행되는 동안 발행된 flush는 잠금 경합 오류로 실패하는 대신 해당 작업이 끝날 때까지 기다렸다가 저장해요. 플러시 중 발생한 실제 I/O 오류는 여전히 호출자에게 전달돼요.
샤드를 닫고 리소스를 해제해요.
def close(self) -> None
Rust에는 close 메서드가 없어요. EdgeShard는 Drop을 구현하므로, 샤드가 스코프를 벗어나면 닫혀요:
{
let shard = EdgeShard::new(path, config)?;
// ... use the shard ...
} // `shard` is dropped here, flushing to disk
두 언어 모두에서 닫으면 보류 중인 데이터가 디스크에 플러시돼요. 데이터는 디스크에 남으며 디렉터리는 load로 다시 열 수 있어요.