3.3

View in English

3.3 분산 시스템

개요와 동기

분산 시스템은 구성 요소가 둘 이상의 기계에서 실행되며 네트워크를 통해 조율하는 모든 시스템입니다. 네트워크를 건너 프로세스 경계를 넘는 순간, 단일 프로세스 안에는 존재하지 않는 어려운 진실들을 물려받습니다. 네트워크는 신뢰할 수 없고 지연은 변합니다. 메시지는 유실되고, 중복되고, 지연되고, 순서가 바뀔 수 있습니다. 원격 구성 요소는 스스로 실패합니다. 공유 시계가 없습니다. 고전적인 ”분산 컴퓨팅의 오류“(네트워크는 신뢰할 수 있다, 지연은 0이다, 대역폭은 무한하다, 토폴로지는 바뀌지 않는다)는 장애를 일으키는 가정을 정확히 가리킵니다. 여러분의 일은 인시던트 중에 다시 발견하는 대신 처음부터 이런 현실에 맞춰 설계하는 것입니다.

대규모 조직에서 분산은 선택이 아닙니다. 국가적 또는 전 세계적 규모를 제공하거나, 여러 부서를 잇거나, 고가용성이 필요한 모든 시스템은 많은 기계, 데이터 센터, 흔히 리전에 걸칩니다. 기업은 분산 트랜잭션 시스템, 이벤트 파이프라인, 다중 리전 배포를 운영합니다. 정부는 각 기관이 자기 시스템을 소유하고 아무도 전체를 통제하지 않는 기관 간 통합을 운영합니다. 여기서 견고한 설계와 취약한 설계의 간극은 헤드라인 장애, 놓친 급여 지급, 규제상의 결과로 나타납니다. 이 장의 기법들(일관성 추론, 멱등성, 백오프가 있는 재시도, 서킷 브레이커, 사가, 분산 관측 가능성)이 표준적인 방어입니다.

분산 시스템에서 가장 어려운 부분은 실패가 부분적이고 간헐적이라는 점입니다. 단일 기계 프로그램은 동작하거나 충돌합니다. 분산 시스템은 반쯤 동작할 수 있습니다. 일부 요청은 성공하고, 일부는 시간 초과되고, 일부는 조용히 유실되는 것이 동시에 일어납니다. 이 장은 대규모 팀이 부분 실패 아래서 우아하게 성능이 저하되고 이해 가능한 상태를 유지하는 시스템을 짓게 해 주는 추론과 패턴에 초점을 맞춥니다.

핵심 원칙

  • 네트워크는 신뢰할 수 없습니다. 모든 원격 상호작용을 느리거나, 실패하거나, 중복되거나, 순서가 바뀔 수 있다고 가정하고 설계하십시오.
  • 파티션 중에는 완벽한 일관성과 완벽한 가용성을 동시에 가질 수 없습니다. 상호작용마다 의도적으로 선택하고(CAP/PACELC), 파티션이 없을 때도 지연은 비용임을 기억하십시오.
  • 연산을 멱등하게 만드십시오. 연산을 안전하게 재시도할 수 있다면 분산 실패 처리의 대부분이 다룰 만해집니다.
  • 모든 원격 호출에는 타임아웃이 필요합니다. 끝없는 대기는 느린 의존성 하나를 시스템 전체의 장애로 바꿉니다.
  • 비즈니스가 허용하는 곳에서는 최종 일관성을 선호하되 명시적으로 하십시오. 사용자와 감사자는 오래된 데이터를 볼 수 있는 때를 이해해야 합니다.
  • 실패를 격리하십시오. 벌크헤드와 서킷 브레이커는 하나의 실패하는 구성 요소가 전부로 연쇄하는 것을 막습니다.
  • 볼 수 없는 것은 디버깅할 수 없습니다. 분산 흐름은 모든 홉에 걸친 상관된 추적, 지표, 로그를 요구합니다.
  • “정확히 한 번 전달”은 신화이고, 정확히 한 번 처리는 엔지니어링의 성취입니다. 중복 제거를 곁들인 최소 한 번 전달로 설계하십시오.

권장 사항

CAP와 PACELC로 일관성을 추론한다

