5장. 안정 해시 설계

2025. 6. 30. 17:10·📝 끄적끄적/📖 가상 면접 사례로 배우는 대규모 시스템 설계 기초

수평적 규모 확장성(scale out)을 달성하기 위해서는 클라이언트로부터의 요청이나 데이터를 서버에 균등하게 나누는 것이 중요하다.


안정 해시는 이 목표를 달성하기 위해 보편적으로 사용하는 기술이다.
안정 해시에 대해서 알기 전에 우선 이러한 해시 기술이 어떠한 문제를 해결하려고 하는지 좀 더 자세히 살펴보자

먼저, 해시란?

안정 해시에 대해서 알아보기 전에 간략하게 해시에 대해서 짚어보자.

 

해시의 사전적 의미는 '임의 길이의 데이터 문자열을 입력으로 받아서 고정 크기의 출력, 일반적으로는 숫자와 문자열로 이루어진 해시 값 또는 해시 코드를 생성하는 수학적 함수'이다.

 

쉽게 풀어 이야기하면 같은 문자열 입력은 항상 같은 해시 코드를 반환한다는 것이다. 해시의 이런 특성을 이용하여 암호화나 파일의 위변조 판정 등 다양한 용도로 사용된다.

해시 키 재배치(rehash) 문제

N개의 캐시 서버가 있다고 하자. 이 서버들에 부하를 균등하게 나누는 보편적 방법은 아래의 해시 함수를 사용하는 것이다.

 

severIndex = hash(key) % N (N은 서버의 개수)

 

총 4대의 서버를 사용하는 예제를 통해 동작 원리를 알아보자.

키 해시 해시%4(서버 인덱스)
key0 18358617 1
key1 26143584 0
key2 18131146 2
key3 35863496 0
key4 34085809 1
key5 27581703 3
key6 38164978 2
key7 22530351 3

 

특정한 키가 보관된 서버를 알아내기 위해, 나머지(modular) 연산을 f(key)%4와 같이 적용하였다.

예를 들어 hash(key0) % 4 = 1이면, 클라이언트는 캐시에 보관된 데이터를 가져오기 위해 서버 1에 접속하여야 한다.
다음 그림은 본 예제에서 키 값이 서버에 어떻게 분산되는지 보여준다.

 


이 방법은 서버 풀(server pool)의 크기가 고정되어 있을 때, 그리고 데이터 분포가 균등할 때는 잘 동작한다.

하지만 서버가 추가되거나 기존 서버가 삭제되면 문제가 생긴다.

 

예를 들어 1번 서버가 장애를 일으켜 동작을 중단했다고 하자.
그러면 서버 풀의 크기는 3으로 변한다.
그 결과로, 키에 대한 해시 값은 변하지 않지만 modular 연산을 적용하여 계산한 서버 인덱스 값은 달라질 것이다.

서버 수가 1만큼 줄어들어서이다.
따라서 다음과 같은 결과를 얻는다. 해시 % 3의 결과 값이다.

키 해시 해시%4(서버 인덱스)
key0 18358617 0
key1 26143584 0
key2 18131146 1
key3 35863496 2
key4 34085809 1
key5 27581703 0
key6 38164978 1
key7 22530351 0

이어서 변화된 키 분포(distribution)이다.

 

위 그림에 보인 대로, 장애가 발생한 1번 서버에 보관되어 있는 키뿐만 아닌 대부분의 키가 재분배되었다.
1번 서버가 죽으면 대부분 캐시 클라이언트가 데이터가 없는 엉뚱한 서버에 접속하게 된다는 뜻이다.
그 결과로 대규모 캐시 미스(cache miss)가 발생하게 될 것이다.
안정 해시는 이 문제를 효과적으로 해결하는 기술이다.

안정 해시

안정 해시(Consistent Hashing)란 분산되어 있는 서버 혹은 서비스에 데이터를 균등하게 나누기 위한 기술이다.

 

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

k는 키의 개수이고, n은 슬롯의 개수이다.
이와는 달리 대부분의 전통적 해시 테이블은 슬롯의 수가 바뀌면 거의 대부분 키를 재배치한다.

 

해시 공간과 해시 링

안정 해시의 동작 원리를 살펴보자. 해시 함수 f로는 SHA-1을 사용한다고 하고, 그 함수의 출렬 값 범위는 x0, x1,... xn과 같다고 하자. SHA-1의 해시 공간 범위는 0부터 (2^160) - 1까지라고 알려져 있다. 따라서 x0는 0, xn은 (2^160) - 1이며, 나머지 x1부터 xn-1까지는 그 사이의 값을 갖게 될 것이다. 다음 그림은 해시 공간을 그림으로 표현한 것이다.


이 해시 공간의 양쪽을 구부려 잡으면 다음과 같은 해시 링이 만들어진다.

 

해시 서버

