본문 바로가기
C.W.K.
Stream
Lesson 03 of 05 · published

중복 없이 재시도해

~12 min · idempotency, retry, deduplication, failure

Level 0마른 펜촉
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"전달은 반복돼도 의도한 효과는 하나로 지켜."

의도한 효과 하나를 정해

네트워크는 자기를 반복해. 탭이 두 번 전달되고 timeout이 성공을 가리고, worker가 output을 쓴 뒤 acknowledge 전에 재시작할 수 있어. 재시도는 정상이고 중복 효과가 버그야.

같은 durable 행을 재시도해

현재 Inkwell은 실패한 durable job의 같은 행을 queued로 돌려 재시도해. guarded update는 queued, running, done이면 아무것도 바꾸지 않으니 retry 명령이 반복돼도 새 job을 만들지 않아.

재시도와 새 요청을 섞지 마

재시도를 전부 새 job으로 보면 경쟁하는 번역이 생겨. 음성은 on-demand라 durable job이 아니야. 원문이 바뀌면 pending review를 supersede하지 retry 명령 안에 두 번째 정체성을 숨기지 않아.

운영 불변식. 전달은 반복돼도 의도한 효과는 하나로 지켜.

crash를 시간선에 넣어

이 설계는 평온한 demo가 아니라 아무 순간에 process가 사라지는 시간선에서 시험해야 해. 수락 전, commit 뒤, claim 뒤, 외부 호출 뒤, 결과 저장 뒤에 각각 crash를 놓고 database가 무엇을 말하는지 적어. 사용자가 같은 요청을 다시 보내도 돈과 문장이 두 번 생기지 않아야 해.

직접 설계해

failed job을 queued로 돌린 직후 client timeout이 난 경우의 반복 retry를 설계해. status와 timestamp, attempt 행을 같이 써. 복구 script가 추측으로 행을 덮지 않고 어떤 증거로 전환하는지 설명해.

관찰 가능성이 복구 가능성이야

운영자가 SQL 한 번으로 queued, running, failed, done을 구분하고 다음 안전 행동을 알 수 있어야 해. 알 수 없는 침묵을 queue라고 부르면 기다림은 이미 데이터를 잃은 거야.

운영 증거를 남겨

같은 failed job에 retry가 반복돼도 guarded update의 승자는 한 번뿐이야. 뒤 요청은 이미 queued인 같은 job id와 status를 읽어 돌려줘.

느린 외부 호출은 transaction 밖에 두고, claim과 완료만 짧고 atomic하게 만들어. 그래야 기다림이 database 전체를 잠그지 않아.

Code

논리 요청의 유일성을 강제해·sql
UPDATE jobs
SET status = 'queued',
    error = NULL,
    started_at = NULL,
    finished_at = NULL
WHERE id = :job_id AND status = 'failed';

SELECT id, status, error
FROM jobs
WHERE id = :job_id;
-- Repeating this command reuses the same durable job row.

External links

Exercise

서버가 commit한 뒤 client timeout이 난 경우의 재시도 처리를 설계해.
Hint
crash 위치를 하나씩 옮겨가며 데이터가 남는지 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.