Foundry
분산 ID 생성기 설계
심화
핵심

칸을 나눠 쓰기

각 칸의 폭이 서로 다른 상한을 정한다

무작위를 쓰지 않고 유일성을 구조로 얻는 방법이 있습니다. 64비트 를 칸으로 나눠 각 칸이 다른 것을 담게 하는 것입니다.

세 칸으로 나눈다

64비트를 시각과 노드 번호와 순번으로 나누면 각 칸의 폭이 상한을 정한다 64비트를 칸으로 나눈다 시각 41비트 노드 10 순번 12 부호 1 각 칸이 정하는 상한 시각 41비트: 밀리초를 담아 약 69년. 수명 30년 요구를 넘는다 노드 10비트: 발급기 1,024대까지. 지금 64대에 여유가 크다 순번 12비트: 한 노드가 같은 밀리초에 4,096개까지 노드당 필요한 것은 초당 1,562개. 밀리초당 2개면 충분하다

같은 순간에 같은 값이 나올 수 없는 이유가 구조에 있습니다.

시각이 다르면 ID 가 다르다
시각이 같으면 노드 번호가 다르다
시각과 노드가 같으면 순번이 다르다

세 칸 중 하나라도 다르면 ID가 다릅니다. 확률이 아니라 규칙으로 유일성을 얻습니다. 그리고 시각이 맨 앞에 있으므로 값이 시간순으로 커집니다.

각 칸의 폭이 정하는 것

정하는 상한
시각41비트밀리초를 담아 약 69년
노드 번호10비트발급기 1,024대
순번12비트한 노드가 같은 밀리초에 4,096개

요구사항과 대조합니다. 수명 30년 는 69년 안에 들어오고, 발급기 64대 는 1,024대에 여유가 큽니다. 발급량 초당 10만 을 64대 로 나누면 노드당 초당 1,562개이므로 밀리초당 2개면 충분합니다.

어느 칸도 부족하지 않고, 남는 여유가 어디에 있는지도 분명합니다. 이렇게 대조하는 것이 폭을 정하는 방법입니다.

폭을 옮기면 무엇이 바뀌나

칸의 합이 정해져 있으므로 한 칸을 늘리면 다른 칸이 줄어듭니다.

바꾸면얻는 것잃는 것
시각을 줄인다노드나 순번이 늘어난다수명이 짧아진다
노드를 줄인다순번이 늘어난다발급기 대수 상한이 낮아진다
순번을 줄인다노드가 늘어난다밀리초당 발급량 상한이 낮아진다

이 표가 이 설계의 전부입니다. 요구사항의 숫자를 넣으면 폭이 정해지고, 폭을 정하면 상한이 정해집니다.

시각의 기준점을 옮긴다

시각을 1970년부터 세면 41비트가 이미 많이 소모돼 남은 수명이 짧습니다. 서비스를 시작한 날을 기준점으로 잡으면 41비트를 처음부터 쓸 수 있어 69년을 온전히 얻습니다.

기준점은 어딘가에 적어 두어야 합니다. 그것을 잃으면 ID에서 시각을 되돌릴 수 없고, 새 발급기가 다른 기준점을 쓰면 시간순 정렬이 어긋납니다.

순번이 넘칠 때

같은 밀리초에 4,096개를 넘게 요청하면 순번이 부족합니다. 그때 선택은 둘입니다.

선택결과
다음 밀리초까지 기다린다지연이 조금 늘고 유일성이 지켜진다
순번을 돌려 다시 쓴다중복이 생긴다

기다리는 쪽이 유일한 정답입니다. 유일성은 절대 포기하지 않는다고 정했기 때문입니다. 다만 그 대기가 예산 1ms 안에 있어야 하므로, 순번 칸을 넉넉히 두는 것이 대기를 드물게 만드는 방법입니다.

면접에서 이렇게 나옵니다

Q.칸을 나눠 쓰는 방식이 유일성을 어떻게 보장하나요

세 칸 중 하나라도 다르면 ID가 다릅니다. 확률이 아니라 규칙입니다.

시각이 다르면 ID 가 다르다
시각이 같으면 노드 번호가 다르다
시각과 노드가 같으면 순번이 다르다

노드 번호가 서로 겹치지 않는다는 전제만 지켜지면 중복이 원리적으로 불가능합니다. 그리고 시각이 맨 앞에 있으므로 값이 시간순으로 커집니다.

흔한 실수: 이 방식을 "무작위보다 충돌 확률이 낮다" 고 설명하는 것. 확률의 문제가 아닙니다. 구조로 막는 것과 확률로 막는 것의 차이를 말하는 것이 이 방식을 이해했다는 신호입니다.

Q.각 칸의 폭을 어떻게 정하시겠습니까

요구사항의 숫자와 대조해 정합니다.

정하는 상한요구사항
시각41비트약 69년수명 30년
노드10비트1,024대발급기 64대
순번12비트밀리초당 4,096개노드당 초당 1,562개

발급량 초당 10만 을 64대 로 나누면 노드당 초당 1,562개이므로 밀리초당 2개면 충분합니다. 어느 칸도 부족하지 않고 여유가 어디 있는지도 분명합니다.

흔한 실수: 관례적인 폭을 그대로 가져오는 것. 폭은 요구사항에서 계산해야 하고, 계산해 보면 노드 칸이나 순번 칸을 줄여 수명을 늘릴 여지가 보이기도 합니다.

Q.시각의 기준점을 어떻게 정하시겠습니까

서비스를 시작한 날로 잡습니다. 그러면 시각 칸을 처음부터 쓸 수 있습니다.

1970년부터 세면 41비트가 이미 많이 소모돼 남은 수명이 짧아집니다. 기준점을 옮기면 69년을 온전히 얻습니다.

기준점은 어딘가에 적어 두어야 한다
잃으면 ID 에서 시각을 되돌릴 수 없다

그리고 새 발급기가 다른 기준점을 쓰면 시간순 정렬이 어긋납니다. 같은 순간에 만든 ID가 서로 크게 다른 값이 됩니다.

흔한 실수: 기준점을 코드에 적어 두고 문서에 남기지 않는 것. ID 형식은 여러 서비스가 오래 쓰는 규약이라 코드보다 오래 살아남습니다. 형식과 기준점을 문서로 고정해야 합니다.

Q.같은 밀리초에 순번이 넘치면 어떻게 하나요

다음 밀리초까지 기다립니다. 순번을 돌려 쓰면 중복이 생깁니다.

선택결과
기다린다지연이 조금 늘고 유일성이 지켜진다
순번을 돌려 쓴다중복이 생긴다

유일성은 절대 포기하지 않는다고 정했으므로 기다리는 쪽이 유일한 답입니다. 최대 대기는 1밀리초 미만이라 지연 예산 안에 있습니다.

순번 칸을 넉넉히 두면 이 대기가 드물어집니다. 폭 배분이 대기 빈도를 정하는 값이기도 합니다.

흔한 실수: 순번이 넘칠 때 다른 노드 번호를 빌려 쓰는 것. 그 노드가 같은 밀리초에 같은 순번을 쓰고 있으면 중복이 생기고, 원인을 찾기가 매우 어렵습니다. 칸의 뜻을 지키는 것이 이 방식의 전제입니다.

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

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

분산 ID 생성기 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.