이 해시 함수 f를 사용하면 서버 IP나 이름을 이 링 위의 어떤 위치에 대응시킬 수 있다.
다음 그림은 4개의 서버를 이 해시 링 위에 배치한 결과이다.

 

해시 키

여기 사용된 해시 함수는 "해시 키 재배치 문제"에 언급된 함수와는 다르며, modular 연산 %는 사용하지 않고 있다.

다음 그림과 같이 캐시할 키 key0, key1, key2, key3 또한 해시 링 위의 어느 지점에 배치할 수 있다.

 

서버 조회

어떤 키가 저장되는 서버는, 해당 키의 위치로부터 시계 방향으로 링을 탐색해 나가면서 만나는 첫 번째 서버다. 다음 그림을 살펴보자

key0은 서버 0에 저장되고, key1은 서버 1에 저장되며, key2는 서버 2, key3는 서버 3에 저장된다.

 

서버 추가

윗 내용에 이어서 서버를 추가하더라도 키 가운데 일부만 재배치하면 된다.


위의 그림을 살펴보자.
새로운 서버 4가 추가된 뒤에 key0 만 재배치됨을 알 수 있다. k1, k2, k3은 같은 서버에 남는다.
이유는 다음과 같다.
서버 4가 추가되기 전, key0은 서버 0에 저장되어 있었다.
하지만 서버 4가 추가된 뒤에 key0의 위치에서 시계 방향으로 순회했을 때 처음으로 만나게 되는 서버가 서버 4이기 때문에 key0 만 재배치된다.

 

서버 제거

하나의 서버가 제거되면 키 가운데 일부만 재배치된다.
다음 그림을 보면 서버 1이 삭제되었을 때 key1만이 서버 2로 재배치됨을 알 수 있다.
나머지 키는 영향이 없다.

 

기본 구현법의 두 가지 문제

안정 해시 알고리즘은 MIT에서 처음 제안되었다고 한다. 그 기본 절차는 다음과 같다.

  • 서버와 키를 균등 분포(uniform distribution) 해시 함수를 사용해 해시 링에 배치한다.
  • 키의 위치에서 링을 시계 방향으로 탐색하다 만나는 최초의 서버가 키가 저장될 서버다.

이 접근법에는 두 가지 문제가 있다.

  1. 서버가 추가되거나 삭제되는 상황을 감안하면 파티션의 크기를 균등하게 유지하는 게 불가능하다.
    • 여기서 파티션은 인접한 서버 사이의 해시 공간이다. 어떤 서버는 굉장히 작은 해시 공간을 할당받고, 어떤 서버는 굉장히 큰 해시 공간을 할당받는 상황이 가능하다는 것이다.
    • 다음 그림은 서버 1이 삭제되는 바람에 서버 2의 파티션이 다른 파티션 대비 거의 두 배로 커지는 상황을 보여준다.

  1. 키의 균등 분포(uniform distribution)를 달성하기가 어렵다는 것이다.

  • 위 그림에서, 서버 1과 서버 3은 아무 데이터도 갖지 않는 반면, 대부분의 키는 서버 2에 보관될 것이다.

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

 

가상 노드

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

 

해시 공간은 유한하다. 그러므로 해시 공간에 배치된 노드 수가 굉장히 많다면 표준편차가 감소하여 노드 하나가 없어진다 하더라도 다음 노드에 큰 부하는 가지 않을 것이다.

문제는 현실 세계에서 물리 노드의 수는 곧 비용이라는 점이다.

 

그래서 물리 노드(Physical node)를 모방하는 가상 노드(Virtual node)를 구현하여 이를 영리하게 해결한다.

위 그림을 살펴보면, 서버 0과 서버 1은 3개의 가상 노드를 갖는다.

 

여기서 숫자 3은 임의로 정한 것이며, 실제 시스템에서는 그보다 훨씬 큰 값이 사용된다.

서버 0을 링에 배치하기 위해 s0 하나만 쓰는 대신에 s0_0, s0_1, s0_2의 세 개 가상 노드를 사용했다. 서버 1도 마찬가지다. 따라서 각 서버는 하나가 아닌 여러 개 파티션을 관리해야 한다.

 

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

k0이 저장되는 서버는 k0의 위치로부터 링을 시계방향으로 탐색하다 만나는 최초의 가상 노드 s1_1가 나타내는 서버, 즉 서버 1이다.

가상 노드의 개수를 늘리면 키의 분포는 점점 더 균등해진다. 표준 편차(standard deviation)가 작아져서 데이터가 고르게 분포되기 때문이다. 표준 편차는 데이터가 어떻게 퍼져 나갔는지를 보이는 척도다.
가상 노드의 개수를 더 늘리면 표준 편차의 값은 떨어지지만 가상 노드 데이터를 저장할 공간은 더 많이 필요하게 될 것이다. 그러니 시스템 요구사항에 맞도록 가상 노드 개수를 적절히 조정해야 한다.

 

