메타데이터를 통해 아래와 같은 질의를 지원해야 한다.
이러한 요구사항을 만족하기 위한 메타데이터 테이블 구조는 다음과 같다:
테이블명 | 컬럼 | 설명 |
---|---|---|
Buckets | bucket_name | 버킷의 이름 |
bucket_id(PK) | 버킷의 고유 식별자 | |
owner_id | 버킷 소유자 ID | |
enable_versioning | 버전 관리 활성화 여부 | |
Objects | bucket_name | 객체의 이름 |
object_name | 객체의 이름 | |
object_version | 객체의 버전 | |
object_id | 객체의 고유 식별자 |
버킷 테이블의 규모 산정
하나의 데이터베이스로 처리 가능한 크기이지만, 모든 읽기/쓰기를 감당하기에는 대역폭이 부족할 수 있음.
따라서 데이터베이스 사본을 활용하는 것이 적절함.
bucket_id
를 기준으로 샤딩한다면, 헤비 유저의 버킷이 핫스팟이 되므로 부하가 분산되지 않음.object_id
를 기준으로 샤딩한다면, 핫스팟은 줄일 수 있지만 앞서 이야기한 1, 2번 질의를 효과적으로 처리하기 어렵다. 이는 두 질의는 URI를 기준으로 처리되기 때문임.bucket_id
와 object_name
을 결합하여 샤딩에 활용할 수 있음.Q. URI를 기준으로 처리하는것과
object_id
를 기준으로 샤딩하는것이 무슨 관계가 있지?두 질의는 모두 URI를 기준으로 처리되기 때문에, 객체의 이름이 문자열로 제공됨.
따라서 이 문자열을object_id
(UUID)로 변환하기 위해 메타데이터가 필요한데, 이는 결국 모든 샤드를 탐색해야 알 수 있음.
반면bucket_id
와object_name
을 결합하여 샤딩하면, 이는 두 문자열을 결합하여 하나의 샤드를 특정할 수 있으므로 효율적임.
단일 데이터베이스 서버에서 객체를 조회하는 방식은 아래와 같다.
# 사용자의 모든 버킷 조회
SELECT * FROM bucket WHERE owner_id={id}
# 버킷 내의 특정 디렉토리 내의 모든 객체 선택(접두어)
SELECT * FROM object
WHERE bucket_id = "123" AND object_name LIKE `abc/%`
이 작업에서 abc
이하의 디렉토리 처리는 어플리케이션에서 처리한다.
분산 데이터베이스에서는 우리가 찾는 데이터가 어떤 샤드에 있는지 모른다.
가장 쉬운 방법은 모든 샤드에 검색을 하고, 이 결과를 종합하는 것이다.
# 모든 샤드에 아래 쿼리 실행 및 결과 취합
SELECT * FROM object
WHERE bucket_id = "123" AND object_name LIKE `a/b/%`