CAP 정리는 네트워크 파티션 동안 시스템이 일관성(모든 읽기가 최신 쓰기를 봄)과 가용성(모든 요청이 응답을 받음) 중에서 선택해야 한다고 말합니다. PACELC는 두 번째 거래를 더합니다. 그렇지 않을(Else) 때, 즉 파티션이 없을 때도 지연(Latency)과 일관성(Consistency)을 맞바꿉니다. 이것을 시스템 전체의 라벨로 찍지 마십시오. 연산마다 결정하십시오. 은행의 잔액 이체는 강한 일관성이 필요하며 이중 지출의 위험을 지느니 거부합니다. 소셜 피드나 상품 조회 카운터는 가용성과 속도를 위해 오래됨을 받아들일 수 있습니다. 각 데이터 흐름이 어떤 일관성 모델(강한, 인과적, 자신의 쓰기 읽기, 최종)을 쓰는지 적어 두어, 시스템이 실제로 제공하지 않는 보장을 아무도 가정하지 않게 하십시오.

멱등성, 타임아웃, 재시도, 백오프를 함께 만든다

이 네 가지 기법을 하나의 패키지로 다루십시오. 모든 원격 연산에 타임아웃을 주어 멈춘 의존성이 스레드를 영원히 막지 못하게 하십시오. 실패하면 재시도하되, 반복해도 안전한 연산에만 하십시오. 반복해도 안전하다는 것은 멱등하다는 뜻입니다. 각 요청에 고유 키를 부여하고 수신자가 중복 제거하게 해서, 재시도된 “카드 청구”가 두 번 청구하지 않게 합니다. 재시도 간격을 지수 백오프와 지터로 두어, 짧은 끊김을 자초한 서비스 거부로 바꾸는 동기화된 재시도 폭풍을 피하십시오. 영원히 재시도하는 것은 실패를 옮기기만 하므로 재시도 횟수와 전체 시간 예산에 상한을 두십시오. 멱등성이 없으면 재시도는 위험합니다. 백오프가 없으면 재시도는 파괴적입니다.

서킷 브레이커와 벌크헤드로 연쇄를 막는다

서킷 브레이커는 의존성 호출을 지켜보다가 임계 횟수의 실패 후 “열립니다”. 어려움을 겪는 서비스에 더 많은 요청을 쌓는 대신 쿨다운 기간 동안 빠르게 실패한 뒤, “반쯤 열려” 복구를 시험합니다. 이는 느린 다운스트림 서비스가 모든 호출자의 스레드를 소진해 시스템 전체가 멈추는 연쇄를 막습니다. 벌크헤드는 자원(스레드 풀, 연결 풀)을 분할하여 한 의존성의 포화가 다른 것들이 필요로 하는 용량을 먹어 치우지 못하게 합니다. 둘 다 우아한 성능 저하와 짝지으십시오. 필수가 아닌 의존성을 쓸 수 없을 때 요청 전체를 실패시키는 대신 캐시되거나 기본값인 응답을 돌려줍니다.

분산 트랜잭션은 2단계 커밋이 아니라 사가로 관리한다

보통 여러 서비스나 데이터베이스에 걸쳐 단일 ACID(원자성, 일관성, 격리성, 지속성) 트랜잭션을 유지할 수 없습니다. 분산 2단계 커밋은 느리고, 자원을 잠그고, 가용성을 깎습니다. 대신 사가 패턴을 쓰십시오. 비즈니스 트랜잭션을 로컬 트랜잭션의 연속으로 모델링하고, 각각이 다음을 촉발하는 이벤트를 발행하며, 뒤 단계가 실패하면 취소하는 각 단계의 보상 행동을 둡니다. 사가는 두 가지 방식이 있습니다. 코레오그래피는 서비스들이 서로의 이벤트에 반응하며 중앙 제어기가 없습니다. 오케스트레이션은 중앙 조정자가 단계를 이끌며, 추론하고 모니터링하기가 더 쉽습니다. 사가는 최종 일관성을 받아들입니다. 시스템은 중간 상태를 거쳐 수렴합니다. 그러니 사용자 경험과 감사 추적이 “진행 중”과 “보상됨” 상태를 감안하도록 설계하십시오.

정확히 한 번을 최소 한 번 더하기 중복 제거로 다룬다

