etcd(리더 선출, 로그 복제)

YYY·2024년 12월 27일

기본 상태 정의

Quorum(쿼럼) = 과반수

즉 etcd 클러스터의 과반수 이상의 노드가 응답해야만 한다.

etcd의 고가용성(HA)을 보장하려면
1. 최소 3대 이상의 노드 필요
2. 홀수 개수의 노드 필요 - raft알고리즘을 따르기 때문

State = 3가지 상태로 존재

Leader: 과반수의 투표를 얻은 Candidate.
Follower: 기본 상태, 리더의 Heartbeat을 기다림.
Candidate: Election Timeout에 도달한 Follower가 리더 선출을 위해 스스로 후보로 선언한 상태.

Timer = Leader서버가 주기적으로 leader가 존재함을 알림

ex) 일정 시간동안 heartbeat를 받지 못하면 Leader가 없어졌다고 간주(Election Timeout)

Term = 리더의 세대

  • Term 번호가 낮은 노드의 리더 선출 시도를 방지
  • 최신 Term을 기준으로 투표와 로그 복제가 이루어짐 : 데이터 충돌 방지

Raft 알고리즘

리더 선출 과정

  1. 모든 서버가 Follower 상태
  2. Election Timeout 발생 - 무작위(서버마다 다ㄹ
  3. Timeout이 발생한 Follower는 Candidate로 전환
    1) 해당 서버의 Term += 1
    2) Vote Request 발송:
    - 네트워크에 있는 모든 노드(Follower)에게 투표 요청
    - Candidate의 Term, 로그 상태(최신 로그 인덱스와 Term) 같이 발송
  4. Follower의 투표
    • Candidate의 Term이 자신보다 높으면 투표 : 이후 Candidate의 Term으로 업데이트
    • Candidate의 로그가 자신보다 최신이어야 함
  5. 리더 선출 : Candidate가 과반수(쿼럼)의 투표를 얻으면 리더로 선출
    1) 주기적으로 Follower에게 Heartbeat 전송
    2) Heartbeat를 통해 자신이 리더임을 알리고 Election Timeout을 초기화
    3) 새로운 로그를 Follower에게 복제하고 일관성을 유지

예시

리더 선출 과정 (3개의 노드)
초기 상태:

  1. 서버 A, B, C는 모두 Follower 상태
    Election Timeout: A(150ms), B(200ms), C(250ms)

  2. A의 Timeout 발생:
    A는 Candidate로 전환, Term을 1로 증가
    B와 C에게 Vote Request 발송

  3. B와 C의 응답:
    B와 C는 A의 Term(1)이 자신보다 높으므로 A에게 투표
    A는 과반수(2/3) 확보 후 리더로 전환

  4. 리더 A의 Heartbeat 전송:
    A는 주기적으로 B와 C에게 Heartbeat 전송
    B와 C는 Heartbeat을 수신하며 Timeout을 초기화

리더 선출 이후 로그 복제 과정

  1. 리더 선출 → 노드 A가 리더로 선출됩니다.
  2. 리더가 클라이언트 요청을 처리 → 로그 항목을 생성하고 nextIndex부터 팔로워들에게 복제
  3. 리더가 팔로워들에게 로그 복제 → AppendEntries RPC를 통해 로그 항목을 복제
  4. 팔로워들이 로그를 받음 → lastIndex를 기준으로 일치 여부를 확인하고 로그를 추가
  5. 리더가 커밋을 완료 → commitIndex가 과반수 이상의 노드에서 복제된 로그 항목에 대해 커밋
  6. 로그가 일관되게 복제되고 적용됨 → 모든 노드가 동일한 로그 항목을 커밋하고 시스템 상태를 일관되게 유지

nextIndex와 lastIndex의 역할:

nextIndex: 리더가 각 팔로워에게 복제할 다음 로그 항목의 인덱스
lastIndex: 각 팔로워가 마지막으로 복제받은 로그 항목의 인덱스
두 값을 통해 리더와 팔로워 간의 로그 동기화가 이루어짐

예시

노드 A (리더), 노드 B (팔로워), 노드 C (팔로워) 3개의 노드로 구성된 Raft 클러스터가 있다고 가정

  1. 리더 선출
  • 리더가 선출되면, 리더는 클라이언트 요청을 처리 -> 로그 엔트리를 생성합니다.
  • 리더는 AppendEntries RPC를 사용 -> 자신이 생성한 로그 항목을 팔로워들에게 복제
  1. 리더가 로그 엔트리 추가
    예시 로그 항목:
{
  "operation": "insert",
  "key": "user1",
  "value": "John Doe",
  "term": 5,
  "index": 1001
}
  1. 리더가 팔로워에게 로그 복제
  • 리더는 AppendEntries RPC를 통해 자신이 생성한 로그 엔트리를 팔로워들에게 복제
  • 리더는 각 팔로워에게 nextIndex부터 복제를 시작하며, lastIndex와 비교하여 필요한 로그 항목을 전달
    예시:
    리더가 nextIndex=1001인 로그 항목을 팔로워에게 보냅니다.
    팔로워는 lastIndex=1000을 리더에게 응답하면서, 로그 항목을 수신하고 이를 자기 로그에 추가합니다.
  1. 커밋 (commitIndex)
  • Commit이란, log entry에 먼저 기록된 데이터를 서버마다 가지고 있는 db(파일시스템)에 write 하는 것을 의미
  • 리더 A는 commitIndex를 갱신하여 로그 항목이 과반수 이상의 팔로워들에게 복제되었음을 확인
  1. 커밋된 로그 항목이 각 노드에서 적용
profile
무지렁이 탈출기

0개의 댓글