From ef0971de374f793c4200cf2dda03b5a96087aa1f Mon Sep 17 00:00:00 2001 From: lim-jaein Date: Sat, 4 Jul 2026 09:55:29 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch05-consistent-hashing/week1.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ch05-consistent-hashing/week1.md b/ch05-consistent-hashing/week1.md index c804886..ea8908d 100644 --- a/ch05-consistent-hashing/week1.md +++ b/ch05-consistent-hashing/week1.md @@ -32,7 +32,6 @@ SHA-1 기준 해시 공간은 `0 ~ 2¹⁶⁰-1` 의 범위를 가진다. | | 일반 해시 | 안정 해시 | | --- | --- | --- | -| **서버 결정 방식** `serverIndex` | hash(key) % N | 링에서 hash(key) 기준 시계 방향 첫 번째 서버 | | **저장 공간** | 가변: 0 ~ N-1 | 고정: 0 ~ 2¹⁶⁰-1 | | **서버 변경 시** | 저장 공간 전체 재정의 → 대부분 키 영향 | 저장 공간 고정 → 근처 키만 영향 | From 815d5b42326f9277231209293360053a71c66496 Mon Sep 17 00:00:00 2001 From: lim-jaein Date: Tue, 7 Jul 2026 08:39:48 +0900 Subject: [PATCH 2/2] =?UTF-8?q?ch06=20week2=20=EC=9E=84=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch05-consistent-hashing/week1.md | 5 + ch06-key-value-store/week2.md | 181 ++++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 1 deletion(-) diff --git a/ch05-consistent-hashing/week1.md b/ch05-consistent-hashing/week1.md index ea8908d..d7fef46 100644 --- a/ch05-consistent-hashing/week1.md +++ b/ch05-consistent-hashing/week1.md @@ -129,6 +129,11 @@ Strategy 2에 아래 조건을 추가했다. - 부하가 가장 균등해짐 (Strategy 1/2/3 중 로드밸런싱 효율 1위) - 각 노드가 유지해야 할 정보가 Strategy 1 대비 **1000배 감소** +## 2주차에 보완해야할 점 +- Strategy3을 최종 채택했을 때, 서버별 스펙이 다른 경우 유연한 설계가 불가하다. +- Stratedy3 + 유연성을 설계한데도 더 좋은 방법이 있을 수 있다. +- 메타데이터의 트레이드오프를 고려했을때, 가상노드 개수는 어떻게 설정해야하나? + ## 참고 자료 - [Amazon Dynamo 논문 원문 (Cornell CS5414)](https://www.cs.cornell.edu/courses/cs5414/2017fa/papers/dynamo.pdf) diff --git a/ch06-key-value-store/week2.md b/ch06-key-value-store/week2.md index 23bd7a4..adb9703 100644 --- a/ch06-key-value-store/week2.md +++ b/ch06-key-value-store/week2.md @@ -84,4 +84,183 @@ Q. 근데 중재자가 선택되는 방식이 단순 첫번째로 고정되는 | 쓰기 가용성 | 별도 항목 없음 | 낮은 W(quorum)로 일부 응답만으로 성공 처리 | | 요청 처리 흐름 | 명시 안 됨 | 코디네이터(중재자) 개념 도입, GET/PUT 단계별 동작 정의 | | 데이터 일관성이 깨질 수 있는 시나리오 | "모르겠음" | 벡터 시계 비교 + R/W quorum(R+W>N) 조합으로 해결됨을 확인 | -| 장애 복구 방식 | "재분배" (모호) | 일시/영구 장애 구분, 영구 장애 시 머클 트리로 차이만 동기화 | \ No newline at end of file +| 장애 복구 방식 | "재분배" (모호) | 일시/영구 장애 구분, 영구 장애 시 머클 트리로 차이만 동기화 | + +--- + +## 5. 확장성 설계 구체화: 안정 해시 + 가상노드 실체화 + +1주차/2주차에서 "안정 해시 + 가상노드 도입"이라고 적었던 부분을 실제 동작 수준으로 풀어낸다. + +### 해시 링 구현 + +링은 **정렬된 맵(TreeMap)**으로 구현한다. + +``` +Key : 가상노드의 해시값 (SHA-1 기준 0 ~ 2¹⁶⁰-1) +Value : 해당 가상노드가 속한 실제 서버 ID +``` + +서버 등록 시 V개의 가상노드를 생성한다: + +``` +hash("서버A#0"), hash("서버A#1"), ..., hash("서버A#V-1") +``` + +**키 → 서버 조회**: `hash(key)` 이상의 가장 가까운 값을 TreeMap에서 ceiling 탐색 → O(log(N×V)) + +### 서버 스펙별 가상노드 수 차등 부여 + +서버마다 스펙이 다른 경우, 가상노드 수를 가중치에 비례하게 설정한다. (ch05 week2 참고) + +``` +서버별 가상노드 수 = 기본_V × (서버_가중치 / 평균_가중치) +``` + +이 방식으로 **균등 파티션 분배(Strategy 3) + 서버 스펙 반영(유연성)** 을 동시에 달성한다. + +### 서버 추가/삭제 시 재배치 범위 + +**서버 추가** +- 새 서버의 V개 가상노드를 링에 삽입 +- 각 삽입 지점 기준으로 반시계 방향 이전 가상노드까지의 범위 중 일부만 이전 + +**서버 삭제 / 장애** +- 해당 서버의 V개 가상노드를 링에서 제거 +- 각 제거 지점의 시계 방향 다음 서버가 해당 범위를 인수 +- V개로 분산되어 있으므로 부하가 단일 서버가 아닌 **여러 서버로 고르게** 나뉨 + +### 복제(Replication)와의 관계 + +N개 복제를 위해 링에서 시계 방향으로 N개의 **실제 서버**를 찾아야 한다. + +가상노드 사용 시 시계 방향으로 N개를 찾으면 같은 물리 서버가 중복될 수 있어 중복 제거가 필요하다. + +``` +복제 대상 서버 목록 = [] +링에서 hash(key)부터 시계 방향 순회: + if 현재 가상노드의 실제 서버가 목록에 없으면: + 목록에 추가 + if 목록 크기 == N: + 종료 +``` + +또한 복제 서버는 가능하면 **물리적으로 다른 랙/데이터센터**에 있어야 한다. +→ 가상노드 순회 시 랙 정보도 체크해서 같은 랙이면 건너뛰는 방식으로 구현 가능 + +### 코디네이터 서버 선택 + +GET/PUT 동작에서 "중재자(첫 번째 서버)"가 코디네이터 역할을 한다. + +- 링에서 `hash(key)` 기준 시계 방향 첫 번째 실제 서버 = 코디네이터 +- 코디네이터가 나머지 N-1개 복제 서버에 데이터를 전파 +- 코디네이터 자체도 데이터를 갖는 N개 중 하나 + +### 링 메타데이터 관리 + +해시 링 정보는 모든 서버가 동일하게 알아야 한다. + +| 방식 | 특징 | 단점 | +| --- | --- | --- | +| 중앙 설정 서버 (ZooKeeper 등) | 일관성 보장, 구현 단순 | SPOF 위험, 추가 인프라 필요 | +| 가십 프로토콜 (분산 동기화) | SPOF 없음, Amazon Dynamo 방식 | 동기화 지연으로 일시적 불일치 가능 | + +**채택: 가십 프로토콜** +- 각 서버는 주기적으로 일부 다른 서버에 현재 멤버십 정보를 전파 +- 서버 추가/삭제 이벤트가 전체 클러스터에 퍼지는 데 수 초~수십 초 소요 +- 이 기간 동안 잘못된 서버로 라우팅될 수 있음 → 해당 서버가 데이터를 모르면 올바른 서버로 포워딩하거나 클라이언트가 재시도 + +--- + +## 6. Fixed Hash Slot 방식과 비교 + +ch05 week2에서 확장성 요구사항을 만족하는 실무 방식으로 Virtual Node와 Fixed Hash Slot 두 가지를 다뤘다. 이 키-값 저장소 설계에 각각 적용했을 때 어떻게 동작하는지 비교한다. + +### Fixed Hash Slot 적용 시 + +해시 공간을 고정된 16,384개 슬롯으로 나누고, 각 서버가 연속된 슬롯 범위를 담당한다. + +**슬롯-서버 매핑 예시** +``` +슬롯 0 ~ 5460 → 서버 A +슬롯 5461 ~ 10922 → 서버 B +슬롯 10923 ~ 16383 → 서버 C +``` + +**키 → 슬롯 조회**: `slot = CRC16(key) % 16384` → O(1) + +**서버 추가 시** +- 기존 서버들에서 슬롯 일부를 새 서버로 명시적 이전 +- 이전 중인 슬롯의 키 요청은 MOVED 응답으로 올바른 서버로 리다이렉트 + +**서버 삭제 시** +- 해당 서버의 슬롯을 다른 서버로 모두 이전 완료 후 제거 + +**복제 구현**: 슬롯 범위 단위로 master-replica 구조 지정 + +### Virtual Node vs Fixed Hash Slot 비교 + +| 항목 | Virtual Node (Dynamo) | Fixed Hash Slot (Redis) | +| --- | --- | --- | +| 키 → 서버 조회 | O(log N×V), TreeMap ceiling 탐색 | O(1), CRC16 % 16384 | +| 서버 추가/삭제 | 링에서 가상노드 즉시 삽입/제거 | 슬롯 이전 후 추가/제거 | +| 재배치 자동화 | ✅ 자동 | 조율 필요 (명시적 이전) | +| N개 복제 구현 | 링 순회로 N개 실제 서버 탐색 | 슬롯 범위 단위 master-replica | +| 이기종 서버 가중치 | ✅ 가상노드 수 조절 | ✅ 슬롯 수 조절 | +| 슬롯 이전 중 가용성 | 일시 불일치 가능 | MOVED 리다이렉트로 처리 | +| 운영 복잡도 | 높음 | 낮음 | + +### 이 설계에서의 선택: Virtual Node + +- **자동 스케일링**: 링에 가상노드를 삽입/제거하는 것만으로 재배치가 자동 처리됨. Fixed Hash Slot은 슬롯 이전을 별도로 조율해야 해서 자동화가 더 복잡함 +- **N개 복제 + 가십 프로토콜 조합**: 링 순회로 복제 서버를 동적으로 탐색하는 방식이 가십 기반 멤버십 관리와 자연스럽게 맞음. Fixed Hash Slot은 슬롯 범위 단위 복제 구조가 고정되어 있어 유연성이 낮음 +- **이기종 서버**: 둘 다 지원하지만 Virtual Node는 가상노드 수 하나만 조절하면 됨 + +--- + +## 7. 범위 기반 파티셔닝과 비교 + +ch05 week2에서 해시 공간 없이도 동작하는 세 번째 방식으로 범위 기반 파티셔닝을 다뤘다. 이 키-값 저장소 설계에 적용했을 때 어떻게 동작하는지 비교한다. + +### 범위 기반 파티셔닝 적용 시 + +키를 해시하지 않고 키 값의 정렬 순서로 공간을 나눠 서버에 배분한다. + +**범위-서버 매핑 예시** +``` +"a" ~ "h" → 서버 A +"i" ~ "p" → 서버 B +"q" ~ "z" → 서버 C +``` + +**키 → 서버 조회**: 중앙 메타데이터 서버에서 키가 속하는 범위를 조회 → 서버 결정 + +**서버 추가 시** +- 부하가 높은 범위를 분할해 새 서버에 일부 이전 +- 메타데이터 서버가 분할 결과를 반영 + +**서버 삭제 시** +- 해당 서버의 범위를 인접 서버에 병합 +- 메타데이터 서버가 병합 결과를 반영 + +**핫스팟 자동 대응**: 특정 범위에 요청이 집중되면 그 범위를 더 잘게 분할해 여러 서버로 분산 + +**복제 구현**: 각 범위에 N개 복제본을 메타데이터 서버가 직접 관리 + +### 세 방식 최종 비교 + +| 항목 | Virtual Node (Dynamo) | Fixed Hash Slot (Redis) | Range-based (HBase 등) | +| --- | --- | --- | --- | +| 키 → 서버 조회 | 로컬 계산, O(log N×V) | 로컬 계산, O(1) | 메타데이터 서버 조회 필요 | +| 중앙 라우팅 서버 | ❌ 불필요 | ❌ 불필요 | ✅ 필요 | +| SPOF 위험 | 없음 | 없음 | 메타데이터 서버가 SPOF | +| 서버 추가/삭제 | 링 삽입/제거 (자동) | 슬롯 이전 (조율 필요) | 범위 분할/병합 (자동 가능) | +| 핫스팟 자동 분산 | 제한적 (가상노드 수 조절) | 제한적 (슬롯 수 조절) | ✅ 범위 자동 분할 | +| 범위 쿼리 지원 | ❌ 해시로 순서 파괴 | ❌ 해시로 순서 파괴 | ✅ 자연스럽게 지원 | +| 운영 복잡도 | 중간 | 낮음 | 높음 | + +### 이 설계에서 범위 기반을 선택하지 않는 이유 + +- 이 키-값 저장소의 키는 순서 의미가 없는 임의 키이므로 범위 쿼리 지원 이점이 없음 +- 중앙 메타데이터 서버가 생기면 SPOF가 되어 가용성 요구사항에 위배 +- 메타데이터 서버 조회가 매 요청마다 추가되면 지연시간 요구사항에 불리함 \ No newline at end of file