메시지 브로커는 실패를 가로질러 정확히 한 번 전달을 진정으로 보장할 수 없습니다. 브로커와 여러분이 달성할 수 있는 것은 멱등한 처리를 곁들인 최소 한 번 전달이며, 정확히 한 번의 효과를 냅니다. 소비자가 멱등성 키나 처리된 메시지 로그를 사용해 중복 메시지를 안전하게 처리하도록 설계하십시오. 브로커의 순서와 전달 보장을 정확히 아십시오. 스트리밍에서는 컨슈머 그룹, 파티션, 오프셋 관리를 의도적으로 쓰고 재처리를 안전하게 만들어, 버그 수정 후 다운스트림 상태를 손상시키지 않고 스트림을 재생할 수 있게 하십시오.

분산 흐름을 처음부터 끝까지 계측한다

서비스 경계를 가로질러 상관된 관측 가능성의 세 기둥을 채택하십시오. 모든 홉에 걸쳐 추적/상관 ID를 전파해, 단일 사용자 요청이 닿는 모든 서비스를 따라갈 수 있게 하십시오(분산 추적). 서비스별, 의존성별로 구조화된 지표(지연 백분위수, 오류율, 포화도, 처리량)를 내보내십시오. 상관 ID를 담은 구조화된 로그를 내보내십시오. 이 모두로 서비스 수준 목표를 정하고, 개별 기계 상태만이 아니라 오류율과 지연처럼 사용자가 실제로 느끼는 증상에 경보를 거십시오. 분산 시스템에서 관측 가능성은 선택적 도구가 아닙니다. 부분 실패 아래의 동작을 이해하는 유일한 방법입니다.

장단점

기법장점단점 / 비용
강한 일관성단순한 멘탈 모델. 오래된 읽기 없음파티션 중 낮은 가용성. 높은 지연. 조율 비용
최종 일관성높은 가용성. 낮은 지연. 확장 가능오래된 읽기. 복잡한 추론. 충돌 해결 필요
백오프가 있는 재시도일시적 실패를 자동으로 넘김잘못 쓰면 부하 증폭. 멱등성과 상한 필요
서킷 브레이커 / 벌크헤드연쇄 실패 방지. 빠른 실패복잡성 추가. 임계값 조정. 조기 작동 위험
사가 (2PC 대비)확장 가능. 가용. 분산 락 없음최종 일관성. 보상 로직. 추론이 더 어려움

핵심 트레이드오프는 조율과 독립성 사이에 있습니다. 기계를 가로지르고 싶은 모든 보장(일관성, 순서, 정확히 한 번)은 지연, 가용성, 복잡성의 비용이 듭니다. 기계들이 합의해야 하는데, 신뢰할 수 없는 네트워크 위의 합의는 비쌉니다. 기술은 비즈니스가 진정으로 필요로 하는 보장만 연산별로 사고, 나머지는 모두 우아한 성능 저하로 설계하는 것입니다. 일관성을 과하게 사면 시스템이 느려지고 취약해집니다. 부족하게 사면 몇 달 뒤 감사 실패로 드러나는 조용한 데이터 손상을 얻습니다.

