////
Search

23장 - S3유사한 객체 저장소

생성일
2024/08/25 03:32
태그
Interview

1. 요구사항 정리

블록 저장소 = 디스크 드라이브를 물리적으로 연결한 형태
원시 블록을 서버에 볼륨 형태로 제공한다.
가장 유연나고 융통성이 높은 저장소
데이터베이스나 가상 머신 엔진 같은 애플리케이션은 원시 블록을 직접 제어하여 최대한의 성능을 끌어냄
서버 입장에서 보면 네트워크/물리적으로 연결된 저장소 모두 동일하게 동작한다.
파일 저장소 = 블록 저장소 위에 구현되는 레이어
파일/디렉터리를 손쉽게 다루기 위한 추상화를 제공
데이터는 계층적으로 구성되는 디렉터리 안에 보관됨
가장 널리 사용되는 범용 저장소 솔루션
객체 저장소 = 실시간 갱신에 필요없는 콜드 데이터 보관에 초점을 맞추어 아카이브나 백업에 주로 쓰인다.
모든 데이터는 수평적 구조 내에 객체로 보관됨
다른 유형의 저장소에 비해 상대적으로 느림

1.1. 모든 요구사항

버킹 생성
객체 업로드 및 다운로드
객체 버전
버킷 내 객체 목록 출력 기능
매년 100PB의 데이터가 추가 가능해야 함
큰 객체든 작은 객체든 효율적으로 저장해야 함
99.999%의 데이터 내구성을 보장
99.99%의 서비스 가용성을 보장

1.2. 규모 추정

디스크 용량: 객체 크기가 다음 분포를 따른다고 가정하자.
객체 가운데 20%는 그 크기가 1MB 미만의 작은 객체다.
정도의 객체는 1MB-64MB 정도 크기의 중간 크기 객체다.
나머지 20% 정도는 64MB 이상의 대형 객체다.
lOPS(IO per seconds)
하드 디스크 하나가 초당 100~150회의 임의 데이터 탐색을 지원할 수 있다고 가정 (100~ 150 IOPS)
계산의 편의를 위해서 객체 유형별 중앙값 사용
소형 = 0.5MB, 중형 = 32MB, 대형 = 200MB
100PB = 100 X 1000 X 1000 X 1000MB = 10^11MB (10^11 X 0.4) / (0.2 X 0.5MB + 0.6 X 32MB + 0.2 X 200MB) = 6억 8천만 개
Plain Text
복사

2. 청사진 그리기

객체 저장소의 몇 가지 속성
객체 저장소에 저장되는 객체는 수정이 불가능하다.
삭제 후 새버전으로 대체는 가능하지만 점진적 변경은 불가능
키-값 저장소를 이용해 객체에 접근할 수 있는 ID를 가져올 수 있다.
저장은 1회, 읽기는 여러번

2.1. 객체 업로드

업로드 워크플로우
생성된 메타데이터
PUT /bucket-to-share/script.txt HTTP/I.I Host: foo.s3example.org Date: Sun, 12 Sept 2021 17:51:00 GMT Authorization: [권한 문자열] Content-Type: text/plain Content-Length: 4567 x-amz-meta—author: Alex [객체 데이터 4567 바이트]
Plain Text
복사
객체 업로드 요청 전문

2.2. 객체 다운로드

다운로드 워크플로우
GET /bucket-to-share/script.txt HTTP/I.I Host: foo.s3example.org Date: Sun, 12 Sept 2021 18:30:01 GMT Authorization: [권한 문자열]
Plain Text
복사
다운로드 요청 전문

3. 상세설계

3.1. 데이터 라우팅 서비스

배치 서비스를 호출하여 데이터를 저장할 최적의 데이터 노드를 판단
데이터 노드에서 데이터를 읽어 API 서비스에 반환
데이터 노드에 데이터 기록

3.2. 배치 서비스

어느 데이터 노드에 데이터를 결정하는 역할을 담당
배치는 내부적으로 가상 클러스터 지도를 유지하는데, 클러스터의 물리적 형상 정보가 보관된다.
이 위치 정보를 활용해 데이터 사본이 물리적으로 다른 위치에 놓이도록 한다.
팩서스(Paxos), 래프트(Raft) 같은 합의 프로토콜을 사용해 구축을 권한다.

