들어가며
최근에 티스토리 서비스가 중단되는 경우가 있었습니다. 이러한 경험은 블로그를 찾는 독자들에게 불편함을 줄 수 있고, 광고로 수익을 얻는 티스토리에게도 손실을 줄 수 있습니다. 2022년에 발생한 데이터센터 화재로 인해 카카오는 서비스 장애 피해 보상액으로 약 275억 원을 지급했다고 합니다. 이러한 사례들을 보면, 가용성이 무척 중요하다는 것을 알 수 있습니다.
이번 글에서는 단일 장애 지점(SPOF)에는 어떤 것들이 있는지 알아보고, 그것을 해결하기 위한 방법, 그에 따른 사이드 이펙트(Side Effect)에 대해서 알아보겠습니다.
가용성(Availability)이란?
위키피디아에 따르면, 가용성은 서버와 네트워크, 프로그램 등의 정보 시스템이 정상적으로 사용 가능한 정도를 말합니다. 가용성은 정상적인 사용 시간(Uptime)을 전체 사용 시간(Uptime+Downtime)으로 나눈 값을 의미하는데요. 여기서 Uptime은 서비스가 정상적으로 운영되는 시간을 의미하고, Downtime은 서비스가 중단되는 시간을 의미합니다. 예를 들어, 100일 중 99일 동안 서비스가 정상적으로 운영되었다면, 가용성은 99%가 됩니다. 가용성이 높은 것을 고가용성(High Availability, HA)이라고 합니다.
고가용성은 흔히 가용한 시간을 비율로 99%, 99.9% 등으로 표현합니다. 1년에 계획된 것을 제외 5분 15초 이하의 장애시간을 허용한다는 의미인 five nines(99.999%)는 매우 높은 수준으로, 고품질의 데이터 센터에서 목표로 한다고 합니다. 예를 들어, AWS S3의 가용성은 99.99%라고 합니다. 이는 1년에 52.6분의 장애 시간을 허용한다는 의미입니다.
고가용성을 달성하기 위한 방법
고가용성을 달성하기 위해서는 SPOF를 제거하는 것이 필수적입니다. SPOF란 시스템의 구성 요소 중 하나가 동작하지 않으면 전체 시스템이 중단되는 요소를 의미합니다. 이러한 구성 요소의 고장은 전체 시스템의 고장을 초래할 수 있으므로, 이를 방지하기 위해서는 시스템에 중복성을 추가하거나 구축해야 합니다. 즉, 특정 구성 요소가 실패하더라도 다른 구성 요소가 정상적으로 작동하여 서비스가 지속될 수 있도록 설계해야 합니다.
이제, 각 SPOF에 대해서 알아보겠습니다.
서버가 SPOF인 경우
문제 상황
먼저 사용자, 서버, DB가 연결되어 있는 단순한 구조부터 시작하겠습니다. 서버 내에는 Nginx -> Tomcat과 같이 Web Server -> Web Application Server가 연결되어 있을 수 있습니다. 저는 서버로 뭉뚱그려서 표현하도록 하겠습니다.
현재 서버는 단일 서버로 구성되어 있습니다. OOM(Out Of Memory), 네트워크 장애, 자원 고갈, 하드웨어 장애와 같은 문제가 발생할 경우 서버의 고장이 전체 시스템의 고장으로 이어집니다.
이중화(다중화)와 로드 밸런서로 해결
서버가 SPOF인 문제를 해결하는 방법은 서버를 이중화하고, 로드 밸런서를 통해 트래픽을 분산하는 것입니다. 이중화는 동일한 애플리케이션을 여러 서버에 배포하여 한 서버가 다운되더라도 다른 서버가 서비스를 제공할 수 있도록 합니다. 로드 밸런서는 서버에 들어오는 트래픽을 여러 서버로 분산시켜주는 역할을 합니다.
로드 밸런서는 주기적으로 서버에 헬스 체크를 보내어 서버의 상태를 확인하고, 이상이 감지되면, 해당 서버로의 트래픽을 차단하고, 정상적인 서버로의 트래픽을 분산시킵니다. 위의 그림처럼 특정 서버가 고장나면, 그 서버로의 트래픽을 차단하고, 정상적인 서버로만 트래픽이 가도록 합니다.
문제점
동시성 이슈
기존 단일 서버에서는 동시성 문제를 상대적으로 간단하게 처리할 수 있었습니다. 단일 서버에서는 모든 요청이 동일한 서버로 들어와서 처리되었기 때문에 스레드 간의 동시성 문제만을 고려하면 되었습니다. 하지만 분산 환경에서는 요청이 여러 서버로 요청이 분산되기 때문에, 서버 간의 동기화 문제를 고려해야 합니다. 예를 들어, 단일 서버에서는 synchronized 키워드를 사용하여 스레드 간의 동기화를 처리할 수 있었다면, 분산 환경에서는 Redis나 Zookeeper와 같은 분산 락을 사용하여 동기화를 처리해야 합니다.
세션 정보
단일 서버에서는 세션 정보를 서버의 메모리에 저장하여 사용하는 경우가 많습니다. 하지만 분산 환경에서도 세션 정보를 메모리에 저장하게 되면, 로드 밸런서에 의해 다른 서버로 요청이 분산되었을 때, 세션 정보가 공유되지 않아 로그인 상태가 유지되지 않는 문제가 발생할 수 있습니다. 이를 해결하기 위해, 세션 정보를 데이터베이스나 Redis에 저장하여, 서버 간에 세션 정보를 공유할 수 있도록 해야 합니다.
모니터링 및 로깅
분산 환경에서는 여러 서버와 서비스로부터 로그와 메트릭이 발생하기 때문에, 수집과 통합이 어렵습니다. 또한 문제 발생 지점과 원인을 파악하기 어렵습니다.
배포
서버가 여러 대로 증가하면, 배포가 어려워집니다. 동일한 서비스가 다양한 버전으로 운영될 수 있고, 이것은 호환성 문제를 발생시킬 수 있습니다. 또한 서버가 많아질수록 배포 시간이 길어지고, 배포 중 장애에 대한 대응도 어려워집니다.
DB가 SPOF인 경우
문제 상황
현재 단일 데이터베이스 서버로 구성되어 있습니다. 데이터베이스 시스템의 부하가 커지거나, 디스크의 용량 초과, 하드웨어 장애 등이 발생하면 데이터베이스를 사용할 수 없게 됩니다. 데이터베이스가 필수인 현대의 서비스에서 데이터베이스가 다운되면 전체 서비스가 중단될 수 있습니다.
복제(Replication)로 해결
데이터베이스가 SPOF인 문제를 해결하기 위한 방법으로 데이터베이스 복제(Replication)이 있습니다. 데이터베이스 복제는 Writer DB 1대와 Reader DB 여러 대로 구성할 수 있습니다. Writer DB는 데이터를 읽고, 쓰는 역할을 담당하고, Reader DB는 데이터를 읽는 역할만 담당합니다. 특정 Reader DB가 다운되더라도 다른 Reader DB로 요청을 분산시켜 서비스를 제공할 수 있습니다. Writer DB가 다운될 경우에는 Reader DB 중 하나를 Writer DB로 승격시켜 서비스를 제공할 수 있습니다.
Writer DB가 다운될 경우 Reader DB 중 하나를 Writer DB로 승격시키는 것을 장애 조치(Failover)라고 한다.
위의 그림은 아주 간단하게 표현한 것으로, 데이터베이스의 복제를 통해 다중화했기 때문에 한 대의 DB가 죽어도 시스템 전체가 중단되지 않음을 나타냅니다.
복제(Replication)의 문제점
Writer DB에서 트랜잭션이 발생하면, 해당 트랜잭션의 변경 사항이 바이너리 로그에 기록됩니다. Writer DB가 Reader DB에 복제를 위한 바이너리 로그를 전달하는데 이 방식에는 비동기(Async), 동기(Sync), 반동기(Semi-Sync)이 있습니다.
동기 방식은 Reader에 바이너리 로그를 전송한 후 성공적으로 적용될 때까지 기다리는 것이고, 비동기 방식은 Reader에 바이너리 로그를 전송한 후 Reader가 이를 적용하는 것을 기다리지 않습니다. 동기 방식은 데이터의 일관성을 보장하지만 Reader가 바이너리 로그를 적용하는데 드는 시간만큼 Writer의 트랜잭션 처리 속도가 느려질 수 있습니다. 비동기 방식의 경우 동기 방식에 비해 Writer의 성능을 향상시킬 수 있지만 Reader가 최신 상태를 반영하지 못하는 일관성에 영향을 줄 수 있습니다. 이로 인해 복제 지연(Replication Lag)가 발생할 수 있습니다.
복제 지연은 트랜잭션 처리 속도, 네트워크 지연, 데이터베이스 성능 등에 따라 발생할 수 있습니다. 복제가 충분히 빠른 경우에는 문제가 없습니다. 하지만 복제 지연이 커진 경우에는 Writer DB를 통해 쓰기를 한 후, Reader DB를 통해 읽을려고 할 때, 아직 복제가 적용되지 않아서 읽을 수 없는 데이터 불일치 문제가 발생할 수 있습니다.
이러한 문제를 해결하기 위해서는 큰 트랜잭션을 작은 트랜잭션으로 나누어 처리하여서 트랜잭션 처리 속도를 최적화하거나 필요한 경우 Writer DB에서 읽기를 수행하는 방법 등이 있을 것 같습니다
가용 영역(Availability Zone, AZ)가 SPOF인 경우
문제 상황
아래와 같이 한 가용 영역에서 서버와 DB등을 운영할 때, 해당 가용 영역에서 장애가 발생할 경우 전체 서비스가 중단될 수 있습니다. 가용 영역이 장애가 날까라고 생각할 수도 있지만, 2022년 카카오 데이터센터 화재 사고도 그렇고, AWS 데이터센터 중단의 역사를 보면, 가용 영역에서 장애가 발생할 수 있다는 것을 알 수 있습니다.
다중 AZ로 해결
AWS의 경우 EC2를 생성할 때, 네트워크의 서브넷 설정을 통해 가용 영역을 지정할 수 있습니다. RDS의 경우에도 다중 AZ 배포 설정을 통해서 여러 가용 영역으로 DB를 분리할 수 있습니다.
다중 AZ의 문제점
다중 AZ를 사용할 경우 네트워크 지연과 비용적인 문제가 발생할 수 있습니다.
가용 영역 간 네트워크 지연을 설명하는 글에 따르면, 동일한 가용 영역에서 왕복 지연은 수 밀리초(sub millisecond)로 1ms보다 짧은 지연 시간을 가진다고 합니다. 반면, 동일한 리전에서 서로 다른 가용 영역의 왕복 지연은 단일 밀리초(single digit millisecond)로 1ms~9ms가 걸린다고 합니다.
동일한 가용 영역 내에서 전송되는 데이터의 경우 일부 무료일 수 있지만, 동일 리전 내 서로 다른 가용 영역에서 전송되는 데이터의 경우 비용이 부과될 수 있습니다.
마치며
이번 글에서는 단일 장애 지점에는 어떤 것들이 있고, 그것을 해결하기 위한 방법들, 그에 따른 사이드 이펙트들을 간단하게 알아보았습니다. 모든 장애 상황을 예방할 수는 없기 때문에, 모니터링을 고도화하고, 빠른 대응을 할 수 있어야 할 것 같습니다. 글을 읽어주셔서 감사합니다 :D
참고
- 카카오의 다짐
- 고가용성을 확보하기 위한 아키텍처 설계
- 단일 장애 지점(SPOF)이란? Single Point of Failure
- 우아한테크코스 6기 백엔드
- 위키피디아
'서버' 카테고리의 다른 글
확장 가능한 좋아요 기능 설계 및 구현하기 (4) | 2025.01.21 |
---|---|
커버링 인덱스를 활용한 페이지네이션 성능 개선하기 (1) | 2025.01.19 |
Docker Desktop 오류, "'com.docker.vmnetd'에 악성 코드가 포함되어 있어서 열리지 않았습니다." 해결 방법 (1) | 2025.01.13 |
Spring REST Docs로 믿을 수 있는 API 문서 만들기 (1) | 2025.01.12 |
무중단 배포(블루/그린 배포)로 서비스 중단 없이 배포하기 (5) | 2025.01.09 |