팀과 논의할 질문

  1. 복원력 패턴이 공유 플랫폼 기본값으로 제공됩니까, 아니면 모든 팀이 타임아웃과 재시도를 다시 발명합니까? 이 장은 멱등성, 타임아웃, 한정된 재시도, 서킷 브레이커, 추적이 공유 라이브러리와 플랫폼 기본값에 한 번 만들어 넣을 때 가장 싸고 신뢰할 수 있다고 다룹니다. 큰 조직에서 각 팀이 직접 만들게 두면 일관성 없음이 보장됩니다. 일부 경로는 멱등하지 않은 연산을 재시도하고, 일부는 타임아웃이 없고, 일부는 상관 ID를 내보내지 않습니다. 서비스 표본을 감사하여 모든 원격 호출에 명시적 타임아웃을 설정하고 추적 ID를 끝까지 전파하는 서비스가 몇인지 세어 증거를 가져오십시오. 그 수가 낮다면 해법은 교육 메모가 아니라 플랫폼 투자입니다. 표준 기본값은 복원력을 테스트 가능하고 감사 가능하게 하기도 하며, 금융과 정부의 규제 기관이 점점 더 입증하기를 기대하는 것입니다.

  2. 타임아웃과 재시도 예산이 전체 호출 체인에 걸쳐 합쳐집니까, 아니면 깊은 요청이 스스로를 재시도해 장애로 몰고 갑니까? 단일 요청이 흔히 많은 홉을 건너는데, 각 계층이 독립적으로 자기 타임아웃으로 세 번씩 재시도하면 가장 안쪽의 실패가 곱해져 바깥 호출자가 사람이 견딜 수 있는 한계를 훨씬 넘어 기다립니다. 사용자와 마주하는 요청에 총 시간 예산을 정하고 체인을 따라 나누어, 안쪽 서비스가 남은 시간이 얼마나 적은지 알고 폭풍으로 재시도하는 대신 빠르게 실패하게 하십시오. 의존성 그래프와 실제 추적을 가져와, 최악의 타임아웃과 재시도 조합을 더해 사용자가 실제로 기다릴 시간과 비교하십시오. 지수 백오프와 지터, 총 시도 횟수의 상한은 짧은 끊김이 자초한 서비스 거부가 되는 것을 막습니다. 깊고 수다스러운 동기 체인이 여기서의 적이므로, 답은 비동기 흐름이나 더 적은 홉으로 이끌 수 있습니다.

  3. 설계가 견딘다고 주장하는 실패를 마지막으로 주입한 것은 언제이며, 예상치 못하게 무엇이 깨졌습니까? 복원력 패턴은 시스템을 일부러 실패시키기 전까지는 가설입니다. 인스턴스를 죽이고, 의존성에 지연을 더하고, 메시지의 일부를 떨어뜨리고, 배치를 두 번 재전달하십시오. 분산 시스템에서 흥미로운 실패는 부분적이고 간헐적이므로, 코드에서 옳아 보이는 서킷 브레이커나 사가 보상도 실제의 ‘완료됐을 수도 있는 타임아웃’ 아래서는 오동작할 수 있습니다. 설계 문서가 아니라 실제 게임 데이 또는 장애 주입 실행의 결과를 가져와, 어떤 경보가 울렸는지, 추적이 결함을 찾는 데 얼마나 걸렸는지, 재시도 폭풍이 형성되었는지 기록하십시오. 규제 부문에서 실패를 시험했다는 증거는 감사자에게 운영 복원력을 입증하는 일부입니다. 한 번도 해 본 적이 없다면, 첫 실험은 영향 범위가 좁고 중단 스위치가 있는 테스트 환경에 속합니다.

  4. 주요 데이터 흐름마다 소유 팀이 그것이 제공하는 일관성 모델을 말할 수 있으며, 그 선택이 비즈니스가 실제로 필요로 하는 것과 맞습니까? CAP와 PACELC는 연산마다 의도적인 선택을 강제하지만, 큰 조직의 기본은 표류입니다. 영향이 작은 카운터로 최종 일관성으로 시작한 흐름이 이제 결제를 승인하거나 접근을 허용하는 무언가에 재사용되는데 아무도 보장을 다시 검토하지 않습니다. 상충하는 고려는 실제입니다. 강한 일관성은 파티션 중 가용성과 없을 때도 지연의 비용이 들고, 최종 일관성은 오래된 읽기와 설계해야 하는 충돌 해결을 대가로 속도를 삽니다. 주요 데이터 흐름의 카탈로그를 가져와 각각에 현재 모델(강한, 인과적, 자신의 쓰기 읽기, 최종)과 오래되거나 잃은 읽기의 비즈니스적 결과를 표시하고, 보장이 이해관계가 정당화하는 것보다 강하거나 약한 불일치를 찾으십시오. 기업 금융과 정부의 급여 또는 신원 시스템에서 권위 있는 결정 뒤의 최종 일관성 읽기는 몇 달 뒤 감사 지적이나 부당한 거부로 드러나는 조용한 결함이므로, 그 검토 자체가 감사자가 보여 달라고 할 증거입니다.

  5. 여러 서비스에 걸친 비즈니스 트랜잭션은 중간 지점에서 어떻게 동작하며, 그것을 푸는 보상에 대해 누가 책임집니까? 2단계 커밋을 사가로 바꾸면 시스템이 눈에 보이는 중간 상태를 거치며, 한 단계가 성공하는 동안 뒤 단계가 실패해 그것을 되돌리는 보상 행동을 촉발할 수 있습니다. 큰 팀에서 이는 어려운 소유권 질문을 낳습니다. 승인-차변-대변-원장 체인은 흔히 여러 팀을 가로지르고, 한 팀이 구현을 잊은 보상은 돈이나 기록을 영구히 불일치하게 둡니다. 서비스들이 중앙 제어기 없이 서로의 이벤트에 반응해 흐름이 보기 어려운 코레오그래피와, 조정자가 단계를 이끌고 모니터링하지만 운영할 구성 요소가 생기는 오케스트레이션을 저울질하십시오. 가장 중요한 사가의 상태 다이어그램, 보상 행동과 그 소유자 목록, “진행 중”과 “보상됨” 상태가 사용자 경험과 감사 추적 양쪽에서 처리된다는 증거를 가져오십시오. 은행업과 공공 부문 사례 관리에서 규제 기관은 중간에 실패한 트랜잭션에 정확히 무슨 일이 있었는지 재구성하기를 기대하므로, 모델링되지 않은 중간 상태는 단순한 버그가 아니라 컴플라이언스 간극입니다.

  6. 메시지 소비자가 중복 및 순서가 바뀐 전달을 견디며, 브로커가 질문을 강제하기 전에 입증할 수 있습니까? 정확히 한 번 전달은 신화이므로 실제 보장은 최소 한 번이고, 각 메시지가 한 번만 순서대로 도착한다고 가정하는 소비자는 페일오버 후 브로커가 배치를 재전달하는 날 이중 처리를 합니다. 여러 팀에 걸쳐 위험은 누적됩니다. 공유 스트림의 멱등하지 않은 소비자 하나가 다른 팀이 의존하는 다운스트림 상태를 손상시킬 수 있고, 재생이나 파티션이 이벤트의 순서를 바꾸기 전까지 실패가 보이지 않기 때문입니다. 트레이드오프는 멱등성 키, 처리된 메시지 로그, 명시적 오프셋 및 파티션 처리의 엔지니어링 비용과 조용한 손상의 비용 사이에 있습니다. 핵심 스트림의 소비자 목록을 가져와 어느 것이 중복 제거하고 어느 것이 그저 바라는지 표시하고, 괜찮을 것이라는 보증이 아니라 실제 재전달 또는 재생 테스트의 결과를 가져오십시오. 기관 간 정부 데이터 교환과 기업 이벤트 파이프라인에서, 버그 수정 후 중복 사례나 청구를 만들지 않고 스트림을 안전하게 재생하는 능력은 운영상의 필수이면서 감사자가 입증해 보이기를 원할 것입니다.

