리더가 둘이었다 · 리더가 둘이었다 · 실습
떼어 놓고, 양쪽에 쓰고, 되돌린다
목표
세 노드 중 하나를 나머지에서 떼어 냈다가 되돌리면서, 같은 순간에 리더가 둘이 되는 상태와
그때 각 쪽에 쓴 값의 운명을 직접 봅니다.
왜 중요한가
분산 시스템의 사고는 대개 '장애' 가 아니라 불완전한 정보에서 옵니다. 떼어진 리더는
자기가 떼어졌다는 것을 모릅니다. 그가 아는 것은 '요즘 응답이 안 온다' 뿐이고, Raft 의 리더에게는
스스로 물러나는 장치가 없습니다. 그래서 그는 계속 리더처럼 행동하고, 클라이언트의 값을 받고,
ok 를 돌려줍니다. 같은 순간 반대편에서는 과반이 모여 더 높은 임기의 새 리더를 뽑습니다.
이때 리더는 정말로 둘입니다. Raft 가 막는 것은 리더가 둘인 상태가 아니라 같은 임기에 리더가
둘인 상태이고, 소수 쪽 리더는 과반의 확인을 받을 수 없으므로 아무것도 확정하지 못합니다.
회복되는 순간 그의 미확정 항목은 조용히 사라집니다. 이 실습이 남기는 질문은 하나입니다 —
그 사이에 ok 를 받아 간 클라이언트는 어떻게 되는가.
단계
1. 세 파일을 /root/raft/ 에 놓고 세 노드를 띄워 /root/raft/leader.json 에 적습니다.
2. /root/raft/net.py 에 should_deliver(src, dst, cut) 를 씁니다.
3. 값 alpha 를 써서 확정하고 /root/raft/before.json 에 적습니다.
4. 리더와 나머지 둘이 서로를 끊게 하고 /root/raft/isolated.json 에 적습니다.
5. 새 리더가 뽑히기를 기다려 /root/raft/two-leaders.json 에 적습니다.
6. 옛 리더에게 ghost 를 쓰고 /root/raft/minority.json 에 적습니다.
7. 새 리더에게 real 을 쓰고 /root/raft/majority.json 에 적습니다.
8. 끊기를 풀고 결과를 /root/raft/verdict.json 에 적습니다.
참고
- 끊기:
curl -s -XPOST -d '{"peers":[2,3]}' 127.0.0.1:5001/cut - 풀기:
curl -s -XPOST -d '{"peers":[]}' 127.0.0.1:5001/cut - 로그 보기:
curl -s 127.0.0.1:5001/log - 흔한 실수 1: 한쪽에만 끊기를 거는 것. 반대 방향이 살아 있으면 분할이 아닙니다.
- 흔한 실수 2: 새 리더가 뽑히기 전에 서둘러 읽는 것. 선거에는 타임아웃만큼의 시간이 필요합니다.
단계 8개
- 세 노드를 세운다
- 선을 끊는 대신 메시지를 거부한다
- 분할 전에 값 하나를 확정한다
- 리더를 떼어 놓는다
- 같은 순간에 리더가 둘이다
- 소수 쪽에 쓴 값
- 과반 쪽에 쓴 값
- 회복 - 무엇이 버려지는가