책너두 (데이터 중심 애플리케이션 설계) 32일차 (~369p)

요약

  • 현실의 분산 트랜잭션에 대한 내용을 이해함.
    • 데이터베이스 내부 분산 트랜잭션
    • 이종 분산 트랜잭션
      • 메시지를 정확히 한번 처리하는 원자적 커밋 지원할 수 있음.
  • XA 트랜잭션을 통해 이종 분산 트랜잭션을 구현함.
    • 장애 발생시 의심스러운 트랜잭션 발생할 수 있음.
    • 코디네이터의 장애를 복구해야함.
    • 이러한 분산 트랜잭션에도 제약이 있음.
      • 코디네이터 자체가 일종의 데이터베이스로 간주해야 하기 때문
  • 내결함성을 지닌 합의에 대한 내용을 이해함.
    • 균일한 동의
    • 무결성
    • 유효성
    • 종료
    • 내결함성을 지닌 합의 알고리즘은 위 형식보다는 전체 순서 브로드캐스트를 구현함.
      • 이 또한 합의의 과정임.
      • 합의의 합의가 필요할 수 있음. (리더 선출과 전체 순서 브로드캐스트)
        • 이 경우 에포크 번호를 붙여 해결할 수 있음.
    • 합의 알고리즘도 제약이 있음.
  • 멤버십과 코디네이션 서비스에 대한 내용을 이해함.
    • 데이터베이스와 다른 주키퍼와 etcd 의 내용에 대해 이해함.
    • 소량의 데이터를 내결함성 있게 복제하도록 도와줌.
    • 서비스 찾기 용도로 사용 가능
    • 멤버십 서비스를 통해 투표에 필요한 노드들을 찾아냄

메모

현실의 분산 트랜잭션

  • 여러 클라우드 서비스들은 분산 트랜잭션이 낳은 운영상 문제 때문에 분산트랜잭션을 구현하지 않는 선택을 함.
  • 어떤 분산 트랜잭션 구현은 무거운 성능 손해를 수반함.
    • ex) MySQL의 분산 트랜잭션은 단일 노드 트랜잭션보다 10배 이상 느리다고 보고됨.
    • 2단계 커밋에 내장된 성능 비용의 많은 부분은 장애 복구를 위해 필요한 부가적인 디스크 강제 쓰기와 부가적인 네트워크 왕복시간 때문임.
  • 그럼에도, 분산 트랜잭션을 완전히 일축하기보다 좀 더 자세히 조사해야 함.
    • 분산 트랜잭션이 무엇을 의미하는지 정확히 해야함.
      • 데이터베이스 내부 분산 트랜잭션
        • 데이터베이스 노드 사이에 내부 트랜잭션을 지원함.
        • 다른 시스템과 호환될 필요가 없으므로 아무 프로토콜이나 쓸 수 있음.
        • 특정 기술에 특화된 최적화를 사용할 수 있음.
      • 이종 분산 트랜잭션
        • 두 가지 서로 다른 벤더의 데이터베이스 일 수도 있고, 메시지 브로커처럼 비데이터베이스 시스템일 수 있음.
        • 이러한 시스템에 걸친 분산 트랜잭션은 시스템의 내부가 완전히 달라도 원자적 커밋을 보장해야 함.
        • 구현이 어려움.

정확히 한 번 메시지 처리

  • 분산 트랜잭션이 지원되면 메시지 브로커와 데이터베이스가 서로 다른 장비에서 실행되는 두 가지 무관한 기술이더라도 원자적 커밋이 가능함.
    • 메시지 전달이나 데이터베이스 트랜잭션 중 하나가 실패하면 둘다 어보트되고, 메시지 브로커는 나중에 메시지를 안전하게 다시 전달할 수 있음.
    • 메시와 그 처리 과정의 부수 효과를 원자적으로 커밋함으로써 메시지가 결과적으로 정확히 한 번 처리되도록 보장할 수 있음.
  • 만약, 2단계 커밋을 지원하지 않는 시스템이 있다면 원자적 커밋이 힘듦.