분야별 관점

스타트업. 움직이는 부분이 두세 개이고 플랫폼 팀이 없다면, 인력을 댈 수 없는 분산 장치를 만들지 마십시오. 결제나 메시징 제공자가 이미 주는 SDK에 복원력이 있는 곳에서는 사고, 희소한 주의를 되돌릴 수 없는 피해를 막는 두 패턴에 쓰십시오. 돈을 움직이거나 계정을 바꾸는 모든 호출의 멱등성 키, 불안정한 연결이 이중으로 행동하지 않게 하는 한정된 재시도가 있는 타임아웃입니다. 네트워크 홉 수를 작게 유지하십시오. 추가하는 모든 동기 의존성은 알아챌 호출 대기자가 있기 전에 실패할 수 있는 또 하나이기 때문입니다.

소기업. 분산 시스템 전문가도 빠듯한 예산도 없을 테니, 이것을 사느냐 만드느냐의 문제로 다루십시오. 운영해야 하는 인프라보다 재시도, 순서, 중복 제거를 대신 처리하는 관리형 큐, 관리형 데이터베이스, 플랫폼을 선호하십시오. 위험을 평이한 말로 구성하십시오. 두 번 실행되거나 오래된 데이터를 돌려주면 고객에게 해가 될 연산이 무엇인지 알고, 벤더가 이미 제공하는 멱등성과 최소 한 번 기능을 켜십시오. 트랜잭션을 흉내 내려고 공유 데이터베이스로 서비스를 엮지 마십시오. 관리할 도구 없이 가장 어려운 분산 문제를 조용히 다시 만드는 일이기 때문입니다.

