<대규모 시스템 설계 기초> "5장 안정 해시 설계"를 읽고 작성하는 포스트 입니다.
안정 해시(Consistent Hash)
는 일반적으로 요청 또는 데이터를 서버에 균등하게 나누기
위해 일반적으로 사용되는 기술이다.
전통적인 Hash Table의 경우 모듈로(%) 연산을 이용한다
ex) serverIndex = hash(key) % N (N은 서버의 개수)
이 경우 적용하려는 대상(서버 또는 데이터)의 갯수가 고정
되어 있는 경우 문제가 없지만, 해당 대상이 추가 되거나 삭제 되는 등의 변동이 있는 경우, 대부분의 해시 대상이 재분배
된다. 따라서 확장성(scalability)
에 취약하다
해시 키 재배치란, 책에 나온 예를 들자면 Key 8개와 서버 4대가 있을 때 Key는 2개씩 0, 1, 2, 3에 할당되어 있지만 서버 1대가 장애가 나는 경우 서버 대수(위 수식의 N)
를 기반으로 해싱하기에 모두 새로 해싱되어 해시 키가 재배치(Rehash) 된다. 이 경우 장애가 발생한 서버에 보관된 키를 제대로 찾지 못해서 대규모 Cache Miss가 발생하게 된다.
이런 해시테이블과 다르게 안정 해시는 해시 테이블 크기가 조정될 때 평균적으로 Key/N(위의 서버 수와 동일)
의 키만 재배치하도록 하는 해시 기술이다.
안정 해시는 전통적 해시 테이블과 다르게 모듈로 연산(%)
으로 대상을 탐색하지 않으며, Hash Ring을 만들어 링 위에서 첫번째 만나는 것을 대상으로 한다.
1, 2, 3, 4의 서버가 있을 때 A의 대상 서버는 2이다.
위와 같은 구조일 때 서버 2에 장애가 난다면 A는 2가 아닌 3 서버에 재배치될 것이다.
이 해시의 문제점은 균등 분포 해시 함수를 사용해도 해시 파티션(partition) (위 그림의 링 위의 서버 사이의 간격) 의 크기를 균등하게 유지하는게 불가능
하다는 것과 이로 인해 키가 균등하게 분포되기 어렵다
는 문제가 있다.
이를 해결 하기 위해 가상노드(Virtual Node)
or 복제(Replica)
라 불리는 기법을 사용한다
하나의 서버
는 링 위에서 여러 개의 가상 노드
를 가지게 된다. (우측 그림)
따라서 안정 해시는 탐색 후 첫번째 만나는 서버를 대상으로 하므로, 가상 노드가 없는 좌측 그림의 구조와 달리 가상 노드가 많을 수록 키의 분포가 균등하게 된다.
가상 노드의 개수를 늘릴 수록 표준 편차의 값은 떨어지지만 가상 노드 데이터를 저장할 공간은 더 많이 필요하므로 시스템의 요구사항에 맞는 적절한 수치가 필요하다.
읽다보니 주 스택으로 사용하는 Java에서의 Hash는 어떻게 구현되어 있나 궁금함이 생겨 검색해보니 아래의 글이 나왔다.
또, 책 내에서 참고 문헌으로 든 Discord의 Scaling 사례가 있다.
좋은 글 감사합니다. 🙏
그나저나 discord scaling 링크가 이걸로 바뀐거같네요~
https://discord.com/blog/how-discord-scaled-elixir-to-5-000-000-concurrent-users