XA 트랜잭션

  • X/Open XA(eXtended Architecture)는 이종 기술에 걸친 2단계 커밋을 구현하는 표준임.
    • 여러 전통적인 관계형 데이터베이스와 메시지 브로커에서 지원됨.
  • XA는 네트워크 프로토콜이 아니라 트랜잭션 코디네이터와 연결되는 인터페이스를 제공하는 C API 임.
  • XA는 애플리케이션이 네트워크 드라이버나 클라이언트 라이브러리를 사용하여 참여자 데이터베이스나 메시징 서비스와 통신한다고 가정함.
    • 드라이버는 코디네이터가 참여자에게 준비, 커밋, 어보트를 요청할 수 있는 콜백도 제공해줌.
    • 트랜잭션 코디네이터는 XA API를 구현함.
  • 애플리케이션 프로세스가 죽거나 실행중인 장비가 죽으면 코디네이터도 함께 사라짐
    • 준비가 됐지만 커밋되지 않은 트랜잭션들을 가진 참여자는 의심스러운 상태에 빠짐.
    • 코디네이터 로그는 애플리케이션 서버의 로컬 디스크에 있기에 그 서버가 재시작돼야 복구됨.

의심스러운 상태에 있는 동안 잠금을 유지하는 문제

  • 트랜잭션이 의심스러운 상태에 빠지는 것을 신경써야함.
    • 그 이유는 잠금때문임.
      • 데이터베이스는 트랜잭션이 커밋하거나 어보트할 때까지 이런 잠금을 해제할 수 없음.
      • 즉, 다른 트랜잭션이 자기 일을 계속할 수 없음.

코디네이터 장애에서 복구하기

  • 현실에서 고아가 된 의심스러운 트랜잭션이 생길 수 있음.
    • 즉, 어떤 이유에서인지 코디네이터가 그 결과를 결정할 수 없는 트랜잭션이 생길 수 있음.
      • ex) 트랜잭션 로그 손실, 소프트웨어의 버그오염
    • 이런 트랜잭션은 자동으로 해소될 수 없어서 다른 트랜잭션을 차단하면서 데이터베이스에 영원히 남음.
  • 이 상황을 빠져나가는 유일한 방법은 관리자가 수동으로 트랜잭션을 커밋하거나 롤백을 결정해야 함.
  • 여러 XA 구현에서는 참여자가 코디네이터로부터 확정적 결정을 얻지 않고 의심스러운 트랜잭션을 어보트 or 커밋할지를 일방적으로 결정할 수 있도록 하는 경험적 결정(heuristic decision)이라는 비상탈출구가 있음.
    • 이는 경험적이므로 원자성을 깰 수 있음.
    • 큰 장애 상황에서 벗어나고자 할 떄만 쓰도록 의도된 것임.

분산 트랜잭션의 제약

  • XA 트랜잭션의 핵심 구현은 트랜잭션 코디네이터 자체가 일종의 데이터베이스여야 한다는 점임.
    • 즉, 다른 중요한 데이터베이스와 동일하게 신경 써서 접근해야 함.
      • 코디네이터가 복제되지 않고 단일 장비에서만 실행되면 SPOF가 됨.
      • 코디네이터가 중심이되면 애플리케이션의 배포 특성이 바뀌게 됨.
      • 데이터베이스 내부 분산 트랜잭션은 제한이 크지 않음.
        • 하지만 2PC가 성공적으로 트랜잭션을 커밋하려면 모든 참여자가 응답해야함.
        • 따라서 이 또한 시스템의 어떤 부분이 고장나면 트랜잭션이 실패함.
        • 내결함성을 지닌 시스템 구축 목적에 어긋남.