대기업. 핵심 문제는 많은 팀에 걸친 일관성이므로, 각 그룹이 직접 만들게 두는 대신 멱등성, 타임아웃, 한정된 재시도, 서킷 브레이커, 상관된 추적을 공유 플랫폼 기본값으로 제공하십시오. 흐름마다 일관성 모델과 전달 보장을 선언하는 방식을 표준화하고, 장애 주입과 게임 데이를 정기적으로 실행하고, 총 시간 예산이 깊은 호출 체인에 걸쳐 합쳐지게 해 한 서비스가 플랫폼을 장애로 재시도해 몰고 갈 수 없게 하십시오. 규모에서는 빠진 타임아웃 하나가 헤드라인 장애로 연쇄할 수 있으므로, 복원력을 사용자에게 보이는 증상에 대한 서비스 수준 목표를 갖춘 측정되는 능력으로 관리하십시오.

정부. 기관 간 시스템은 아무도 전체를 소유하지 않는다는 뜻이므로, 통제하지 않는 경계에 맞춰 설계하십시오. 최소 한 번 전달의 내구성 있는 큐, 안정적인 메시지 ID에 대한 중복 제거, 감사자에게 종단 간 추적을 주도록 기관 경계를 가로질러 흐르는 상관 ID입니다. 조달과 투명성 규칙은 각 통합의 일관성 모델과 전달 보장을 문서화하게 하고, 권위 있는 결정(신원, 자격, 급여)은 캐시된 엔드포인트가 아닌 강하게 일관된 읽기에 두게 합니다. 시험된 실패의 증거와 재구성 가능한 트랜잭션 이력을 인도물로 다루십시오. 운영 복원력과 대중에 대한 책임성은 내부의 예의가 아니라 계약적, 법적 의무이기 때문입니다.

사례

스타트업. 작은 핀테크 스타트업은 네트워크로 대화하는 움직이는 부분이 단 둘입니다. 앱과 제3자 결제 제공자입니다. 이 규모에서도 모든 청구 요청에 멱등성 키를 싣고 호출을 백오프가 있는 재시도로 감싸서, 불안정한 연결에서 응답이 떨어져도 고객에게 이중 청구하지 않습니다. 이를 건너뛰는 것은 첫날에는 싸게 느껴지지만, 실제 사용자에게 닿는 첫 중복 청구는 고객 지원 소동, 환불, 어린 회사가 감당할 수 없는 신뢰의 흠집을 치르게 합니다.

대기업. 한 글로벌 승차 공유 플랫폼은 여행 결제를 사가로 처리합니다. 카드 승인, 승객 차변, 운전자 대변, 원장 항목 기록이며, 각각 보상 되돌리기가 있는 로컬 트랜잭션입니다. 모든 단계가 멱등성 키를 싣기 때문에 네트워크 타임아웃 후의 재시도가 이중 청구하지 않습니다. 사기 점수 서비스 호출은 서킷 브레이커 뒤에 있어, 피크 시간에 성능이 저하되면 브레이커가 열리고 운행은 모든 승차를 막는 대신 보수적인 점수로 대체됩니다. 고객이 운행에 이의를 제기하면 분산 추적으로 엔지니어가 열두 개 서비스를 가로질러 몇 초 만에 따라갑니다.

정부. 한 국가 신원 서비스를 여러 기관이 검증에 사용합니다. 권위 있는 상태 확인을 위한 강하게 일관된 읽기(오래된 신원 데이터에 근거해 급여를 승인해서는 안 됩니다)와, 대량의 필수가 아닌 조회를 위한 최종 일관성의 캐시된 엔드포인트를 제공합니다. 기관 간 데이터 교환은 최소 한 번 전달의 내구성 있는 메시지 큐 위에서 돌고, 각 기관의 소비자가 메시지 ID로 중복 제거하므로 재전달된 레코드가 중복 사례를 만들지 않습니다. 상관 ID가 기관 경계를 가로질러 흘러, 감사자에게 시민의 데이터가 부서 간에 어떻게 이동했는지 종단 간 추적을 줍니다.

비즈니스 사례: 동기, ROI, TCO

