Foundry
안정 해시 설계
중급
핵심

나머지 연산의 한계

한 대 늘리는데 99퍼센트가 이사한다

앞 단계에서 이동량이 첫 제약이고, 담당은 물어보지 않고 계산으로 알아야 한다고 정했습니다. 계산으로 담당을 정하는 가장 단순한 방법부터 봅니다.

서버 수로 나눈 나머지

담당 서버 번호 = 해시(키) % 서버 수

좋은 점이 많습니다. 계산이 연산 두 번이라 0.1ms 예산에 여유가 크고, 해시가 고르면 분포도 고르며, 구현이 한 줄이고 들고 있을 상태가 서버 수 하나뿐입니다.

서버 수가 바뀌면 규칙 자체가 바뀐다

나머지 연산으로 담당을 정하면 서버 수가 바뀔 때 거의 모든 키의 담당이 바뀐다 3대일 때 4대로 늘리면 012 345 678 9 0 1 2 0 1 2 0 1 2 0 0 1 2 3 0 1 2 3 0 1 보라색 셋만 제자리다. 나머지는 담당이 바뀐다 담당이 값의 크기에 따라 규칙 없이 재배열된다 서버가 많아질수록 제자리는 줄어든다 100대에서 101대로 늘리면 약 1퍼센트만 남는다 한 대를 더했는데 10억 개 중 9억 9천만 개가 이사한다

문제는 나누는 수가 규칙의 일부라는 것입니다. 서버 수가 바뀌면 모든 키의 계산 결과가 함께 바뀝니다. 값이 조금 밀리는 것이 아니라 규칙 없이 재배열됩니다.

서버 수한 대 늘릴 때 제자리에 남는 키
3에서 4약 4분의 1
10에서 11약 11분의 1
100대 에서 101대약 1퍼센트

서버가 많아질수록 나빠집니다. 규모를 키우려고 서버를 늘리는데 늘릴수록 늘리기가 어려워지는 구조입니다.

요구사항과 대조하면 탈락한다

앞 단계에서 계산한 숫자를 그대로 씁니다. 담당이 99퍼센트 바뀌면 적중률이 거의 0으로 떨어지고 원본 요청이 20배가 됩니다. 적중률 95퍼센트 이상 유지라는 요구사항을 정면으로 어깁니다.

그리고 이 일이 주당 3~4번 일어납니다. 한 번이면 새벽에 감당할 수 있지만 매주라면 구조를 바꿔야 합니다.

그래도 이 방법이 맞는 경우

나머지 연산을 나쁜 방법으로 외우면 안 됩니다. 서버 수가 고정이거나, 담당이 바뀌어도 잃을 것이 없으면 이보다 단순하고 값싼 방법이 없습니다.

상황나머지 연산이
서버 수가 고정. 늘릴 계획이 없다충분하다. 더 정교한 방법은 과설계다
상태가 없는 계산을 나눠 준다충분하다. 담당이 바뀌어도 잃을 것이 없다
담긴 데이터가 있고 구성이 바뀐다무너진다. 이 요구사항이 그렇다

무엇을 담고 있는지가 판단을 가릅니다. 담당이 바뀔 때 잃는 것이 없다면 나머지 연산으로 충분합니다.

서버 수를 넉넉하게 잡아 두면 되지 않나

미리 1,000으로 나눠 두고 서버 100대가 각각 10개 조각을 맡는 방법이 있습니다. 조각 수는 고정이므로 나머지 규칙은 그대로이고, 서버가 늘면 조각의 담당만 옮깁니다.

이 방법은 실제로 쓰입니다. 다만 조각과 서버의 매핑 표를 누군가 관리하고 모두에게 알려야 하고, 처음 정한 조각 수가 상한이 됩니다. 조각 수를 늘리는 순간 다시 같은 문제로 돌아갑니다.

다음 단계에서 매핑 표 없이 같은 효과를 얻는 방법을 봅니다.

면접에서 이렇게 나옵니다

