리더가 둘이었다 · 받은 것과 확정한 것 · 실습
과반이 받아야 커밋이다
목표
리더가 받은 값이 어떻게 세 노드로 퍼지고, 어느 순간 '확정' 되는지를 규칙으로 씁니다.
끝나면 로그 일치성, 덮어쓰기, 커밋 조건, 그리고 뒤처진 노드가 따라잡는 과정을 손으로 겪은 상태가 됩니다.
왜 중요한가
복제는 '값을 여러 곳에 보낸다' 가 아닙니다. 보낸 것과 확정한 것을 구분하는 일입니다.
리더가 값을 받아 자기 로그에 적었다는 사실은 아무것도 보장하지 않습니다 — 그 리더가 다음 순간
죽으면 그 값은 없던 일이 될 수 있습니다. 과반이 같은 자리에 같은 항목을 갖고 있어야 비로소
'어떤 미래의 리더도 이 자리를 바꿀 수 없다' 가 성립하고, 그때서야 클라이언트에게 성공이라고
말할 수 있습니다.
커밋 조건에는 사람들이 거의 항상 빠뜨리는 단서가 하나 더 붙습니다 — 리더는 자기 임기의 항목이
과반에 닿았을 때만 커밋 번호를 올립니다. 앞 임기의 항목이 과반에 닿았다는 이유로 커밋하면,
그 뒤에 뽑힌 다른 리더가 같은 자리를 덮어써서 이미 확정했다고 말한 값이 사라질 수 있습니다.
단계
1. node.py 와 rules-for-replication.py 를 제자리에 놓고 리더를 뽑아 /root/raft/leader.json 에 적습니다.
2. raftrules.py 에 up_to_date 를 더하고 on_request_vote 가 그 조건을 함께 보게 합니다.
3. /root/raft/raftlog.py 에 append_entry(log, term, value) 를 씁니다.
4. 같은 파일에 log_ok(log, prev_index, prev_term) 을 더합니다.
5. 같은 파일에 apply_entries(log, prev_index, entries) 를 더합니다.
6. 같은 파일에 commit_index(counts, total, log, term) 을 더합니다.
7. 값 세 개를 써서 세 노드가 모두 커밋하는 것을 보고 /root/raft/replicated.json 에 적습니다.
8. 팔로워 하나를 죽였다 되살려 따라잡는 것을 보고 /root/raft/catchup.json 에 적습니다.
참고
- 이 실습은 60분 안팎이 걸립니다. 세션 시간이 모자라면 화면에서 연장하세요. 실습 파드에는
- 값 쓰기:
curl -s -XPOST -d '{"value":"x"}' 127.0.0.1:5001/client - 로그 보기:
curl -s 127.0.0.1:5001/log - 상태 보기:
curl -s 127.0.0.1:5001/status(commit 과 log_len 을 함께 보세요) - 흔한 실수 1: 항목이 없는 심장박동에도 로그를 자르는 것. 어긋날 때만 자릅니다.
- 흔한 실수 2: 넘겨받은 로그 목록을 그 자리에서 고치는 것. 새 목록을 만들어 돌려주세요.
볼륨이 없어서 세션이 끝나면 /root 의 작업물이 사라집니다 — 남기고 싶은 코드는 따로 복사해 두세요.
단계 8개
- 앞 실습의 결과를 다시 세운다
- 뒤처진 후보에게는 표를 주지 않는다
- 클라이언트 값이 로그에 붙는다
- 로그 일치성
- 어긋나는 자리부터 잘라 낸다
- 커밋 조건
- 세 노드에 값을 쓴다
- 되살아난 노드가 따라잡는다