분산 시스템 규율은 싸게 사고 그 부재는 파국적으로 치릅니다. 도입 비용은 멱등성, 타임아웃, 재시도, 서킷 브레이커, 추적을 공유 라이브러리와 플랫폼 기본값에 만들어 넣는 엔지니어링 시간입니다. 모든 팀에 이득이 되는 소소하고 대체로 일회성인 투자입니다. 도입하지 않는 비용은 주요 장애로 측정됩니다. 빠진 타임아웃 하나가 플랫폼 전체 장애로 연쇄하고, 멱등하지 않은 결제 경로가 수천 고객에게 이중 청구하고, 사가 없는 분산 트랜잭션이 데이터를 영구히 불일치하게 둡니다. 각각이 직접적인 매출, 복구, 평판 비용이 드는 헤드라인 인시던트이며, 규제 부문에서는 벌금도 따릅니다.

리더십에게는 가용성과 영향 범위를 중심으로 논거를 세우십시오. 복원력 패턴은 심각한 인시던트의 빈도와 지속 시간을 모두 직접 줄이며, 경영진이 이미 가동 시간과 평균 복구 시간으로 추적하는 지표입니다. 분산 관측 가능성은 MTTR에 대한 가장 큰 단일 지렛대입니다. 상관된 추적이 있는 팀은 서비스 간 인시던트를 훨씬 짧은 시간에 해결합니다. 이런 기능은 공유 플랫폼 기본값으로 제공할 때 가장 좋으므로 팀당 한계 비용은 낮고 조직 전체의 수익은 누적됩니다. TCO 논거는 단순합니다. 처음부터 복원력을 만들어 넣는 것은 문제를 강제하는 장애 뒤에 사후에 덧붙이는 것의 비용의 일부입니다.

안티패턴과 함정

  • 타임아웃 없음. 멈춘 의존성 하나가 모든 스레드를 소진하고 시스템 전체를 쓰러뜨립니다.
  • 멱등하지 않은 연산의 재시도. 중복된 부작용. 이중 청구, 중복 레코드, 이중으로 간 이메일.
  • 재시도 폭풍. 백오프와 지터 없는 동기화된 재시도가 작은 끊김을 장애로 증폭합니다.
  • 정확히 한 번 전달 가정. 브로커가 결국 전달할 중복 메시지에서 깨지는 소비자를 만드는 것.
  • 공유 데이터베이스를 통한 분산 트랜잭션. ACID를 흉내 내려고 하나의 데이터베이스로 서비스를 결합해 분산된 모놀리스를 다시 만드는 것.
  • 부분 실패 무시. 원격 호출이 완전히 성공하거나 완전히 실패한다고 가정하고, “시간 초과됐지만 완료됐을 수도 있음”에 대한 처리가 없는 코드.
  • 상관 ID 없음. 열 대의 기계에서 관련 없는 로그를 grep하며 서비스 간 인시던트를 디버깅하는 것.
  • 수다스러운 동기 호출 체인. 어느 한 홉만 느려도 요청 전체가 멈추는 깊은 동기 의존성 그래프.