내결함성을 지닌 합의

  • 비공식적으로 합의는 여러 노드가 어떤 것에 동의해야 한다는 뜻임.
  • 합의 문제는 다음과 같이 형식화됨.
    • 하나 또는 그 이상의 노드들이 값을 제안할 수 있음.
    • 합의 알고리즘은 그 값 중 하나를 결정함.
  • 위 형식에서 합의 알고리즘은 다음 속성을 만족해야 함.
    • 균일한 동의
    • 무결성
    • 유효성
    • 종료
  • 균일한 동의와 무결성 속성은 합의의 핵심 아이디어임.
  • 내결함성이 상관없다면 처음 세 개의 속성을 만족시키는 건 쉬움.
    • 그냥 한 노드를 독재자로 만들면 됨.
    • 하지만 이 노드가 장애가 나면 그 시스템은 어느 결정도 할 수 없음.
  • 종료 속성은 내결함성의 아이디어를 형식화함.
    • 어떤 노드가 장애가 나더라도 다른 노드들은 여전히 결정해야함.
    • 노드가 복구 되기를 기다리는 알고리즘을 가진 시스템 모델은 종료 속성을 만족할 수 없음.
      • ex) 2PC
  • 만약 모든 노드가 죽는다면 어떤 알고리즘을 쓰더라도 아무것도 결정할 수 없음.
    • 알고리즘이 견딜 수 있는 장애의 수에 제한이 있음.

합의 알고리즘과 전체 순서 브로드캐스트

  • 내결함성을 지닌 합의 알고리즘 중 가장 널리 알려진 것은 아래와 같음.
    • 뷰스탬프 복제
    • 팍소스
    • 라프트
      • 알고리즘의 상세한 부분은 보지않음.
      • 이 알고리즘의 공통의 고수준 아이디어를 아는 것으로 충분함.
  • 위 알고리즘은 형식적 모델을 사용하지 않고 값의 순차열을 결정해서 전체 순서 브로드캐스트 알고리즘을 만듦.
    • 전체 순서 브로드캐스트를 하기 위해 모든 노드에 메시지가 정확히 한 번, 같은 순서로 전달돼야 함.
      • 즉, 전체 순서 브로드캐스트는 합의를 여러 번 반복하는 것과 동일함.

단일 리더 복제와 합의

  • 단일 리더 복제는 본질적으로 전체 순서 브로드캐스트처럼 보임.
    • 근데 5장에서 왜 합의에 대한 문제를 고민하지 않았을까?
      • 리더를 어떻게 선택하는지에 대한 내용을 생각해야함.
      • 5장은 사람이 수동으로 리더를 선택하는 독재자 방식의 합의 알고리즘을 생각했던 것임.
      • 만약 수동으로 제어할 사람이 없다면 리더가 선정되지 않아 쓰기를 할 수 없음.
  • 리더를 선출하려면 합의가 필요함.
    • 근데, 전체 순서 브로드캐스트 알고리즘 또한 합의가 필요함.
    • 즉, 합의를 해결하기 위해 먼저 합의를 해결해야 함.
    • 이 문제를 어떻게 해결해야 하는가?

에포크 번호 붙이기와 정족수

  • 지금까지의 합의 프로토콜은 리더가 유일하다고 보장하지 않음.
    • 대신, 약한 보장을 할 수 있음.
    • 에포크 번호(= 투표 번호)를 정의하고 각 에포크 내에서는 리더가 유일하다고 보장함.
  • 리더가 죽었다고 생각되면 새 노드를 선출하기 위해 노드 사이 투표가 시작됨.
    • 에포크 번호는 단조증가함.
    • 두 가지 다른 에포크에 있는 다른 리더 사이 충돌이 있으면 에포크 번호가 높은 리더가 이김.
  • 즉, 리더가 뭔가 결정하도록 허용하기 전에, 더 높은 에포크 번호를 가진 리더가 없는지 먼저 확인해야함.
    • 진실은 다수결로 결정된다를 상기하자.(p300)
    • 노드의 정족수로부터 투표받아야 함.
    • 내결함성을 지닌 합의 알고리즘은 노드의 과반수로부터만 투표받으면 됨.

합의의 제약

  • 합의 알고리즘이 모든 곳에 쓰이지 않음.
    • 이득에는 대가가 따르기 때문.
  • 제안이 결정되기 전, 노드가 제안에 투표하는 과정은 일종의 동기식 복제임.
  • 합의 시스템은 항상 엄격한 과반수가 동작하기를 요구함.
    • 노드 한 대의 장애를 견디려면 최소 세 대의 노드가 필요함.
  • 합의 알고리즘은 투표에 참여하는 노드 집합이 고정돼 있다고 가정함.
    • 클러스터에 노드를 그냥 추가, 제거할 수 없음.
  • 합의 시스템은 장애 노드를 감지하기 위해 타임아웃에 의존함.
    • 네트워크 문제임에도 장애가 발생했다고 잘못 생각할 수 있음.
  • 합의 알고리즘은 네트워크 문제에 민감함.

