키-값 저장소는 기능이 두 개뿐입니다. 값을 넣고 꺼내는 것입니다. 기능이 단순한 만큼 설계는 비기능 요구사항이 전부 정합니다.
| 항목 | 값 |
|---|---|
| 대상 | 분산 키-값 저장소 |
| 데이터 | 100TB |
| 노드 | 300대 |
| 쓰기 | 초당 10만 |
| 읽기 | 초당 50만 |
| 값 크기 | 평균 1KB |
| 읽기 지연 | 상위 1퍼센트가 10ms 이내 |
| 분단이 생기면 | 쓰기를 계속 받는다 |
| 견뎌야 하는 장애 | 노드 두 대가 동시에 죽어도 데이터가 남는다 |
| 응답한 쓰기 | 노드가 죽어도 사라지지 않는다 |
기능 요구사항과 범위 밖
| 구분 | 내용 |
|---|---|
| 이번에 만든다 | 키로 값 넣기, 키로 값 꺼내기, 사본 유지, 노드 추가와 제거 |
| 범위 밖 | 여러 키를 묶는 트랜잭션, 키 범위 조회, 값 내용 검색, 두 번째 인덱스, 서버가 두 값 중 최신을 골라 주는 것 |
범위 밖이 이 설계에서 특히 중요합니다. 여러 키를 묶는 트랜잭션을 빼면 노드 사이 합의가 필요 없어지고, 그것이 아래의 모든 선택을 가능하게 합니다. 하나만 남겨 두었다면 설계가 완전히 달라집니다.
분단 중에 쓰기를 받는다는 결정
네트워크가 갈라졌을 때 쓰기를 계속 받으려면 양쪽이 각자 받아야 합니다. 리더가 한쪽에 있으면 반대쪽 사용자는 쓰기를 할 수 없습니다.
그래서 이 요구사항은 리더가 없는 구조를 강제합니다. 어느 사본이든 쓰기를 받을 수 있고, 사본끼리 나중에 맞춥니다.
낸 값이 있습니다. 같은 키에 서로 다른 값이 생길 수 있고, 그것을 정리하는 일이 새 숙제가 됩니다. 고른 것과 낸 값을 함께 말하는 것이 이 결정을 설명하는 방법입니다.
숫자가 정하는 것
| 조건 | 강제하는 것 |
|---|---|
| 100TB 를 300대 에 | 키를 나눠 담아야 한다. 나누는 방법은 안정 해시 설계에서 다뤘다 |
| 쓰기 초당 10만, 값 평균 1KB | 초당 100MB. 제자리를 찾아 고치는 방식은 디스크가 못 따라온다 |
| 두 대 동시 사망 견디기 | 사본이 셋 이상이어야 한다 |
| 응답한 쓰기 유실 불가 | 응답하기 전에 디스크에 남겨야 한다 |
| 읽기 10ms | 값을 찾느라 파일 여러 개를 뒤지는 비용을 줄여야 한다 |
사본이 셋인 이유
두 대가 동시에 죽어도 데이터가 남으려면 사본이 셋 이상이어야 합니다. 둘이면 두 대가 함께 죽을 때 그 데이터가 사라집니다.
셋보다 많이 두면 저장 비용이 그만큼 늘어납니다. 100TB 에 사본 셋이면 실제로 저장하는 양은 300TB 입니다. 요구사항이 두 대까지라고 정했으므로 셋에서 멈춥니다.
이 저장소가 하지 않는 것
리더가 없으므로 "가장 최근 값" 을 아무도 확정해 주지 않습니다. 읽는 쪽이 낡은 값을 볼 수 있고, 두 값이 함께 반환될 수도 있습니다.
이 성질을 응용에 알려야 합니다. 잔액이나 재고처럼 정확한 순서가 필요한 데이터는 이 저장소에 두지 않는 편이 낫습니다. 무엇을 담을 수 있는 저장소인지가 요구사항에서 이미 정해집니다.