성숙도 모델

  • 1단계: 시작. 원격 호출이 로컬 호출처럼 다뤄집니다. 타임아웃이 없거나 순진하고, 재시도가 없거나 무모하며, 실패가 시스템 전체로 연쇄합니다. 일관성이나 전달에 대한 공유된 관점이 없고, 서비스 간 인시던트를 디버깅한다는 것은 사후에 기계별 로그를 헤집는 것을 뜻합니다.
  • 2단계: 발전. 일부 팀이 타임아웃과 기본적인 재시도, 약간의 멱등성을 추가하지만, 실천은 서비스마다 일관되지 않습니다. 로그는 중앙화되었지만 상관되지 않아 홉을 가로지르는 요청 추적이 수동입니다. 분산 트랜잭션은 모델링되기보다 동작하기를 바라는 대상이고, 일관성 보장은 개별 엔지니어의 머릿속에 있습니다.
  • 3단계: 표준화. 멱등성, 한정된 재시도, 지터가 있는 백오프, 서킷 브레이커, 벌크헤드가 공유 라이브러리를 통해 조직 전체의 표준입니다. 보상 행동이 있는 사가가 여러 서비스 트랜잭션을 처리하고, 상관 ID를 갖춘 분산 추적이 갖춰져 있으며, 모든 주요 데이터 흐름이 일관성 모델과 전달 보장을 문서화합니다. 규칙은 각 팀에 맡겨지지 않고 적혀서 조직 전체에서 시행됩니다.
  • 4단계: 관리. 복원력이 존재하는 것만이 아니라 기준선에 대해 측정됩니다. 서비스와 의존성별 오류율, 지연 백분위수, 포화도, 처리량을 추적하고, 재시도 비율과 서킷 브레이커 개방률을 지켜보며, 사용자에게 보이는 증상에 서비스 수준 목표를 둡니다. 총 시간 예산이 호출 체인에 걸쳐 합쳐지는지 검증하고, 서비스 간 인시던트의 평균 복구 시간이 모니터링되는 지표이며, 장애 주입과 게임 데이 결과가 각 변경을 관문으로 통제하는 숫자에 공급됩니다.
  • 5단계: 오케스트레이션. 복원력이 조직 전체에 통합되고 조건에 적응하며 지속적으로 개선되는 플랫폼 기본값입니다. 장애 주입이 좁은 영향 범위로 프로덕션에서 일상적으로 실행되고, 시스템은 설계상 우아하게 성능이 저하되며, 일관성과 전달 선택은 부하와 비즈니스 이해관계가 이동함에 따라 재검토됩니다. 4단계의 지표가 자동화된 대응과 꾸준한 아키텍처 진화를 이끌어, 분산 자산이 인시던트를 그저 견디는 것이 아니라 매번 더 견고해집니다.

논의를 위한 아이디어

  1. 핵심 연산 중 어느 것이 오늘 진정으로 멱등하며, 어느 것이 조용히 그렇지 않습니까?
  2. 주요 데이터 흐름마다 팀이 일관성 모델과 전달 보장을 외워서 말할 수 있습니까?
  3. 마지막 연쇄 장애를 서킷 브레이커가 어디서 막았을 것입니까?
  4. 실패하는 단일 요청을 그것이 닿는 모든 서비스에 걸쳐 추적하는 데 현재 얼마나 걸립니까?
  5. “분산 트랜잭션” 중 어느 것이 실제로 운에 의존하고, 어느 것이 보상을 갖춘 진짜 사가입니까?
  6. 메시지 브로커가 한 시간 동안 모든 메시지를 두 번씩 재전달한다면 무엇이 깨지겠습니까?

핵심 요점

  • 네트워크는 신뢰할 수 없고 실패는 부분적이라고 가정하십시오. 모든 원격 상호작용을 느림, 유실, 중복, 순서 뒤바뀜에 맞춰 설계하십시오.
  • CAP/PACELC로 일관성 대 가용성을 연산마다 결정하고, 각 흐름이 제공하는 모델을 문서화하십시오.
  • 멱등성, 타임아웃, 한정된 재시도, 지터가 있는 백오프는 하나의 패키지입니다. 나머지 셋 없이 재시도를 채택하지 마십시오.
  • 서킷 브레이커와 벌크헤드가 실패를 가두고, 보상이 있는 사가가 동작하지 않는 분산 트랜잭션을 대체합니다.
  • 전달을 최소 한 번으로 다루고 처리를 멱등하게 만들어 정확히 한 번의 효과를 달성하십시오.
  • 상관된 추적, 지표, 로그가 분산 흐름을 이해하고 운영하는 유일한 방법입니다.

참고 문헌과 더 읽을거리

  • Martin Kleppmann, Designing Data-Intensive Applications
  • Andrew Tanenbaum and Maarten van Steen, Distributed Systems: Principles and Paradigms
  • Michael Nygard, Release It!: Design and Deploy Production-Ready Software
  • Sam Newman, Building Microservices
  • Chris Richardson, Microservices Patterns (sagas, transactional messaging)
  • Eric Brewer, “CAP Twelve Years Later” and Daniel Abadi on PACELC
  • Leslie Lamport, “Time, Clocks, and the Ordering of Events in a Distributed System”
  • Cindy Sridharan, Distributed Systems Observability
  • Nassim Nicholas Taleb’s notion of antifragility (as applied by resilience-engineering literature)