3.3. 데이터 저장 흐름

큰 흐름은 기록 아래와 같다.
요청 → UUID 할당 → 클러스터 확인 → 저장노드 결정 → 데이터/UUID 전송 → 데이터 저장 및 다중화 → 등록 UUID 반환
데이터 일관성을 높이면 응답성이 낮아진다 → 서로간의 trade off 관계다.
모든 노드에 저장이 완료된 후 알림을 응답을 줄것인가?
1번은 모두 저장되어야 응답준다.
2번은 부 데이터 1에만 저장되면 응답준다.
3은 메인 노드에 저장되면 바로 응답준다.
2, 3은 결과적 일관성의 한 형태로 볼 수 있다.

3.4. 데이터 저장

가장 단순한 저장방법 ⇒ 각각의 객체를 개별 파일로 저장
작은 파일이 많아지면 성능이 떨어짐
아이노드 용량 한계를 초과할 수 있음
작은 객체를 큰 파일로 모아서 해결한다.
WAL과 같이 이미 존재하는 파일에 추가하는 방식

3.5. 객체 소재 확인

객체의 소재를 파악하는 데 필요한 정보
객체가 보관된 데이터 파일
데이터 파일 내 객체 오프셋
객체의 크기
객체 소재를 찾는데는 적은 정보와 연산 속도를 요한다.
고로 RDB가 가장 적합하다.
파일형 데이터베이스인 SQLite 이용을 권한다.

3.6. 개선된 데이터 저장 흐름

3.7. 데이터 내구성

데이터 안정성은 아주아주 중요하다.
하드웨어 장애는 흔하게 발생하는데 이를 방지하는 방법은 독립적인 데이터 센터를 여러개 두어서 서로 데이터를 복제해두는 것이다.
최소 3중으로 다중화 해놓는다.
물리적 위치를 공유하지 않으면 극단전 상황에서도 가용성을 보장할 수 있다.
또 다른 방안으로는 소거코드를 이용하면 된다.
같은 크기의 단위로 분할하여 각 데이터를 수학 공식을 사용해 패리티 블록을 만든다.
이후 블록 소실 시 패리티 블록을 통해 데이터를 복구한다.
데이터 다중화 시 소거 코드 사용시 최대 8개의 노드에서 데이터를 가져와야 한다.
이는 소거 코드의 구조적 단점이다.
대규모 시스템은 메모리가 망가지는 경우도 자주 일어나는데 이때 체크섬을 통해서 해결할 수 있다.
체크섬 알고리즘을 통해서 작은 데이터 블록을 만든다.
이후 새로 계산한 체크섬과 달라지면 데이터가 망가진걸로 판단한다.
계산이 같다고 온전할 확률이 100%는 아니지만 아주 낮은 확률이기에 현실적으로는 대다수 같다.
체크섬 알고리즘은 MD5, SHA1, HMAC 등 다양하다.
각 객체 끝에 체크썸을 둔다.

3.8. 객체 버전

업로드 시 버저닝을 지원하며 기존 버전이 있을 경우 TIMEUUID값이 가장 큰 것이 최신버전이다.
삭제 마킹을 해두면 종전 버전이 현재 버전이 된다.

3.9. 멀티파트 업로드

객체를 작은 단위로 쪼개서 독립적으로 업로드 한다.
이후 업로드ID와 태그를 따라 재조립하는 과정을 멀티파트라 부른다.

3.10. 쓰레기 수집

앞서 멀티파트 업로드 후 더 이상 쓰이지 않는 지원을 회수하는 과정
다음의 경우 쓰레기가 생길 수 있음
객체의 지연된 삭제(lazy object deletion): 삭제했다고 표시는 하지만 실제로 지우지는 않는다.
갈 곳 없는 데이터(orphaned data): 반쯤 업로드된 데이터, 또는 취소된 멀티파트 업로드 데이터.
훼손된 데이터(corrupted data): 체크섬 검사에 실패한 데이터.