1) 서문
- 지난 몇 개 장에서 되풀이됐던 주제는 시스템이 잘못된 것을 어떻게 처리하느냐였다.
예를 들어, 복제 서버 장애 복구, 복제 지연, 트랜잭션의 동시성 제어를 설명했다.
실제 환경 시스템에서 나타날 수 있는 다양한 에지 케이스를 잘 이해할수록 이것들을 잘 처리할 수 있다.
- 그러나 결함에 관한 많은 얘기를 했지만, 지난 몇 개 장은 아직도 너무 낙관적이었다.
현실은 훨씬 더 암울하다.
이제 비관주의를 최대한으로 끌어올려 어떤 것이든지 잘못될 가능성이 있다면 잘못된다고 가정한다.
- 분산 시스템을 다루는 것은 한 컴퓨터에서 실행되는 소프트웨어를 작성하는 일과는 근본적으로 다르다.
그리고 핵심적인 차이는 뭔가 잘못될 수 있는 새롭고 흥미진진한 방법이 많다는 점이다.
이번 장에서는 현업에서 일어나는 문제점들을 맛보고, 우리가 기댈 수 있는 것과 그렇지 않은 것을 이해하게 된다.
- 결국 엔지니어로서의 우리의 임무는 모든 게 잘못되더라도 제 역할을 해내는(즉, 사용자가 기대하는 보장은 만족시키는)
시스템을 구축하는 것이다. 9장에서는 분산 시스템에서 이런 보장을 제공하는 알고리즘의 몇 가지 예를 살펴본다.
하지만 먼저 이번 장에서 우리가 어떤 도전에 직면해 있는지 이해해야 한다.
- 이번 장은 분산 시스템에서 잘못될지도 모르는 것에 관한 지독하게 비관적이며 우울한 개요다.
네트워크 관련 문제와 시계 및 타이밍 문제를 조사하고 이것들을 어느 정도로 회피할 수 있는지 설명한다.
이 모든 문제의 결과는 종잡을 수 없다.
따라서 분산 시스템의 상태에 대해 생각하는 방법과 무슨 일이 일어났는지 추론하는 방법을 알아본다.
2) 결함과 부분 장애
- 한 컴퓨터에서 프로그램을 작성할 때는 프로그램이 보통 상당히 예측 가능한 방식으로 동작한다.
돌아가거나 안 돌아가거나 둘 중 하나다.
버그투성이 소프트웨어는 가끔씩 컴퓨터가 "운수 나쁜 날"인 것처럼 보이게 하지만,
이건 대부분 잘못 작성한 소프트웨어의 결과일뿐이다.
- 단일 컴퓨터에서 실행되는 소프트웨어를 믿지 못할 근본적인 이유는 없다.
하드웨어가 올바르게 동작하면 같은 연산은 항상 같은 결과를 낸다(결정적이다)
하드웨어 문제(예를 들어 메모리 오염이나 헐거운 커넥터)가 있으면
보통 시스템이 완전히 실패하는 결과(예를 들어, 커널 패닉, "죽음의 블루 스크린", 부팅 실패 등)를 낳는다.
좋은 소프트웨어가 설치된 각각의 컴퓨터는 보통 완전하게 동작하거나 전체 장애가 발생하지
그 중간 상태가 되지는 않는다.
- 이것은 컴퓨터를 설계할 때 의도적으로 선택한 것이다.
우리는 컴퓨터에 내부 결함이 발생하면 잘못된 결과를 반환하기보다는 완전히 동작하지 않기를 원한다.
잘못된 결과는 다루기 어렵고 혼란스럽기 때문이다.
따라서 컴퓨터는 구현 기반이 되는 불분명한 물리적 현실을 감추고 수학적 완벽함을 갖고 동작하는
이상화된 시스템 모델을 보여준다.
- CPU 인스트럭션은 항상 같은 일을 한다.
메모리나 디스크에 데이터를 쓰면 온전하게 남아 있고 제멋대로 오염되지 않는다.
이렇게 항상 올바른 계산을 목표로 한 설계는 바로 첫 번째 디지털 컴퓨터까지 거슬러 올라간다.
- 네트워크로 연결된 여러 컴퓨터에서 실행되는 소프트웨어를 작성할 때는 근본적으로 상황이 다르다.
분산 시스템에서는 더 이상 이상화된 시스템 모델에서 동작하지 않는다.
물리적 세계의 지저분한 현실을 마주하는 것 외에 다른 선택은 없다.
그리고 물리적 세계에서는 아래 일화로 설명되는 것처럼 매우 광범위한 것들이 잘못될 수 있다.
- 분산 시스템에서는 시스템의 어떤 부분은 잘 동작하지만 다른 부분은 예측할 수 없는 방식으로 고장나는 것도
무리가 아니다.
이를 부분 장애(partial failure)라고 한다.
부분 장애는 비결정적이라서 어렵다. 여러 노드와 네트워크와 관련된 뭔가를 시도하면 어떨 때는 동작하지만
어떨 때는 예측할 수 없는 방식으로 실패한다.
뒤에서 보게 되겠지만 심지어 뭔가 성공했는지 아닌지 알지 못할 수도 있다.
메시지가 네트워크를 거쳐 전송되는 시간도 비결정적이기 때문이다!
비결정성과 부분 장애 가능성이 분산 시스템을 다루기 어렵게 한다.
3) 클라우드 컴퓨팅과 슈퍼 컴퓨팅
- 대규모 컴퓨팅 시스템 구축 방법에 관한 몇 가지 철학이 있다.
(1) 대규모 컴퓨팅의 한쪽 끝에는 고성능 컴퓨팅 분야가 있다.
수천 개의 CPU를 가진 슈퍼컴퓨터는 보통 일기예보나 분자 동력학처럼 계산 비용이
매우 높은 과학 계산 작업에 쓰인다.
(2) 다른 극단에는 클라우드 컴퓨팅이 있다. 명확히 정의되지는 않지만 멀티 테넌트 데이터센터,
IP 네트워크 컴퓨터, 신축적, 주문식 자원 할당, 계량 결제와 흔히 관련돼 있다.
(3) 전통적인 기업형 데이터센터는 이 두 극단의 중간 지점에 있다.
- 이런 철학에 따라 결함 처리 방법도 매우 다르다.
슈퍼컴퓨터에서 실행되는 작업은 보통 가끔씩 계산 상태를 지속성 있는 저장소에 체크포인트로 저장한다.
노드 하나에 장애가 발생했을 때, 흔한 해결책은 그냥 전체 클러스터 작업부하를 중단하는 것이다.
장애가 발생한 노드가 복구된 후 마지막 체크포인트부터 계산을 재시작한다.
- 따라서 슈퍼컴퓨터는 분산 시스템보다는 단일 노드 컴퓨터에 가깝다.
슈퍼컴퓨터는 부분 장애를 전체 장애로 확대하는 방법으로 처리한다.
시스템의 어느 부분에 장애가 발생하면(단일 장비에서의 커널 패닉처럼) 그냥 전체가 죽게한다.
- 이 책에서는 인터넷 서비스를 구현하는 시스템을 집중적으로 다루며 이는 보통 슈퍼컴퓨터와 매우 다르다.
(1) 여러 인터넷 관련 애플리케이션은 언제라도 사용자에게 지연 시간이 낮은 서비스를 제공해야 한다는 점에서
온라인이다. 수리를 위해 클러스터를 중단시키는 것처럼 서비스를 이용할 수 없게 하는 것은 허용되지 않는다.
반대로 날씨 시뮬레이션 같은 오프라인(일괄 처리)작업은 멈췄다 재시작해도 충격이 덜하다.
(2) 슈퍼컴퓨터는 전형적으로 특화된 하드웨어를 사용해 구축한다.
각 노드는 매우 신뢰성이 높으며 노드 사이에는 공유 메모리와 원격 직접 메모리 접근을 사용해 통신한다.
반면 클라우드 서비스의 노드는 상용 장비를 사용해 구축한다.
규모의 경제 덕에 낮은 비용으로 동일한 성능을 제공하지만 실패율도 높다.
(3) 거대한 데이터센터의 네트워크는 흔히 IP와 이더넷을 기반으로 하며 높은 양단 대역폭을 제공하기 위해
클로스 토폴로지와 연결돼 있다.
슈퍼컴퓨터는 통신 패턴이 정해진 HPC 작업부하에서 높은 성능을 보여주는 다차원 메시나
토러스 같은 네트워크 토폴로지를 자주 사용한다.
(4) 시스템이 커질수록 구성 요소 중 하나가 고장날 가능성도 노팡진다.
시간이 지나면서 고장난 것은 수리되고 새로운 것이 고장나지만 수천 개의 노드가 있는 시스템에서는
항상 뭔가 고장난 상태라고 가정하는 게 합리적이다.
오류 처리 전략에 그냥 포기하는 것을 포함한다면 대형 시스템은 유용한 일을 하기보다
결함으로부터 복구하는데 많은 시간을 쓰게 될 수도 있다.
(5) 시스템이 장애가 난 노드를 감내할 수 있고 전체적으로는 계속 동작할 수 있다면
이는 운영과 유지보수에 매우 유용한 특성이 된다.
이를테면 끊김 없이 사용자에게 서비스를 계속 제공하면서 한 번에 노드 하나씩 재시작하는
순회식 업그레이드를 할 수 있다.
클라우드 환경에서 가상 장비 하나의 성능이 좋지 않으면 그냥 그것을 죽이고 새 갓아 장비를 요청할 수 있다.
(6) 지리적으로 분산된 배포를 할 때 통신은 대부분 인터넷을 거치기 쉬운데 로컬 네트워크에 비해 느리고 신뢰성도
떨어진다. 슈퍼컴퓨터는 일반적으로 모든 노드가 가까운 곳에 함께 있다고 가정한다.
- 분산 시스템이 동작하게 만들려면 부분 장애 가능성을 받아들이고 소프트웨어에 내결함성 메커니즘을 넣어야 한다.
바꿔 말하면 신뢰성 없는 구성 요소를 사용해 신뢰성 있는 시스템을 구축해야 한다.
단지 몇 개의 노드만으로 구성된 작은 시스템이라도 부분 장애를 고려하는 것은 중요하다.
작은 시스템에서는 거의 항상 구성 요소 대부분이 올바르게 동작할 가능성이 아주 높다.
그러나 조만간 시스템의 어떤 부분에 결함이 생길 것이고 소프트웨어는 어떤 식으로든 그 결함을 처리해야 한다.
결함 처리는 소프트웨어 설계의 일부여야 하며 여러분은 결함이 발생하면 소프트웨어가 어떻게 동작할지 알아야 한다.
- 결함이 드물 것이라 가정하고 최선의 상황을 바라기만 하는 것은 현명하지 못하다.
발생 가능성이 상당히 낮을지라도 생길 수 있는 결함을 광범위하게 고려하고
테스트 환경에서 인위적으로 이런 상황을 만들어서 어떤 일이 생기는지 보는 게 중요하다.
분산 시스템에서 의심, 비관주의, 편집증은 그 값어치를 한다.
4) 신뢰성 없는 네트워크
- 2부 소개에서 말했듯이 이 책에서 주로 다루는 분산 시스템은 비공유 시스템,
즉 네트워크로 연결된 다수의 장비다. 네트워크는 이 장비들이 통신하는 유일한 수단이다.
각 장비는 자신만의 메모리와 디스크를 갖고 있으며 다른 장비의 메모리나 디스크에 접근할 수 없다고 가정한다.
- 비공유가 시스템을 구축하는 유일한 방법은 아니지만 몇 가지 이유로 인터넷 서비스를 구축하는 주된 방법이 됐다.
특별한 하드웨어가 필요하지 않아서 상대적으로 저렴하고, 상품화된 클라우드 서비스를 활용할 수 있으며,
지리적으로 분산된 여러 데이터센터에 중복 배치함으로써 높은 신뢰성을 확보할 수 있다.
- 인터넷과 데이터센터 내부 네트워크 대부분(흔히 이더넷)은 비동기 패킷 네트워크다.
이런 종류의 네트워크에서 노드는 다른 노드로 메시지(패킷)를 보낼 수 있지만
네트워크는 메시지가 언제 도착할지 혹은 메시지가 도착하기는 할 것인지 보장하지 않는다.
요청을 보내고 응답을 기다릴 때 여러 가지가 잘못될 수 있다.
'데이터 중심 애플리케이션 설계' 카테고리의 다른 글
[데이터 중심 애플리케이션 설계] 관계형 모델과 문서 모델 (0) | 2024.08.18 |
---|---|
[데이터 중심 애플리케이션 설계] 트랜잭션 (1) | 2024.07.25 |
[데이터 중심 애플리케이션 설계] 유지보수성 (2) | 2024.07.24 |
[데이터 중심 애플리케이션 설계] 부하 대응 접근 방식 (0) | 2024.07.24 |