세 서버가 같은 상태를 복제하고 있는데 기존 리더와의 연결이 끊겼다고 하자. 남은 서버는 새 리더를 뽑아야 한다. 하지만 기존 리더가 실제로 죽은 것이 아니라 네트워크만 갈라졌다면 양쪽에서 리더가 생길 수 있다.
합의(consensus: 여러 서버가 장애와 메시지 지연이 있어도 하나의 값이나 작업 순서에 동의하도록 만드는 규칙)는 서버가 모두 같은 순간에 같은 화면을 보는 기능이 아니다. 어떤 제안을 확정된 것으로 인정할지와 새 리더가 이전 결정을 어떻게 이어 갈지를 정한다.
실패와 지연을 완전히 구분할 수는 없다
서버 A가 B의 응답을 받지 못했을 때 B가 죽었을 수도 있고 네트워크가 느릴 수도 있고 A 쪽 연결만 끊겼을 수도 있다.
A ──?── B
관찰 가능한 사실: 제한 시간 안에 응답이 없음
알 수 없는 사실: B가 실제로 종료됐는지, 답이 늦는지
장애 감지(failure detection: 응답 시간과 연결 상태를 보고 다른 서버가 사용할 수 없다고 추정하는 과정)는 확정 판정이 아니라 시간 기준의 의심이다. 그래서 리더를 바꾸는 규칙은 잘못된 의심이 생겨도 두 리더의 변경이 동시에 확정되지 않게 해야 한다.
정족수는 겹치는 다수의 확인을 요구한다
정족수(quorum: 결정을 인정하는 데 필요한 서버 응답 수)는 보통 전체의 과반을 사용한다. 세 서버라면 두 대, 다섯 서버라면 세 대다.
서버 3대: 과반 = 2
분할 2대 쪽 → 과반 확보 가능
분할 1대 쪽 → 혼자서는 새 결정을 확정할 수 없음
두 과반 집합은 적어도 한 서버가 겹친다. 이 겹침이 서로 다른 두 결정이 같은 로그 위치에서 모두 확정되는 일을 막는 핵심이 된다.
서버 수를 늘리면 장애 허용 수가 자동으로 크게 늘지는 않는다. 과반을 유지해야 하므로 세 대는 한 대, 다섯 대는 두 대 장애를 견딜 수 있다. 통신과 저장 확인 비용도 함께 늘어난다.
임기는 오래된 리더의 메시지를 구분한다
임기(term: 리더 선출 시도와 리더 기간을 구분하는 단조 증가 번호)는 서버가 자신보다 오래된 선출과 메시지를 거절하게 한다.
term 4: 서버 A가 리더
네트워크 분리
term 5: 서버 B가 새 리더로 선출
A의 term 4 메시지가 도착
→ B와 다른 서버는 오래된 임기로 판단해 거절
서버는 더 큰 임기를 보면 자신의 역할을 낮추고 새 상태를 따른다. 시간 시계보다 논리적 임기 번호를 사용하는 이유는 각 서버의 시계가 정확히 같지 않아도 순서를 비교할 수 있기 때문이다.
리더 후보는 과반의 표를 받아야 한다
리더 선출(leader election: 현재 임기에서 로그 복제를 이끌 서버 하나를 고르는 과정)은 보통 일정 시간 동안 리더 신호를 받지 못한 서버가 후보가 되면서 시작한다.
후보는 임기를 올리고 자신에게 투표한 뒤 다른 서버에 표를 요청한다. 한 임기에 한 번만 투표하고 로그가 충분히 최신인 후보에게만 표를 주는 규칙을 둘 수 있다.
두 후보가 동시에 나와 표가 갈리면 누구도 과반을 얻지 못한다. 각 서버가 무작위 선거 시간 초과(randomized election timeout: 후보가 되는 대기 시간을 서버마다 조금 다르게 정하는 방식)를 사용해 다음 선거의 동시 충돌을 줄인다.
로그는 같은 위치와 임기로 맞춘다
복제 로그(replicated log: 모든 서버가 같은 순서로 적용하려고 보관하는 명령 목록)는 각 항목의 위치와 임기를 가진다.
리더 로그
index 8, term 4: set x=1
index 9, term 5: set y=2
팔로워 로그
index 8, term 4: set x=1
리더는 다음 항목과 그 앞 위치의 정보를 보내 팔로워 로그가 이어지는지 확인한다. 충돌하면 팔로워의 확정되지 않은 뒤쪽 항목을 맞는 지점까지 되돌리고 리더 로그를 복사한다.
로그에 기록됐다는 사실과 커밋됐다는 사실은 다르다. 항목이 정족수에 복제되고 프로토콜의 안전 조건을 만족해야 커밋된 것으로 인정한다. 그 뒤 상태 머신(state machine: 같은 명령 순서를 적용하면 같은 상태가 되는 결정적 처리 규칙)에 순서대로 적용한다.
클라이언트 응답과 리더 장애 사이에 회색 구간이 있다
리더가 항목을 정족수에 복제한 뒤 클라이언트에게 응답하기 전에 죽을 수 있다. 작업은 커밋됐지만 클라이언트는 시간 초과를 받는다. 반대로 리더 한 곳에만 기록된 항목은 새 리더 선출 뒤 사라질 수 있다.
클라이언트 → 리더: 명령 K
리더 → 과반 복제: K 커밋
리더 장애, 응답 유실
클라이언트: 성공 여부 모름 → K 재시도 가능
합의가 있어도 클라이언트의 중복 재시도 문제는 남는다. 명령에 클라이언트 ID와 요청 번호를 넣어 이미 적용한 결과를 돌려주는 멱등성 규칙이 필요하다.
읽기도 최신성을 어디까지 요구하는지 정해야 한다
팔로워에서 읽으면 리더 부담과 지연을 줄일 수 있지만 복제가 늦어 이전 값을 볼 수 있다. 리더에서 읽어도 자신이 여전히 유효한 리더인지 확인하지 못하면 네트워크 분할 중 오래된 값을 줄 수 있다.
선형화 가능 읽기(linearizable read: 각 읽기와 쓰기가 실제 시간 순서의 한 지점에서 원자적으로 일어난 것처럼 보이게 하는 강한 일관성 읽기)는 현재 리더와 정족수 상태를 확인하는 추가 통신이 필요할 수 있다. 모든 조회에 같은 수준이 필요한지는 업무별로 정한다.
이해 확인 질문과 답변
응답이 없으면 서버가 죽었다고 확정할 수 있을까?
없다. 서버 장애와 네트워크 지연·분할을 관찰만으로 완전히 구분할 수 없다. 제한 시간 안에 응답이 없다는 사실을 바탕으로 의심하고 잘못된 의심에도 안전한 정족수와 임기 규칙을 사용한다.
왜 과반 정족수를 자주 사용할까?
서로 다른 두 과반 집합은 적어도 하나의 서버를 공유한다. 이 겹침을 이용해 같은 위치의 서로 다른 결정을 둘 다 확정하지 못하게 한다.
새 리더는 가장 빠르게 응답한 서버를 고르면 될까?
아니다. 이전에 커밋된 로그를 이어 갈 수 있을 만큼 최신 로그를 가진 후보여야 한다. 응답 속도만 보면 확정된 변경을 잃을 수 있다.
합의 프로토콜이 있으면 클라이언트 재시도도 정확히 한 번 처리될까?
아니다. 명령이 커밋된 뒤 응답만 사라질 수 있다. 클라이언트 요청 식별자와 중복 결과 저장 같은 멱등성 규칙을 상태 머신에 포함해야 한다.
AI에게 이렇게 요청할 수 있다
서버 A, B, C 중 A가 리더인 상태에서 네트워크가 2대와 1대로 나뉘는 시간표를 보여 줘. 과반 정족수, term, 새 리더 선출, 충돌한 로그 정리와 커밋 경계를 설명하고, 커밋 뒤 응답 유실로 클라이언트 재시도가 생기는 경우도 포함해 줘.
합의의 핵심은 모든 서버가 늘 연결되어 있는 데 있지 않다. 서로의 생사를 확정할 수 없는 상황에서도 정족수가 겹치게 하고 임기와 로그 순서를 지켜, 확정된 결정을 새 리더가 이어 가게 하는 데 있다.
'배움과 성장 > 백엔드·데이터' 카테고리의 다른 글
| 같은 요청이 다시 와도 결과가 한 번만 바뀌게 하려면? 멱등성과 멱등성 키 (0) | 2026.09.20 |
|---|---|
| LSM 트리는 쓰기를 어떻게 모아 디스크에 정리할까? SSTable과 컴팩션 (0) | 2026.09.19 |
| MVCC는 읽기와 쓰기가 서로 기다리지 않게 어떻게 도울까? 행 버전과 스냅샷 (0) | 2026.09.18 |
| WAL은 데이터 페이지보다 로그를 왜 먼저 쓸까? 변경 기록과 체크포인트 (0) | 2026.09.17 |
| 여러 복제본은 언제 같은 값을 보여야 할까? 복제와 일관성 (0) | 2026.09.09 |
댓글