책 리뷰/가상 면접 사례로 배우는 대규모 시스템 설계 기초
가상 면접 사례로 배우는 대규모 시스템 설계 기초 - 1장
eess
2024. 8. 14. 02:16
🔖 1장 : 사용자 수에 따른 규모 확장성
읽은 날짜 : 2024.08.13
지은이 : 알렉스 쉬
출판사 : 인사이트
기억하고 싶은 내용
✔️ 시스템 규모 확장 방법 정리
- 웹 계층은 무상태 계층으로
- 모든 계층에 다중화 도입
- 가능한 한 많은 데이터를 캐시할 것
- 여러 데이터 센터를 지원할 것
- 정적 콘텐츠는 CDN을 통해 서비스할 것
- 데이터 계층은 샤딩을 통해 그 규모를 확장할 것
- 각 계층은 독립적 서비스로 분할할 것
- 시스템을 지속적으로 모니터링하고, 자동화 도구들을 활용할 것
단일 서버 아키텍처
- 사용자 단말(웹/앱)에서 도메인으로 접속
- DNS에 도메인을 조회하여 IP 주소로 변환
- IP 주소로 HTTP 요청
- HTML이나 JSON 응답
데이터베이스
- 웹/모바일의 트래픽을 처리하는 서버와 데이터베이스 서버를 독립적으로 확장해 나갑니다.
- 데이터베이스는 관계형 / 비관계형 중 선택해야 합니다.
- 관계형 데이터베이스
- 테이블, 열, 컬럼으로 데이터를 표현하고, 테이블 조인 가능
- MySQL, Oracle, PostgreSQL 등
- 비관계형 데이터베이스(NoSQL)
- 테이블 조인 기능이 없다.
- CouchDB, Neo4j, Cassandra, Amazon DynamoDB 등
- NoSQL은 다시 네 분류로 나눌 수 있습니다.
- 키-값 저장소
- 그래프 저장소
- 칼럼 저장소
- 문서 저장소
- 대부분 관계형 데이터베이스가 적합하나, 다음의 경우 NoSQL을 고려해볼 수 있습니다.
- 아주 낮은 응답 지연시간이 요구될 때
- 다루는 데이터가 비정형이라 관계형 데이터가 아닐 때
- 데이터를 직렬화/역직렬화 할 수 있기만 하면 될 때
- 아주 많은 양의 데이터를 저장할 필요가 있을 때
- 관계형 데이터베이스
웹 계층의 수직적 규모 확장 vs 수평적 규모 확장
수직적 규모 확장(scale up)
- 서버에 고사양 자원(더 좋은 CPU, 더 많은 RAM 등)을 추가하는 것
- 트래픽 양이 적을 때 적합합니다.
- 장점 : 단순합니다.
- 단점 :
- 단일 서버에 자원을 증설하는 데에는 한계가 있습니다.
- 장애 발생시 서비스가 중단됩니다. 장애에 대한 자동복구 방안이나 다중화 방안이 필요합니다.
수평적 규모 확장(scale out)
- 더 많은 서버를 추가하여 성능을 개선하는 것
- 대규모 애플리케이션 지원에 좀 더 적합한 방식입니다.
- 로드밸런서가 필요해집니다.
로드밸런서
- 부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할
- 사용자 단말은 로드밸런서의 공개(public) IP로 접속하고, 로드밸런서는 보안을 위해 서버의 사설(private) IP로 통신합니다.
- 서버1이 다운되면 모든 트래픽은 서버2로 전송됩니다. ➡️ 장애 자동복구 & 가용성 향상!
데이터베이스 다중화 : master-slave 구조
- 원본은 주(master) 서버에, 사본은 부(slave) 서버에 저장하는 방식입니다.
- 쓰기 연산(insert, delete, update)은 주 서버에서만 지원합니다.
- 부 서버에서는 주 서버에서 그 사본을 전달받으며 읽기 연산(select)만 지원합니다.
- 대부분 애플리케이션은 읽기 연산의 비중이 훨씬 높아서 부 서버의 개수가 더 많습니다.
- 데이터베이스 다중화의 장점 :
- 데이터베이스 서버가 분산되어 병렬로 처리하는 질의(query)가 늘어나 성능 향상을 기대할 수 있습니다.
- 일부 데이터베이스 서버가 파괴돼도 다른 서버에 데이터가 보존됩니다.
- 지역적으로 여러 장소에 복제하여 장애가 발생해도 다른 서버에서 가져와서 계속 서비스가 가능해집니다.
- 추가적으로 생각해봐야 할 점
- 부 서버가 다운된 경우
- 부 서버가 한 대라면 읽기 연산은 일시적으로 주 서버가 처리하고 즉시 새로운 slave 서버 추가
- 부 서버가 여러 대라면 다른 부 서버가 읽기 연산 처리
- 주 서버가 다운된 경우
- 부 서버가 한 대라면 해당 서버가 새로운 주 서버가 되고 일시적으로 모든 연산 처리. 이후 새로운 slave 서버 추가.
- 부 서버에 보관된 데이터가 최신 상태가 아닐 수 있기 때문에, 없는 데이터는 복구 스크립트를 돌려서 추가.
- 부 서버가 다운된 경우
캐싱
- 캐시는 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 요청이 보다 빨리 처리될 수 있도록 하는 저장소입니다.
- 데이터베이스 부하를 줄이고 서버의 성능을 개선할 수 있습니다. 또한, 캐시 계층을 따로 두면 이를 독립적으로 확장시킬 수 있습니다.
- 읽기 주도형 캐시 전략(read-through caching strategy)
- 웹서버가 캐시에 응답이 저장되어 있는지 보고 있으면 해당 데이터를 클라이언트에 반환합니다.
- 없으면 데이터베이스에서 찾아서 캐시에 저장한 뒤 클라이언트에 반환합니다.
- 캐시 사용시 유의할 점
- 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어날 때 고려해볼 만 합니다.
- 영속적으로 보관할 데이터는 캐시에 두면 안 됩니다.
- 너무 짧지도 길지도 않은 만료 기한을 두어야 합니다.
- 저장소의 원본을 갱신하는 연산과 캐시를 갱신하는 연산이 단일 트랜잭션으로 처리되지 않는 경우 일관성이 깨질 수 있습니다.
- Scaling Memcache at Facebook [참고]
- 여러 지역에 걸쳐 캐시 서버를 분산시켜 단일 장애 지점이 되는 것을 피해야 합니다.
- 캐시 메모리가 너무 작으면 데이터가 너무 자주 캐시에서 밀려나버려 성능 저하가 발생할 수 있습니다. ➡️ 캐시 메모리 과할당
- 캐시 메모리가 꽉 차서 데이터를 방출해야 할 때 전략을 고려해야 합니다.
- LRU(Least Recently Used)
- LFU(Least Frequently Used)
- FIFO(First In First Out)
콘텐츠 전송 네트워크(CDN)
- CDN은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크입니다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있습니다.
- CDN 동작 과정
- 사용자가 정적 콘텐츠 접근하면 CDN 서비스 사용자가 제공한 URL로 요청합니다.(사용자와 가장 가까운 곳으로)
- 콘텐츠가 CDN 서버에 없으면 원본 서버에 요청합니다.
- 원본 서버가 CDN 서버에 파일을 반환합니다. 이때 응답 헤더에 *TTL 값이 들어있습니다. TTL에 명시된 시간이 끝날 때까지 캐시됩니다.
* TTL: Time To Live. 해당 파일이 얼마나 오래 캐시될 수 있는지 설명하는 값 - CDN 서버는 파일을 캐시하고 사용자에게 반환합니다.
- CDN 사용시 고려해야 할 사항
- CDN은 제3사업자에 의해 운영되므로 데이터 전송 양에 따라 비용이 발생합니다. 자주 사용되지 않는 콘텐츠는 빼는 것을 고려해야 합니다.
- 적절한 만료 시한 설정해야 합니다.
- CDN 장애 발생 시 이를 감지하여 원본 서버로부터 가져오도록 클라이언트를 구성할 필요가 있습니다.
- 캐시된 콘텐츠 무효화 : 캐시된 데이터와 원본 서버의 일관성을 유지하기 위해 아직 만료되지 않은 콘텐츠라도 CDN에서 제거할 수 있어야 합니다.
- CDN 서비스 사업자가 제공하는 API를 사용합니다.
- URL 마지막에 버전 번호를 주어 콘텐츠의 다른 버전으로 서비스할 수 있도록 합니다.
무상태 웹 계층
- 상태 정보(세션 등)를 웹 계층에서 제거하고, RDBMS나 NoSQL, 캐시 시스템(Memcached, Redis)에 보관해야 합니다.
- 웹 서버에서 상태 정보를 가지고 있으면 같은 사용자의 요청은 같은 서버로만 보내야 해서 자동 규모 확장이 어려워집니다.
- 상태 정보를 공유 저장소에서 가져오도록 하여 웹서버로부터 물리적으로 분리해야 합니다.
데이터센터
- 장애가 없는 상황에서 사용자는 가장 가까운 데이터센터로 안내됩니다. ➡️ 지리적 라우팅
- 데이터센터 중 하나에 장애가 발생하면 모든 트래픽은 장애가 없는 데이터센터로 전송됩니다.
- 기술적 난제
- 트래픽 우회 : 사용자에게서 가장 가까운 데이터 센터로 트래픽을 보내줘야 합니다.
- 데이터 동기화 : 데이터 센터마다 다른 데이터베이스를 사용하고 있는 경우 해당 데이터센터에 찾는 데이터가 없을 수도 있습니다. 이에 대한 보편적인 전략으로 데이터를 여러 데이터센터에 걸쳐 다중화하는 것입니다.
- 테스트와 배포 : 자동화된 배포 도구를 사용하여 모든 데이터 센터에 동일한 서비스가 설치되도록 할 수 있습니다.
메시지 큐
- 메시지의 무손실(메세지큐에 보관된 메시지는 소비가 꺼낼 때까지 안전히 보관됨)을 보장하는, 비동기 통신을 지원하는 컴포넌트
- 동작 방식
- 생산자(또는 발행자)가 메시지를 만들어서 메시지 큐에 발행
- 소비자(또는 구독자)가 메시지를 받아 그에 맞는 동작 수행
- 사용 예시
- 사진 보정 애플리케이션 : 시간이 오래 걸릴 수 있는 사진 보정 프로세스를 메시지 큐에 넣고 비동기적으로 완료
로그, 메트릭 그리고 자동화
- 서비스와 사업 규모가 커지면 로그, 메트릭, 자동화 같은 것들이 필요해집니다.
- 로그 : 에러 로그 모니터링. 로그를 단일 서비스로 모아주는 도구 활용하면 편리합니다.
- 메트릭 : 사업 현황에 관현 유용한 정보나 시스템 현재 상태를 파악할 수 있습니다.
- 호스트 단위 메트릭 : CPU, 메모리, 디스크 I/O
- 종합 메트릭 : 데이터베이스 계층의 성능, 캐시 계층의 성능
- 핵심 비즈니스 메트릭 : DAU, 수익, 재방문
- 자동화 : CI 도구로 빌드/테스트/배포 절차 자동화하여 개발 생산성을 향상시킬 수 있습니다.
데이터베이스 규모 확장
수직적 확장(scale up)
- 기존 서버에 더 많은 고성능의 자원(CPU, RAM, 디스크 등) 증설
- 한계
- 서버 하드웨어의 한계로 무한 증설은 불가능합니다.
- 단일 장애 지점으로 인한 위험성이 있습니다.
- 자원 증설에 대한 비용이 증가합니다.
수평적 확장(sharding)
- 더 많은 서버를 추가해서 성능 향상
- 대규모 데이터베이스를 샤드(shard)로 분할하는 기술입니다.
- 모든 샤드는 같은 스키마를 쓰지만, 샤드에 보관되는 데이터 사이에는 중복이 없습니다.
- 샤딩 전략 구현시 가장 중요한 것은 샤딩 키를 어떻게 정하느냐입니다. 데이터를 고르게 분할할 수 있도록 하는 게 중요하기 때문입니다. 예를 들어, user 데이터를 user_id % 4를 해시 함수로 사용하여 데이터가 보관되는 샤드를 정합니다.
- 샤딩 도입시 고려해야 할 점
- 데이터의 재 샤딩 :
- 데이터가 고르게 분포되지 못해 특정 샤드가 빠르게 소진될 수 있습니다.
- 샤드 키 계산 함수 변경하고 데이터 재배치. 안정 해시 기법 활용.
- 유명인사 문제 :
- 특정 샤드에 질의가 집중되어 과부하가 걸리는 문제.
- 예를 들어, SNS 애플리케이션을 구축할 때 유명인사가 전부 같은 샤드에 저장되면 과부하가 걸릴 수 있습니다.
- 조인과 비정규화 :
- 여러 샤드에 걸친 데이터를 조인하기가 힘들어지는 문제가 있습니다.
- 데이터베이스 비정규화하여 하나의 테이블에서 질의 수행
- 데이터의 재 샤딩 :
오늘 읽은 소감
- 처음 읽었을 때는 잘 이해가 가지 않았는데, 시간이 좀 흐르고 다시 읽어보니 대부분 이해가 되었다.
- 항상 생각의 깊이가 코드 수준, 단일 서버 아키텍처 수준으로 머물러 있다는 느낌이 들었는데 1장의 내용을 통해 시스템 설계의 큰 그림을 대략 이해할 수 있었다. 각 기술의 세부적인 개념을 차차 채워나가야겠다.
궁금한 내용 & 잘 이해되지 않는 내용
데이터 직렬화 / 역직렬화
- 데이터 직렬화(serialization)
- 데이터를 파일이나 데이터베이스에 저장하거나, 네트워크를 통해 전송할 수 있는 형식으로 변환하는 과정입니다.
- 직렬화의 결과는 일반적으로 바이너리 또는 JSON, XML 형식의 텍스트입니다.
- 예시 : JavaScript의 JSON.stringfy()
- 데이터 역직렬화(deserialization)
- 직렬화된 데이터를 원래의 데이터 구조나 객체로 변환하는 과정입니다.
- 예시 : JavaScript의 JSON.parse()
메시지 큐 사용 사례
언제 사용하면 좋을까?
- 즉시 처리되기 어려운 요청에 대해 응답을 먼저 보내주고 작업을 나중에 처리하고 싶을 때
- 어느정도 응답 지연이 허용되는 부가적인 기능
- 시스템에서 특정 이벤트가 발생할 때 작업을 처리해야 하는 경우
- 여러 서버가 동시에 작업을 처리해야 하는 경우
사용 사례
- 저장소에 대용량 파일 업로드 후 파일 변환이나 최적화 작업
- 푸시 알림이나 이메일 전송(비밀번호 재전송, 새로운 계정 생성 등)
- 전자상거래 시스템에서 주문 처리, 재고 관리, 결제 처리 등의 작업을 비동기적으로 처리
- 선착순 이벤트
- 쿠폰 발급
구현 기술
- RabbitMQ
- Apache Kafka
- AWS SQS(Simple Queue Service)
참고
도서 - 가상 면접 사례로 배우는 대규모 시스템 설계 기초 1장