Foundry
분산 ID 생성기 설계
고급
핵심

시계가 뒤로 갈 때

중복이 생기는 유일한 경로다

칸을 나눠 쓰는 방식은 유일성을 구조로 보장합니다. 단 전제가 둘 있습니다. 노드 번호가 겹치지 않는 것과, 시각이 뒤로 가지 않는 것입니다. 이 절은 뒤쪽 전제를 다룹니다.

시계는 실제로 뒤로 간다

원인상황
시각 동기화 보정시계가 앞서 있었으면 뒤로 당긴다
가상 머신 정지와 복귀멈춘 동안 시각이 어긋난다
사람의 수동 변경운영 중 실수로 바꾼다

드문 일이지만 반드시 일어납니다. 노드 64대 를 수년 운영하면 겪습니다.

뒤로 가면 무엇이 잘못되나

시계가 뒤로 가면 이미 발급한 시각 구간을 다시 써서 중복이 생길 수 있다 시각 칸이 지나온 구간 이미 발급에 쓴 시각 지금 시계가 뒤로 가면 이 구간을 다시 쓴다 그 시각의 순번이 아직 안 쓴 값이면 괜찮다 이미 쓴 순번과 겹치면 중복이다. 되돌릴 방법이 없다

시각이 ID의 일부이므로 시계가 뒤로 가면 이미 발급에 쓴 시각 구간을 다시 씁니다. 그 시각의 순번이 아직 쓰지 않은 값이면 우연히 괜찮지만, 이미 쓴 순번과 겹치면 같은 ID가 두 번 나옵니다.

중복은 되돌릴 방법이 없습니다. 두 데이터가 하나로 취급되고, 그 사실을 나중에 알아채기도 어렵습니다.

마지막으로 쓴 시각을 기억한다

대응의 출발점은 하나입니다. 자기가 발급에 쓴 가장 큰 시각을 들고 있는 것입니다. 새 발급에서 현재 시각이 그보다 작으면 되돌림을 감지합니다.

되돌린 폭대응
몇 밀리초따라잡을 때까지 기다린다
그보다 크면발급을 거부하고 경보를 올린다

거부가 맞는 이유는 요구사항에 있습니다. 유일성은 절대 포기하지 않는다고 정했습니다. 발급 실패는 재시도로 회복되지만 중복은 회복되지 않습니다. 회복 가능한 실패를 골라야 합니다.

재시작하면 기억이 사라진다

프로세스가 다시 뜨면 마지막 시각 기억이 없습니다. 그때 시계가 뒤로 가 있으면 감지하지 못합니다.

마지막으로 쓴 시각을 주기적으로 디스크나 외부에 남긴다
재시작할 때 그 값을 읽어 비교한다

남기는 주기가 곧 보호 범위입니다. 1초마다 남기면 최악의 경우 1초분을 놓칩니다. 쓰기 비용과 보호 범위의 균형점으로 정합니다.

순서 문제와 구분한다

시계를 순서의 근거로 쓰면 안 된다는 이야기는 다른 곳에서도 나옵니다. 그런데 문제의 성질이 다릅니다.

상황시계가 틀리면
시계로 순서를 정할 때순서가 뒤바뀐다. 보이는 결과가 어색하다
시계가 ID 의 일부일 때중복이 생긴다. 데이터가 섞인다

같은 원인이 훨씬 나쁜 결과를 만듭니다. 그래서 여기서는 시계를 감시 대상으로 두고 발급 경로에서 직접 검사합니다.

면접에서 이렇게 나옵니다

Q.시계가 뒤로 가면 무엇이 잘못되나요

이미 발급에 쓴 시각 구간을 다시 쓰게 되고, 순번이 겹치면 중복이 생깁니다.

시각이 ID의 일부이므로 같은 시각을 두 번 쓰면 남은 칸이 노드 번호와 순번뿐입니다. 노드 번호는 같으니 순번이 겹치는 순간 같은 ID가 나옵니다.

그 시각의 순번이 아직 안 쓴 값이면 우연히 괜찮다
이미 쓴 순번과 겹치면 중복이다

중복은 되돌릴 방법이 없습니다. 두 데이터가 하나로 취급되고 발견도 늦습니다.

흔한 실수: 시계 되돌림을 드문 일로 보고 대응을 생략하는 것. 시각 동기화 보정과 가상 머신 복귀로 실제로 일어나고, 노드 수가 많고 수년을 운영하면 반드시 겪습니다.

Q.시계 되돌림을 어떻게 다루시겠습니까

자기가 쓴 가장 큰 시각을 기억하고, 현재 시각이 그보다 작으면 대응합니다.

되돌린 폭대응
몇 밀리초따라잡을 때까지 기다린다
그보다 크면발급을 거부하고 경보를 올린다

거부가 맞는 이유는 요구사항입니다. 유일성은 절대 포기하지 않는다고 정했고, 발급 실패는 재시도로 회복되지만 중복은 회복되지 않습니다.

회복 가능한 실패를 고르는 것이 이런 선택의 일반 원칙입니다.

흔한 실수: 되돌림을 감지하고 그냥 진행하는 것. 로그만 남기고 발급을 계속하면 가장 나쁜 결과를 조용히 만듭니다. 감지했으면 멈춰야 합니다.

Q.재시작하면 마지막 시각 기억이 사라지지 않나요

사라집니다. 그래서 주기적으로 밖에 남깁니다.

마지막으로 쓴 시각을 디스크나 외부 저장소에 주기적으로 남긴다
재시작할 때 그 값을 읽어 현재 시각과 비교한다

남기는 주기가 곧 보호 범위입니다. 1초마다 남기면 최악의 경우 1초분을 놓치므로, 그 구간에서 시계가 뒤로 가 있으면 감지하지 못합니다.

쓰기 비용과 보호 범위의 균형점으로 정합니다. 발급량이 많으면 매 발급마다 남길 수 없습니다.

흔한 실수: 재시작 직후를 안전하다고 보는 것. 오히려 가장 위험한 순간입니다. 기억이 비어 있고, 재시작의 원인이 시각 문제였을 수도 있습니다. 시작할 때 한 번은 반드시 확인해야 합니다.

Q.시계를 순서의 근거로 쓰는 문제와 어떻게 다른가요

결과의 무게가 다릅니다.

상황시계가 틀리면
시계로 순서를 정할 때순서가 뒤바뀐다. 보이는 결과가 어색하다
시계가 ID 의 일부일 때중복이 생긴다. 데이터가 섞인다

순서가 뒤바뀌는 것은 화면을 다시 정렬하면 되지만, 중복은 두 데이터가 하나로 합쳐지는 문제라 복구가 불가능합니다.

그래서 ID 생성기에서는 시계를 감시 대상으로 두고 발급 경로에서 직접 검사합니다.

흔한 실수: 두 문제를 같은 대응으로 다루는 것. 순서 문제는 서버가 붙이는 번호로 우회할 수 있지만, ID 생성기에서는 시계 자체가 입력이라 우회할 대상이 없습니다. 검사와 거부가 유일한 방법입니다.

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

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

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