2 minute read

시스템은 예기치 않은 장애로 인해 다운될 수 있지만, 최신 보안 패치를 설치하기 위해 시스템을 재부팅하는 경우로 인해 다운될 가능성도 있다.

고가용성 시스템의 목표

  • 개별 노드 장애에도 불구하고 시스템 전체가 계속 실행되도록 함
  • 노드 노후화의 영향을 가능한 한 작게 유지함

리더 기반 복제를 통해 고가용성을 달성하는 방법을 살펴보자.

팔로워 장애에는 캐치업 복구로 해결한다.

  1. 각 팔로워는 로컬 디스크에 리더로부터 받은 데이터 변경 로그를 보관합니다.
  2. 팔로워가 충돌하여 재시작되거나 리더와 팔로워 간의 네트워크가 일시적으로 중단되는 현상 발생이 발생할 때
  3. 팔로워는 로그에서 장애가 발생하기 전에 처리된 마지막 트랜잭션으로 복구한다.

팔로워는 리더와의 연결이 끊어진 시간 동안 발생한 모든 데이터 변경 사항을 요청할 수 있습니다. 이러한 변경 사항을 적용하면 리더를 따라잡고 이전처럼 데이터 변경 스트림을 계속 수신할 수 있다.

리더 실패에는 페일오버 Failover 처리를 한다.

리더 장애는 팔로워 장애보다 훨씬 까다롭다.

  • 팔로워 중 한 명을 새 리더로 승격한다.
  • 클라이언트가 새 리더에게 쓰기를 보내도록 재구성해야 한다.
  • 다른 팔로워가 새 리더의 데이터 변경 사항을 받도록 해야 한다.

이러한 프로세스를 페일오버라고 한다.

페일오버 프로세스는 일반적으로 다음 단계로 구성된다.

1. 리더 실패 확인

리더가 실패했는지 확인한다. 충돌, 정전, 네트워크 문제 등 잠재적으로 문제가 원인이 된다. 무엇이 잘못되었는지 감지하는 완벽한 방법은 없기 때문에 대부분의 시스템은 단순히 타임아웃을 사용한다. 노드는 서로 메시지를 자주 주고받고, 노드가 일정 시간(예: 30초) 동안 응답하지 않으면 죽은 것으로 간주한다.

2. 새로운 리더 선출

새 리더를 선출한다. 이는 선거 절차(나머지 복제본의 과반수가 리더를 선출)를 통해 이루어질 수도 있고, 이전에 선출된 컨트롤러 노드가 새 리더를 임명할 수도 있다. 일반적으로 데이터 손실을 최소화하기 위해 이전 리더로부터 가장 최신의 데이터 변경 사항이 있는 복제본이 리더로 가장 적합한 후보다.

3. 팔로워에게 새 리더를 인식시키기

이제 클라이언트는 쓰기 요청을 새 리더에게 보내야 한다. 이전 리더가 다시 돌아와도 다른 복제본에 의해 강제로 물러나야 한다는 사실을 인식하지 못하고 여전히 자신이 리더라고 생각할 수 있다. 시스템은 이전 리더가 팔로워가 되어 새 리더를 인식할 수 있도록 해야 한다.

페일오버는 여러 가지 상황을 고려해야하므로 매우 다루기 어렵다:

  • 비동기 복제를 사용하는 경우 새 리더가 이전 리더가 실패하기 전에 모든 쓰기를 받지 못했을 수 있다.
  • 새 리더가 선택된 후 이전 리더가 클러스터에 다시 참여하면 새 리더는 그 동안 충돌하는 쓰기를 받았을 수 있다.

가장 일반적인 해결책은 이전 리더의 복제되지 않은 쓰기를 단순히 폐기하는 것인데, 이는 신뢰성을 악화한다.

쓰기 삭제로 인한 시스템 오류 사례

이는 GitHub에서 발생한 한 사건이다. 오래된 MySQL 팔로워가 리더로 승격되었다. 데이터베이스는 자동 증가 카운터를 사용하여 새 행에 기본 키를 할당했지만 새 리더의 카운터가 이전 리더의 카운터보다 뒤처졌다. 이전 리더가 이전에 할당했던 일부 기본 키를 재사용했다. 이러한 기본 키는 Redis 저장소에서도 사용되었기 때문에 기본 키 재사용으로 인해 MySQL과 Redis 간에 불일치가 발생하여 일부 개인 데이터가 잘못된 사용자에게 공개되었다.

두 명의 리더가 선출되는 문제

두 노드 모두 자신이 리더라고 생각하는 경우가 발생할 수 있다. 두 리더가 모두 쓰기를 수락하고 충돌을 해결하는 프로세스가 없는 경우, 데이터가 손실되거나 손상될 가능성이 높다. 일부 시스템에는 두 명의 리더가 감지되면 한 노드를 종료하는 메커니즘이 있지만, 이 메커니즘을 신중하게 설계하지 않으면 두 노드가 모두 종료될 수 있다.

리더 장애 판정시 적절한 타임아웃은

리더가 죽은 것으로 선언되기까지 적절한 타임아웃은 얼마일까? 타임아웃이 길수록 리더가 실패할 경우 복구하는 데 걸리는 시간이 길어진다. 그러나 타임아웃이 너무 짧으면 불필요한 페일오버가 발생할 수 있다. 예를 들어, 일시적인 부하 급증으로 인해 노드의 응답 시간이 타임아웃 이상으로 증가하거나 네트워크 결함으로 인해 패킷이 지연될 수 있다. 시스템이 이미 높은 부하 또는 네트워크 문제로 어려움을 겪고 있는 경우, 불필요한 장애 조치로 인해 상황이 개선되기는커녕 악화될 가능성이 높습니다.

이러한 문제에 대한 쉬운 해결책은 없다. 이러한 이유로 일부 운영팀은 소프트웨어가 자동 페일오버를 지원하더라도 수동으로 페일오버를 수행하는 것을 선호한다.

TLDR;

  • 팔로워의 장애가 발생할 경우, 데이터 변경 로그를 따라잡아(캐치업) 해결한다.
  • 리더 실패에는 페일오버(Failover) 라는 3 가지 프로세스를 수행한다.
  • 페일오버는 리더 실패를 확인하고 리더를 선출하고 팔로워들에게 리더를 인식시키는 프로세스다.
  • 페일오버는 자동으로 하기에는 단점이 많기 때문에 수동으로 수행하는 것을 선호한다.