Q.해시 값을 서버 수로 나눈 나머지로 담당을 정하면 무엇이 문제인가요

나누는 수가 규칙의 일부라서, 서버 수가 바뀌면 모든 키의 계산 결과가 함께 바뀝니다.

서버 수한 대 늘릴 때 제자리에 남는 키
3에서 4약 4분의 1
100대 에서 101대약 1퍼센트

키 10억 개 중 9억 9천만 개가 담당이 바뀝니다. 값이 조금 밀리는 것이 아니라 규칙 없이 재배열됩니다.

그리고 서버가 많아질수록 나빠집니다. 규모를 키우려고 서버를 늘리는데 늘릴수록 늘리기 어려워지는 구조입니다.

흔한 실수: "서버 추가 시 재분배가 필요하다" 까지만 말하는 것. 재분배가 필요한 것과 거의 전부가 이동하는 것은 다른 이야기입니다. 비율을 숫자로 말하지 않으면 왜 다른 방법이 필요한지가 설명되지 않습니다.

Q.나머지 연산은 언제 써도 되나요

담당이 바뀔 때 잃을 것이 없으면 써도 됩니다. 오히려 그때는 가장 좋은 선택입니다.

상황나머지 연산이
서버 수가 고정충분하다. 더 정교한 방법은 과설계다
상태 없는 계산 분배충분하다. 담당이 바뀌어도 잃을 것이 없다
데이터를 담고 있고 구성이 바뀐다무너진다

계산이 연산 두 번이고 들고 있을 상태가 서버 수 하나뿐입니다. 이보다 값싼 방법은 없습니다.

흔한 실수: 나머지 연산을 나쁜 방법으로 외우고 어디서나 안정 해시를 쓰겠다고 답하는 것. 안정 해시는 링과 가상 노드와 구성원 목록 공유가 따라오는 구조입니다. 잃을 것이 없는 곳에 그 복잡도를 들이는 것은 과설계입니다.

Q.조각을 미리 많이 만들어 두는 방법은 어떤가요

실제로 쓰이는 방법입니다. 1,000개 조각으로 나눠 두고 서버 100대 가 각각 10개씩 맡습니다.

조각 수가 고정이므로 나머지 규칙은 변하지 않고, 서버가 늘면 조각의 담당만 옮깁니다. 이동하는 키는 옮긴 조각의 몫뿐입니다.

조각 번호 = 해시(키) % 1000
서버 = 조각 담당 표에서 찾는다

대가가 둘 있습니다. 조각과 서버의 매핑 표를 누군가 관리하고 모두에게 알려야 하고, 처음 정한 조각 수가 상한이 됩니다. 조각 수를 늘리는 순간 다시 같은 문제로 돌아갑니다.

흔한 실수: 조각 수를 서버 수의 몇 배 정도로 잡는 것. 나중에 서버를 크게 늘릴 여지를 없앱니다. 조각 수는 앞으로 도달할 최대 서버 수를 넉넉히 넘게 잡아야 하고, 그래서 처음 정할 때 신중해야 합니다.

Q.담당이 99퍼센트 바뀌면 실제로 어떤 일이 생기나요

적중률이 거의 0으로 떨어지고 원본 요청이 20배가 됩니다.

평소: 조회 50만 x 미스 5퍼센트 = 원본 요청 2.5만
직후: 원본 요청 50만

원본이 그 부하를 못 받으면 캐시를 채우는 것도 실패해서 회복이 더 늦어집니다. 적중률 95퍼센트 이상 유지라는 요구사항을 정면으로 어깁니다.

그리고 이 일이 주당 3~4번 일어납니다. 한 번이면 운영으로 감당하지만 매주라면 구조로 풀어야 합니다.

흔한 실수: 서버를 늘릴 때 미리 데이터를 옮겨 두면 된다고 답하는 것. 옮기려면 새 담당을 알아야 하는데, 나머지 규칙에서는 새 담당이 모든 키에 대해 새로 계산되므로 사실상 전체를 다시 채우는 것과 같습니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

안정 해시 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.