재배치할 키 결정

서버가 추가되거나 제거되면 데이터 일부는 재배치해야 한다. 어느 범위의 키들이 재배치되어야 할까?
그림으로 예를 들어보자.


서버 4가 추가되었다고 해 보자.

 

이에 영향 받은 범위는 s4(새로 추가된 노드)부터 그 반시계 방향에 있는 첫 번째 서버 s3까지이다.
즉 s3부터 s4 사이에 있는 키들을 s4로 재배치하여야 한다.

마치며

안정 해시의 이점은 요약해 보자면 다음과 같다.

  • 서버가 추가되거나 삭제될 때 재배치되는 키의 수가 최소화된다.
  • 데이터가 보다 균등하게 분포하게 되므로 수평적 규모 확장성을 달성하기 쉽다.
  • 핫스폿(hotspot) 키 문제를 줄인다. 특정한 샤드에 대한 접근이 지나치게 빈번하면 서버 과부하 문제가 생기지만, 안정 해시는 데이터를 좀 더 균등하게 분배하므로 이런 문제가 생길 가능성을 줄인다.

안정 해시는 실제로 널리 쓰이는 기술이다. 그중 유명한 사례를 살펴보면 다음과 같다.

  • Amazon DynamoDB의 파티셔닝 관련 컴포넌트
  • Apache Cassandra 클러스터에서의 데이터 파티셔닝
  • 디스코드 채팅 어플리케이션
  • 아카마이 CDN
  • meglev 네트워크 부하 분산기

 

 

 

 

그림 및 참고
https://velog.io/@minu/5%EC%9E%A5.-%EC%95%88%EC%A0%95-%ED%95%B4%EC%8B%9C-%EC%84%A4%EA%B3%84
안정 해시 이해하기 굉장히 좋은 블로그

저작자표시 비영리 (새창열림)

'📝 끄적끄적 > 📖 가상 면접 사례로 배우는 대규모 시스템 설계 기초' 카테고리의 다른 글

8장. URL 단축기 설계  (0) 2025.07.14
7장. 분산 시스템을 위한 유일 ID 생성기 설계  (0) 2025.07.01
6장. 키-값 저장소 설계  (0) 2025.07.01
4장. 처리율 제한 장치의 설계  (0) 2025.06.30
3장. 시스템 설계 면접 공략법  (0) 2025.06.05
2장. 개략적인 규모 추정  (0) 2025.06.04
'📝 끄적끄적/📖 가상 면접 사례로 배우는 대규모 시스템 설계 기초' 카테고리의 다른 글
  • 7장. 분산 시스템을 위한 유일 ID 생성기 설계
  • 6장. 키-값 저장소 설계
  • 4장. 처리율 제한 장치의 설계
  • 3장. 시스템 설계 면접 공략법
현주먹
현주먹
대구 불주먹 출신 현주먹의 개발.log
  • 현주먹
    현주먹의 개발로그
    현주먹
  • 전체
    오늘
    어제
    • 전체글 (179)
      • 👶🏻 CS (15)
        • Operating System (7)
        • DB (5)
        • Data Structure (2)
        • Software Engineering (1)
      • 💻 Dev (54)
        • Java & OOP (24)
        • Spring (4)
        • DB&JPA (6)
        • Test Code (1)
        • JSP & Servlet (13)
        • Etc (6)
      • 💡 Algorithm (25)
        • 인프런 (9)
        • 백준 (16)
      • 🛠 DevOps & Tool (11)
        • Linux (4)
        • AWS (1)
        • Git (2)
        • Etc (4)
      • 📝 끄적끄적 (74)
        • 후기 및 회고 (11)
        • TDD, 클린 코드 with Java 17기 (3)
        • F-Lab (23)
        • 🖥️ 자바의 정석 (11)
        • 📖 Clean Code (3)
        • 항해99 코테 스터디 (11)
        • 📖 가상 면접 사례로 배우는 대규모 시스템 설계 .. (11)
  • 블로그 메뉴

    • 🐈‍⬛ GitHub
    • TIL repository
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 태그

    객체지향
    인프런 특정문자뒤집기
    F-Lab
    개구리책
    jsp 2.3 웹 프로그래밍: 기초부터 중급까지
    오라클
    로또 미션
    코딩테스트준비
    ==와 equals()
    백준
    C
    NextSTEP
    개발자취업
    항해99
    자바의신절판
    에프랩
    f-lab 후기
    오블완
    자바의정석
    티스토리챌린지
    2025스프링캠프
    jsp
    JPA
    til
    에프랩 후기
    99클럽
    TDD 클린 코드 with Java
    코테스터디
    개발자멘토링
    데브클럽
  • hELLO· Designed By정상우.v4.10.2
현주먹
5장. 안정 해시 설계
상단으로

티스토리툴바