본문 바로가기
C.W.K.
Stream
Lesson 02 of 04 · published

받아들이기 전엔 안 끝나

~12 min · completion, durability, idempotency, core-rule

Level 0Empty Shelf
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"control plane 이 durably 받아들이기 전엔 계산이 안 끝나."

시스템에서 가장 중요한 한 문장

Recall 의 분산 설계는 전부 규칙 하나로 압축돼. executor 는 transcript 계산을 끝낼 수 있어. 함수가 return 했고, 파일이 디스크에 있고, 로그에도 성공이라고 찍혀. 근데 그 어느 것도 job 이 완료됐다는 뜻은 아냐. 완료는 일을 한 기계가 아니라 진실의 원천이 가진 속성이거든. job 은 control plane 이 결과를 받아들였다고 durably 기록했을 때, 오직 그때만 끝나.

왜 이렇게까지 엄격하냐고? 'executor 가 끝냈다' 와 'control plane 이 안다' 사이에는 네트워크가 있고, 네트워크는 실패하거든. executor 가 완벽한 결과를 계산하고 나서 보고하기 전에 연결을 잃을 수도 있어. 그걸 '완료' 라고 부르면 진실이랑 실제 일이 조용히 어긋나. executor 는 끝났다고 여기고, DB 는 job 이 아직 pending 이라고 여기고. 최악의 버그는 그 틈에서 살아.

끝내는 건 값싸고, 수락은 durable 해

그래서 executor 가 느끼는 로컬 '완료' 는 사실이 아니라 제안으로 다뤄. 결과를 계산하고, control plane 에 제출하고, control plane 이 검증한 다음 상태 전이를 한 번의 atomic DB write 로 커밋해. 그 커밋만이 완료야. return 한 함수는 소문이고, 커밋된 전이는 진실이야.

이 규칙 하나가 전부를 버티게 만들어. executor 가 계산을 끝내고 보고하기 전에 죽으면, control plane 은 수락을 본 적이 없으니까 lease 가 만료되고 job 이 queue 로 돌아가서 다시 돌아. control plane 이 커밋한 다음에 죽으면 job 은 진짜로 끝난 거라 다시 안 돌고. 중요한 순간은 durable 커밋 하나뿐이고, 그건 진실을 소유하는 호스트에서 일어나.

replay 는 안전해야 해

미묘한 경우가 하나 있어. executor 가 계산하고 control plane 이 커밋했는데, executor 로 돌아가는 확인(ack)이 중간에 유실되면? executor 는 성공한 걸 모르니까 재시도하고, 같은 결과가 두 번 도착해. 시스템은 그걸 무해하게 만들어야 해. Recall 은 identity 로 그걸 해결해. 이미 받아들인 결과를 다시 제출하면 중복을 만드는 대신 기존 record 를 돌려주거든. 수락이 idempotent 하니까 재시도는 언제나 안전해. 거기다 control plane 은 재시작할 때 크래시가 중간에 남겨둔 job 을 화해(reconcile) 시켜. 수락은 한 번, replay 는 안전하게, 시작할 때 치유하기. 이 세 가지가 불안정한 네트워크를 사이에 두고도 두 호스트가 서로 정직하게 남는 방법이야.

Code

return 은 소문, 커밋은 진실·python
# 틀림: executor 가 완료를 결정
result = transcribe(chunk)
return result            # 함수가 return 했어... 그래서?
                         # 여기서 크래시나면 진실은 영영 못 배워

# 맞음: 완료는 control plane 에 산다
result = transcribe(chunk)
ack = control_plane.submit_result(job_id, lease_token, result)
# control_plane 이 atomic 전이 하나를 커밋한 뒤 확인해준다.
# 이 호출이 유실되면 executor 가 재시도하고, 이미 받아들인
# 결과의 재제출은 기존 행을 돌려준다 (idempotent).
# job 은 DB 가 그렇다고 해서만 완료다.

External links

Exercise

네 코드에서 백그라운드 작업이 스스로 완료를 표시하는 데를 찾아봐. 플래그를 세우거나, 성공을 return 하거나, 파일을 쓰거나. 이제 일이 끝난 한 줄 뒤, '완료' 가 권위 있는 어딘가에 durably 기록되기 전에 프로세스가 죽었다고 상상해. 재시작하면 어떻게 돼? 일이 다시 돌아, 조용히 사라져, 아니면 중복돼? 진실의 소유자가 durably 받아들였을 때만 완료로 치도록, 그리고 재시도해도 안전하도록 다시 써봐.
Hint
두 가지를 물어봐. 첫째, '완료' 가 실제로 어디에 durably 기록돼? 그리고 worker 가 그 record 를 소유해, 아니면 제안만 해? 둘째, 확인이 유실돼서 같은 결과가 두 번 제출되면 두 번째 제출이 중복을 만들어, 아니면 기존 걸 돌려줘? 중복이 생길 수 있으면 identity key 를 넣어서 수락을 idempotent 하게 만들어.

Progress

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

댓글 0

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

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