GN⁺: 분산 시스템 초보자를 위한 조언
(somethingsimilar.com)- 분산 시스템 엔지니어는 많은 경우 현장에서 실수로 인해 생긴 상처를 통해 배우게 됨
- 새로운 엔지니어들이 이러한 상처를 겪지 않도록 하기 위해 이 글을 작성함
분산 시스템은 자주 실패함
- 분산 시스템은 다른 소프트웨어 엔지니어링 분야와 달리 실패 확률이 높음. 특히 부분적인 실패 확률이 높음.
- 분산 컴퓨팅에서 일하지 않은 시스템 엔지니어는 "그냥 두 시스템에 쓰기를 보내면 될 거야" 또는 "성공할 때까지 계속 쓰기를 재시도하면 돼"와 같은 아이디어를 내놓음
- 네트워크 시스템은 단일 머신보다 더 자주 실패하며, 이러한 실패는 부분적일 가능성이 큼
- 쓰기 중 하나는 성공하고 다른 하나는 실패할 수 있으므로 이제 데이터의 일관된 보기를 얻으려면 어떻게 해야 할까? 이러한 부분 실패는 추론하기가 훨씬 더 어려움
- 스위치가 다운되거나, 가비지 컬렉션으로 인해 리더가 "사라지거나", 소켓 쓰기가 성공한 것처럼 보이지만 실제로는 실패하는 등의 문제가 발생할 수 있음. 로컬 메모리에서 읽는 것이 몇 개의 스위치를 통해 읽는 것보다 훨씬 안정적임
- "실패를 대비한 설계"를 해야 함
견고한 분산 시스템 작성은 비용이 더 많이 듦
- 견고한 분산 솔루션을 만들기 위해서는 단일 머신 솔루션보다 더 많은 비용이 듦.
- 가상 머신과 클라우드 기술이 분산 시스템 엔지니어링을 더 저렴하게 만들지만, 여전히 많은 비용이 필요함.
- 시뮬레이션은 유용하지만, 실제 분산 환경에서 발생하는 문제를 모두 해결할 수는 없음.
견고한 오픈 소스 분산 시스템은 드물음
- 많은 머신을 장기간 운영하는 비용은 오픈 소스 커뮤니티에 부담이 됨.
- 취미로 오픈 소스 코드를 작성하는 사람들은 분산 시스템의 많은 문제를 탐구하거나 해결할 재정적 자원이 부족함.
- 일부 문제는 기업 엔지니어들이 해결하지만, 그들의 우선순위가 항상 일치하지는 않음.
조정은 매우 어려움. 가능한 한 조정을 피해야 함
- 수평 확장성의 핵심은 독립성임. 머신 간의 통신과 합의를 최소화해야 함.
- 두 머신이 무언가에 대해 합의해야 할 때마다 서비스 구현이 더 어려워짐.
- Paxos 알고리즘은 구현하기 매우 어려움.
문제를 메모리에 맞출 수 있다면, 아마도 사소한 문제임
- 분산 시스템 엔지니어에게 단일 머신에 국한된 문제는 쉽다고 여겨짐.
- 데이터가 몇 개의 스위치 떨어져 있는 경우, 데이터를 빠르게 처리하는 것은 더 어려움.
"느림"은 가장 어려운 문제임
- "느림"은 사용자 요청을 수행하는 여러 시스템 중 하나 이상이 느리다는 것을 의미할 수 있음.
- 부분적인 실패는 그래프에 나타나지 않으며, 명확해지기 전까지는 문제 해결에 필요한 자원을 받기 어려움.
시스템 전반에 걸쳐 역압을 구현해야 함
- 역압은 제공 시스템에서 요청 시스템으로 실패를 신호하고, 요청 시스템이 이러한 실패를 처리하는 방법을 의미함.
- 역압 메커니즘이 없으면 연쇄적인 실패나 의도치 않은 메시지 손실이 발생할 가능성이 높음.
부분적으로 가용할 수 있는 방법을 찾아야 함
- 시스템의 일부가 실패하더라도 일부 결과를 반환할 수 있는 능력을 의미함.
- 예를 들어, 검색 시스템은 일정 시간 내에 모든 문서를 검색하지 못하면 수집된 결과를 반환함.
메트릭은 작업을 완료하는 유일한 방법임
- 메트릭을 노출하는 것은 시스템이 실제로 어떻게 작동하는지 이해하는 유일한 방법임.
- 로그 파일은 유용하지만, 종종 거짓말을 함. 성공 로그는 대부분의 경우 중복되므로 기록되지 않음.
평균이 아닌 백분위를 사용해야 함
- 백분위는 평균보다 더 정확하고 유용함. 평균은 종종 잘못된 결정을 내리게 함.
용량을 추정하는 방법을 배워야 함
- 작업을 수행하는 데 필요한 머신 수를 아는 것은 중요함.
- 예를 들어, 트윗 ID를 메모리에 얼마나 많이 저장할 수 있는지 계산하는 것과 같은 백지 계산을 자주 하게 됨.
기능 플래그는 인프라를 롤아웃하는 방법임
- 기능 플래그는 새로운 기능을 시스템에 롤아웃하는 일반적인 방법임.
- 기능 플래그를 사용하면 프로젝트에 대한 자신감을 얻고 실패 비용을 줄일 수 있음.
ID 공간을 현명하게 선택해야 함
- 시스템의 ID 공간은 시스템의 구조를 형성함.
- 예를 들어, Twitter API의 트윗 ID는 단순한 64비트 숫자로, 다른 데이터와 연결되지 않음.
데이터 로컬리티를 활용해야 함
- 데이터의 처리와 캐싱을 지속적인 저장소에 가깝게 유지하면 더 효율적임.
- 네트워크는 포인터 역참조와 fread(3)보다 더 많은 실패와 지연을 겪음.
캐시된 데이터를 지속적인 저장소에 다시 쓰는 것은 나쁨
- 많은 시스템에서 이 문제가 발생함. 특히 분산 시스템 경험이 적은 사람들이 설계한 시스템에서 자주 나타남.
컴퓨터는 생각보다 더 많은 일을 할 수 있음
- 경험이 적은 실무자들로부터 컴퓨터의 능력에 대한 잘못된 정보가 많음.
- 현대의 웹 서버는 수천 개의 요청을 몇 백 밀리초 내에 처리할 수 있음.
CAP 정리를 사용하여 시스템을 비판해야 함
- CAP 정리는 시스템을 구축하는 데 사용할 수 있는 것이 아님. 그러나 분산 시스템 설계를 비판하는 데 유용함.
서비스를 추출해야 함
- 서비스는 저장 시스템보다 높은 수준의 논리를 포함하는 분산 시스템을 의미함.
- 서비스 추출은 라이브러리를 만드는 것보다 더 빠르고 쉽게 배포할 수 있음.
GN⁺의 정리
- 분산 시스템 엔지니어링은 높은 실패 확률과 부분적인 실패로 인해 다른 소프트웨어 엔지니어링 분야와 다름.
- 견고한 분산 시스템을 작성하는 데는 더 많은 비용이 들며, 오픈 소스 커뮤니티에서는 드물게 나타남.
- 조정과 데이터 로컬리티, 역압, 부분적 가용성 등의 개념을 이해하고 구현하는 것이 중요함.
- 메트릭과 백분위 사용, 기능 플래그, ID 공간 선택 등의 방법을 통해 시스템의 효율성과 안정성을 높일 수 있음.
- CAP 정리를 사용하여 시스템을 비판하고, 필요할 때 서비스를 추출하는 것이 좋음.
Hacker News 의견
-
CALM (Consistency as Logical Monotonicity) 원칙이 CAP보다 이해하기 쉽고 더 근본적인 결과임
- Idempotence, CRDTs, WALs, Raft 모두 CALM 원칙의 특수 사례임
- 링크: CALM 원칙 논문
-
정확히 한 번의 전달은 불가능하며, 최대 한 번 또는 최소 한 번의 전달 중 하나를 선택해야 함
-
좋은 기사임. 8년 전의 글이지만 여전히 유효한 내용이 많음
-
과거의 논의 링크:
-
실용적이고 현실적인 설명이 좋음. "마이크로서비스" 같은 유행어가 없음
- 이 조언은 단일 시스템에도 적용될 수 있음
- IPC나 스레드 간의 조정 등 다양한 분산 구성 요소를 고려해야 함
- 단일 CPU에서 다중 CPU, 다중 컴퓨터까지 분산의 스펙트럼이 존재함
-
Lookout에서 일할 때 Jeff Hodges가 이 에세이를 발표했음
- 엔지니어링이 정치적이라는 점을 강조했음
- 10년이 지난 지금도 엔지니어링 리더십과 SRE/DevOps의 교차점을 잘 이해하는 사람이 드뭄
-
이 글의 저자와 함께 일한 경험이 있음
- Jeff는 매우 긍정적이고 배울 점이 많은 사람이었음
- 도전에 대해 솔직했고 멘토링과 조언에 매우 접근하기 쉬웠음
-
2013년 이후 많은 것이 변했음
- 당시에는 클라우드 서비스가 덜 성숙했음
- 현재는 AWS 같은 서비스를 사용하면 대부분의 분산 시스템 문제를 해결할 수 있음
- 이론적인 분산 컴퓨팅 개념에 대해 걱정할 필요가 거의 없음
- 실용적인 것들, 예를 들어 로깅, 디버깅, 백프레셔 등을 여전히 고려해야 함
- 가용성은 이론적으로 중요하지만 실제로는 덜 중요함
- 대부분의 회사는 몇 시간의 다운타임을 견딜 수 있음
- 분산 컴퓨팅의 이론적 및 실용적 측면을 다루는 1%의 엔지니어는 운이 좋음
- 과거에 분산 데이터베이스와 논문을 작성했지만, 실제로는 이러한 것들에 대해 걱정할 필요가 거의 없었음
- 링크: PostgreSQL fsync 문제
- 링크: ScalienDB
- 링크: 논문