수평적 규모 확장성을 달성하기 위해서는 요청 또는 데이터를 서버에 균등하게 나누는 것이 중요하다. 안정 해시는 이 목표를 달성하기 위해 보편적으로 사용되는 기술이다.
N개의 캐시 서버가 있다고 하자. 아래의 해시 함수를 사용하여 서버의 부하를 균등하게 나누어보자.
serverIndex = hash(key) % N
위의 해시 함수를 적용하면 키 값이 다음과 같이 서버에 분산된다.
해시 키 재배치
하지만 서버가 추가되거나 기존 서버가 삭제되면 문제가 생긴다. 예를 들어 서버 1이 중단되었다고 하면, 해시 키가 재분배된다.
전통적인 해시 테이블은 슬롯(N) 수가 바뀌면 대부분의 키를 재배치한다.
안정 해시를 통해 해시 테이블의 재배치 문제를 해결할 수 있다.
안정 해시(consistent hash)는 해시 테이블 크기가 조정될 때 평균적으로 오직 k/n
개의 키만 재배치하는 해시 기술이다. (k
: 키의 개수, n
: 슬롯 수).
안정 해시의 동작 원리에 대해 알아보자.
x0
, x1
, x2
, … , xn
위의 해시 공간을 구부려서 해시 링을 만든다. x0
과 xn
은 끝 지점에서 서로 맞닿아 있다.
해시 함수 f를 사용하여 서버 IP나 이름을 링 위에 배치시킬 수 있다. 마찬가지로 캐시할 키 k0
, k1
, k2
, k3
또한 해시 링 위의 임의의 지점에 배치할 수 있다.
%
연산은 사용하지 않고 있음에 유의어떤 키가 저장되는 서버는, 해당 키의 위치로부터 시계 방향으로 링을 탐색해 나가면서 만나는 첫 번째 서버이다.
따라서 서버가 추가된 경우, 키 가운데 일부만 재배치하면 된다.
s4
서버가 k0
과 s0
사이에 추가되었다고 가정k0
기준 시계방향으로 가장 가까운 서버가 s4
로 바뀌었으므로, s4
로 재배치s3
~s4
마찬가지로 서버가 제거될 때도 일부 키만 재배치된다.
s1
이 삭제되었다고 가정k1
기준 시계방향으로 가장 가까운 서버가 s2
로 바뀌었으므로, s2
로 재배치s0
~s2
살펴본 안정 해시 알고리즘은 다음과 같다.
하지만 해당 접근법은 두 가지 문제점을 가진다.
문제점
s1
서버가 삭제되면, s2
서버는 다른 서버에 비해 훨씬 큰 해시 공간을 가지게 됨s2
에 저장될 것이며, s3
에는 아무 키도 보관되지 않을 것위의 문제를 해결하기 위해 제안된 기법이 가상 노드(또는 복제, replica) 기법이다.
가상 노드는 실제 서버를 가리키는 노드로서, 하나의 서버는 링 위에 여러 개의 가상 노드를 가질 수 있다.
Open image-20250106-161509.png
s1
, s2
가 존재하며, 각 서버는 3개의 가상 노드(sx_0
, sx_1
, sx_2
)를 가진다고 가정k0
의 경우 시계방향으로 가장 가까운 s1_1
에 저장됨특징
안정 해시 도입 시 이점
안정해시 사례
다른 안정 해시 알고리즘
def jump_consistent_hash(key, num_buckets):
key = hash(key) # 64-bit hash
b, j = -1, 0
while j < num_buckets:
b = j
key = ((key * 2862933555777941757) & 0xFFFFFFFFFFFFFFFF) + 1 # 해시 업데이트
j = int((b + 1) * (1 << 31) / ((key >> 33) + 1)) # 1/N으로 확률이 점점 감소
return b