멤버십과 코디네이션 서비스

  • 주키퍼나 etcd 같은 프로젝트는 “분산 키-값 저장소”, “코디네이션 설정 서비스”로 설명됨.
    • 이 서비스 API는 데이터베이스의 API와 매우 비슷함.
    • 이들은 데이터베이스와 다르지만, 어떻게 합의 알고리즘을 구현할 수 있었을까?
      • 주키퍼 서비스가 어떻게 사용되는지 살펴보면 도움이 됨.
  • 애플리케이션 개발자는 주키퍼를 직접 쓸 필요는 거의 없음.
    • 다른 프로젝트에 의해 간접적으로 주키퍼에 의존하게 될 가능성이 높음.
      • ex) HBase, 하둡 얀, 카프카 등
    • 위 프로젝트는 주키퍼에 얻는 것은 무엇인가?
  • 주키퍼와 etcd 는 완전히 메모리 안에 들어올 수 있는 작은 양의 데이터를 보관하도록 설계됨.
    • 애플리케이션의 모든 데이터를 저장할 수는 없음.
    • 이 소량의 데이터는 내결함성을 지닌 전체 순서 브로드캐스트 알고리즘을 사용하여 모든 노드에 걸쳐 복제됨.
    • 복제본들이 일관성을 유지할 수 있음.
  • 주키퍼는 위 내용 외에도 여러 기능을 구현함.
    • 선형성 원자적 연산
    • 연산의 전체 순서화
    • 장애 감지
    • 변경 알림

작업을 노드에 할당하기

  • 주키퍼는 여러 프로세스나 서비스가 있고, 그 중 하나가 리더나 주 구성요소로 선택돼야할 때 잘 동작함.
    • 리더에 장애가 나면 다른 노드 중 하나가 넘겨받아야 함.
    • 파티셔닝 자원에서 어떤 파티션을 어떤 노드에 할당해야할지 결정해야 하는 경우.
      • ex) 부하의 재균형화
  • 위 종류의 작업은 주키퍼에서 원자적 연산, 단명 노드, 알림을 신중하게 사용하면 잘 해낼 수 있음.
    • 쉽지는 않지만 합의 알고리즘을 밑바닥 부터 구현하려고 시도하는 것보다는 나음.
  • 애플리케이션이 수천 대의 노드로 늘어날 수 있음.
    • 매우 많은 노드에서 과반수 투표를 수행하는 것은 매우 비효율적임.
    • 주키퍼는 고정된 수의 노드에서 실행되고, 이 노드들 사이에서 과반수 투표를 수행하면서 많아질 수 있는 클라이언트를 지원함.
  • 주키퍼로 관리되는 데이터의 종류는 매우 느리게 변함.
    • 매초, 수천 번 혹은 수백만 번까지 변경될지도 모르는 애플리케이션의 런타임 상태 저장용으로 의도된건 아님.
      • 이는 다른 도구인 아파치 북키퍼 같은 것을 사용할 수 있음.

서비스 찾기

  • 주키퍼, etcd 는 서비스 찾기의 용도로 자주 사용됨.
    • 특정 서비스에 연결하려면 어떤 IP 주소로 접속해야 하는지 알아내야 하는 용도임.
  • 서비스 찾기가 실제로 합의가 필요한지는 분명해 보이진 않음.
    • ex) DNS 서비스는 질의 결과가 조금 뒤처지더라도 신뢰성 있게 사용 가능하고 네트워크 끊김에 견고함.

멤버십 서비스

  • 멤버십 서비스는 클러스터에서 어떤 노드가 현재 활성화된 살아 있는 멤버인지 결정함.
  • 장애 발생 시, 장애 감지를 합의와 연결하면, 노드들은 어떤 노드가 살아 있는 것으로 여겨져야하고, 죽은 것으로 여겨져야 하는지에 동의할 수 있음.

댓글

Designed by JB FACTORY