Skip to content

Commit

Permalink
Merge pull request #22 from yeslee-v/21-5장-안정-해시-설계
Browse files Browse the repository at this point in the history
5장 안정 해시 설계
  • Loading branch information
yeslee-v authored Jan 27, 2024
2 parents e349fe0 + d6e5c79 commit f9489e0
Showing 1 changed file with 135 additions and 0 deletions.
135 changes: 135 additions & 0 deletions System_Design_Interview/5장_안정_해시_설계.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# 안정 해시 설계

- 수평적 규모 확장성, 요청 또는 데이터를 서버에 균등하게 나누기 위해 사용한다.

> 안정 해시가 필요한 이유와 어떻게 동작하는지 살펴본다.
## TL;DR

- 서버가 추가되거나 삭제될 때 재배치되는 키의 수가 최소화된다.

- 데이터가 균등하게 분포하게 되므로 수평적 규모 확장성을 달성하기 쉽다.

- 핫스팟(hotspot) 키 문제를 줄인다.

- 특정한 샤드(shard)에 대한 접근이 지나치게 빈번하면 서버 과부하문제가 발생할 수 있는데, 안정해시는 데이터를 좀 더 균등하게 분배하므로 이런 문제의 발생 가능성을 줄인다.

## 해시 키 재배치(rehash) 문제

```bash
# N: 서버 갯수
serverIndex = hash(key) % N
```

- 서버 풀(server pool)의 크기가 고정되어 있고 데이터 분포가 균등할 때 잘 동작한다.

- 서버 갯수에 변동(추가 또는 삭제)이 생기면 문제가 된다.

- 키에 대한 해시 값은 변하지 않지만 나머지(%) 연산을 적용하여 서버 인덱스 값이 달라진다.

- 대부분의 캐시 클라이언트가 데이터가 없는 엉뚱한 서버에 접속하게 되면서 대규모 캐시 미스(cache miss)가 발생한다. -> 안정 해시

## 안정 해시

- 해시 테이블 크기가 조정될 때 평균적으로 오직 k/n개의 키만 재배치하는 해시 기술이다.

- k는 키의 갯수, n은 슬롯(slot)의 개수다.

- 대부분의 전통적인 해시 테이블은 슬롯의 수가 바뀌면 거의 대부분 키를 재배치 한다.

### 해시 공간과 해시 링

- 해시 함수 f는 SHA-1을 사용하고, 함수의 출력 값 범위는 x0, x1, ... xn으로 가정한다.

> SHA-1(Secure Hash Algorithm 1)?
>
> 입력받은 값을 160비트 해시값으로 만드는 암호화 해시 함수이다.
>
> SHA-1의 해시 공간(hash space) 범위는 0 ~ 2^160-1이다.
- 해시 공간의 양쪽을 구부려 접으면 해시 링(hash ring)이 만들어진다.

### 해시 서버

- 해시 함수 f를 사용하면 서버 IP나 이름을 이 링 위의 한 위치에 대응시킬 수 있다.

### 해시 키

> 해시 키 재배치 문제에서 언급한 함수와 다르며, 나머지(modular) 연산 %는 사용하지 않는다.
- 캐시할 키 key0, key1 또한 해시 링 위의 어느 지점에 배치할 수 있다.

### 서버 조회

- 한 키가 저장되는 서버는 해당 키의 위치로부터 시계 방향으로 링을 탐색해 나가면서 만나는 첫번째 서버다.

### 서버 추가

- 서버를 추가하더라도 키 가운데 일부만 재배치하면 되므로 다른 키들은 재배치되지 않는다.

### 서버 제거

- 하나의 서버가 제거되면 키 가운데 일부만 재배치되고, 나머지 키에는 영향이 없다.

### 기본 구현법의 두 가지 문제

- 안정 해시 알고리즘은 MIT에서 처음 제안되었다.

- 서버와 키를 균등 분포(uniform distribution) 해시 함수를 사용하여 해시 링에 배치한다.

- 키의 위치에서 링을 시계 방향으로 탐색하다 만나는 최초의 서버가 키가 저장될 서버이다.

- 이 접근법에는 다음과 같은 문제가 있다.

- 서버가 추가되거나 삭제되는 상황을 감안하면, 파티션의 크기가 균등하게 유지하는게 불가능하다.

> 파티션(partition)? 인접한 서버 사이의 해시 공간.
- 어떤 서버는 굉장히 작은 해시 공간을 할당 받고, 어떤 서버는 굉장히 큰 해시 공간을 할당받게 된다.

- 키의 균등 분포(uniform distribution)를 달성하기 어렵다.

- 이 문제를 해결하기 위해 제안된 기법이 가상 노드(virtual node) 또는 복제(replica) 기법이다.

### 가상 노드(virtual node)

- 실제 노드 또는 서버를 가리키는 노드로 하나의 서버는 링 위에 여러 개의 가상 노드를 가질 수 있다.

- 각 서버는 하나가 아닌 여러 개의 파티션을 관리해야 한다.

- 키의 위치로부터 시계방향으로 링을 탐색하다 만나는 최초의 가상 노드가 해당 키를 저장될 서버가 된다.

- 가상 노드 개수를 늘릴수록 표준 편차(standard deviation)이 작아져 데이터가 고르게 분포되면서 키의 분포는 균등해진다.

> 표준 편차는 데이터가 어떻게 퍼져 나갔는지를 보이는 척도다.
- 가상 노드 개수를 늘릴수록 표준 편차의 값은 더 떨어지지만, 가상 노드 데이터를 저장할 공간은 더 많이 필요해진다.

- 가상 노드 개수와 표준 편차 사이의 타협적 결정(tradeoff)가 필요하다.

### 재배치할 키 결정

- 서버가 추가 혹은 제거되면 데이터 일부는 재배치해야 한다.

- 서버가 추가됐을 때 그 영향을 받는 범위는 새로 추가된 노드부터 그 반시계 방향에 있는 첫번째 서버까지다.

## 마치며

- 안정 해시는 아마존, 아파치, 디스코드 등에서 사용할 정도로 실제로 널리 쓰이는 기술이다.

## 참고문헌

- [Consistent hashing](https://en.wikipedia.org/wiki/Consistent_hashing)

- [Consistent Hashing](https://tom-e-white.com/2007/11/consistent-hashing.html)

- [Dynamo: amazon's highly available key-value store](https://dl.acm.org/doi/10.1145/1323293.1294281)

- [Cassandra - A Decentralized Structured Storage System](https://www.cs.cornell.edu/projects/ladis2009/papers/lakshman-ladis2009.pdf)

- [How Discord Scaled Elixir to 5,000,000 Concurrent Users](https://discord.com/blog/how-discord-scaled-elixir-to-5-000-000-concurrent-users)

- [CS168: The Modern Algorithmic Toolbox
Lecture #1: Introduction and Consistent Hashing](https://theory.stanford.edu/~tim/s16/l/l1.pdf)

- [Maglev: A Fast and Reliable Software Network Load Balancer](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44824.pdf)

0 comments on commit f9489e0

Please sign in to comment.