단일 서버
- 모든 컴포넌트가 단 한대의 서버에서 실행되는 간단한 시스템
- DB, 웹, 캐시 등이 전부 서버 한대에서 실행된다.
요청처리흐름
- 사용자가 웹브라우저에 주소를 입력하면 브라우저에 캐시에 있는 도메인과 연결된 서버의 주소를 찾는다
- 없으면 DNS로 요청을 해서 서버의 주소를 가져온다
- 서버의 주소로 요청을 보낸 후 응답을 받는다.
- 응답을 토대로 브라우저가 화면을 렌더링 해준다.
데이터 베이스
- 위의 흐름에서 데이터베이스는 웹 서버와 통신을 한다.
- 비관계형 데이터베이스는 4가지로 분류된다.
- 키-밸류 저장소 ( etcd )
- 그래프 저장소
- 칼럼 저장소
- 문서 저장소 ( 몽고 )
- 비관계형 데이터베이스는 조인 을 지원하지 않는다.
- 비관계형 데이터베이스가 바람직한 경우
- 아주 낮은 응답 지연시간이 요구되는 경우
- 다루는 데이터가 비정형 이라 관계형 데이터가 아님
- 데이터 (JSON, YAML, XML 등) 를 직렬화 하거나 역직렬화 할수 있기만 하면 됨
- 아주 많은 양의 데이터를 저장할 필요가 있음
수직적 규모 확장 vs 수평적 규모 확장
- 스케일 업과 스케일 아웃
- 스케일 업
- 한대의 서버에 CPU나 메모리를 증설하는 방식
- 스케일 아웃
- 서버를 여러대 추가하여 로드밸런스로 연결시키는 방식
- 스케일업의 단점
- 무한대로 CPU와 메모리를 증설할 수 없다.
- 자동복구 ( failover ) 방안이나 다중화 방안을 제시하지 않는다.
- 서버에 장애가 발생하면 웹이나 앱이 완전히 죽는다.
로드밸런서
- 부하분산집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할
- 로드밸런서는 처음 흐름과 다르게 도메인 주소와 연결된게 웹서버의 IP가 아닌 로드밸런서의 공개 IP 주소와 연결된다.
- 더 나은 보안을 위해 서버간 통신( 로드밸런서와 서버)에는 사설 IP주소가 이용된다.
데이터베이스 다중화
- 보통 서버사이에 master서버와 slave서버 관계를 설정하고 데이터 원본은 master에 저장하고 사본은 slave에 저장하는 방식이다.
- write operation ( 쓰기 연산) 은 마스터에만 지원한다.
- 슬레이브는 마스터로부터 사본을 전달받으며 읽기 연산만 지원한다
- 데이터베이스를 변경하는 명령어들 가령 insert, delete, update 등은 주 데이터베이스로만 전달되어야 한다.
- 대부분의 애플리케이션은 읽기 연산의 비중이 매우 높다.
- 그래서 슬레이브 서버를 많이두고 마스터서버를 적게 둔다.
장점
- 더 나은 성능
- master-slave 다중화 모델에서 모든 데이터 변경 연산은 주 데이터베이스 서버로만 전달되는 반면 읽기 연산은 부 데이터베이스 서버들로 분산된다.
- 병렬로 처리될수 있는 쿼리의 수가 늘어나므로 성능이 좋아진다.
- 안전성
- 디비 서버 중 몇개가 파괴되어도 데이터는 보존된다.
- 가용성
- 디비의 데이터를 여러지역에 복제해둠으로써 하나의 디비서버에서 장애가 일어나도 다른 서버에 있는 데이터를 가져와 계속 서비스할 수 있게 된다.
시나리오
- 부 서버가 한대뿐인데 다운됐을 경우
- 읽기 연산이 모두 마스터 디비로 전달
- 즉시 새로운 슬레이브 디비 서버가 장애난 슬레이브 서버 디비를 대체
- 부 서버가 여러대인데 그중 한대가 다운됐을 경우
- 읽기 연산이 나머지 슬레이브 디비로 분산되며
- 새로운 슬레이브 디비 서버가 장애난 슬레이브 디비서버를 대체
- 주 디비서버가 다운되면
- 부 디비서버가 한개일 경우
- 슬레이브 서버중 한대가 새로운 마스터 서버가 될것이며 모든 디비 연산은 일시적으로 새로운 마스터 서버에서 수행된다.
- 그리고 새로운 슬레이브 서버가 추가된다.
- 하지만 이런 경우 부 서버에 보관된 데이터가 최신 상태가 아닐 수 있기 때문에 복구 스크립트를 돌려서 추가 해야 한다.
- 다중 마스터나 원형 다중화 방식을 도입하면 이런 상황에 대처하는데 도움이 될수도 있지만
- 해당 구성은 훨씬 복잡하다.
- 부 디비서버가 한개일 경우
- 더 나은 성능
캐시
- 캐시는 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소다.
- 애플리케이션의 성능은 데이터 베이스를 얼마나 자주 호출하느냐에 크게 좌우되는데 캐시는 그런 문제를 완화할 수 있다.
캐시계층
- 데이터가 잠시 보관되는 곳으로 데이터베이스보다 훨씬 빠르다.
- 별도의 캐시 계층을 두면 성능이 개선될 뿐 아니라 데이터베이스의 부하를 줄일수 있고
- 별도의 캐시 계층을 두면 성능이 개선될 뿐 아니라 데이터베이스의 부하를 줄일 수 있고 캐시 계층의 규모를 독립적으로 확장시키는것도 가능해 진다.
- 요청받은 웹 서버는 캐시에 응답이 저장되어 있는지를 본다.
- 만일 저장되어 있다면 해당 데이터를 클라이언트에 반환한다.
- 없는 경우 데이터베이스에 쿼리를 날린 후 데이터를 찾아 캐시에 저장한 뒤 클라이언트에 반환한다.
- 이러한 캐시 전략을 읽기 주도형 캐시 전략 이라고 부른다.
- 다양한 캐시전략이 있는데 캐시할 데이터 종류, 크기, 액세스 패턴에 맞는 캐시전략을 선택하면 된다.
- 캐시 서버를 이용하는 방법은 간단한데 대부분의 캐시 서버들이 일반적으로 널리 쓰이는 프로그래밍 언어로 API를 제공하기 때문이다.
캐시 사용시 유의할 점
- 캐시는 어떤 상황에서 바람직 한가 ?
- 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어난다면 바람직하다.
- 어떤 데이터를 캐시에 두어야 하는가?
- 캐시는 데이터를 휘발성 메모리에 두므로 영속적으로 보관할 데이터를 캐시에 두는 것은 바람직 하지 않ㄴ다.
- 예를 들어 캐시 서버가 재 시작되면 캐시 내의 모든 데이터는 사라진다.
- 중요한 데이터는 여전히 지속적 저장소(persistent data store)에 두어야 한다.
- 캐시에 보관된 데이터는 어떻게 만료 되는가 ?
- 이에 대한 정책을 마련해 두는것은 좋은 습관이다.
- 만료된 데이터는 캐시에서 삭제되어야 한다.
- 만료 정책이 없으면 데이터는 캐시에 계속 남게 된다.
- 만료 기한은 너무 짧으면 곤란한데 데이터베이스를 너무 자주 읽게 될것이기 떄문이다.
- 너무 길어도 곤란한데 원본과 차이날 가능성이 높아지기 때문이다.
- 일관성은 어떻게 유지되는가 ?
- 일관성은 데이터 저장소의 원본과 캐시 내의 사본이 같은지 여부다.
- 저장소의 원본을 갱신하는 연산과 캐시를 갱신하는 연산이 단일 트랜잭션으로 처리되지 않는 경우 이 일관성은 깨질수 있다.
- 여러 지역에 걸쳐 시스템을 확장해 나가는 경우 캐시와 저장소 사이에 일관성을 유지하는것은 어려운 문제다
- 장애에는 어떻게 대처할 것인가 ?
- 캐시 서버를 한대만 두는 경우 해당 서버는 단일 장애 지점이 되어버릴 가능성이 있다.
- 단일 장애 지점 이란?
- 어떤 특정 지점에서의 장애가 전체 시스템의 동작을 중단시켜버릴 수 있는 경우 우리는 해당 지점을 단일 장애 지점이라고 부른다.
- 단일 장애 지점을 피하려면 여러지역에 캐시 서버를 분산시켜야 한다.
- 캐시 메모리는 얼마나 크게 잡을 것인가 ?
- 캐시 메모리가 너무 작으면 액세스 패턴에 따라서는 데이터가 너무 자주 캐시에서 밀려나버려 ( eviction ) 캐시의 성능이 떨어지게 된다.
- 이를 막을 한가지 방법은 캐시 메모리를 과할당 하는것이다.
- 이렇게 하면 캐시에 보관될 데이터가 갑자기 늘어났을 때 생길 문제도 방지할 수 있게 된다.
- 데이터 방출 ( eviction ) 정책은 무엇인가 ?
- 캐시가 꽉 차버리면 추가로 캐시에 데이터를 넣어야 할 경우 기존 데이터를 내보내야 한다.
- 이것을 캐시 데이터 방출 정책이라 하는데 가장 널리 쓰이는 것은 마지막으로 사용된 시점이 가장 오래된 데이터를 내보내는 정책이다.
- 다른 정책으로는 사용빈도가 가장 낮은 데이터를 내보내는 정책이다
- FIFO 같은 것도 있으며 경우에 맞게 적용 가능하다.
CDN
- 정적 콘텐츠를 전송하는 데 쓰이는 지리적으로 분산된 서버의 네트워크이다.
- 이미지, 비디오, CSS, javascript 파일 등을 캐시할 수 있다.
- 어떤 사용자가 웹사이트를 방문하면 그 사용자에게 가장 가까운 CDN서버가 정적 콘텐츠를 전달하게 된다.
- 직관적으로도 당연하겠지만 사용자가 CDN 서버로부터 멀면 멀수록 웹사이트는 천천히 로드될 것이다.
동작
- 사용자 A가 이미지 URL을 이용해 image.png에 접근한다.
- URL의 도메인은 CDN 사업자가 제공한 것
- CDN 서버의 캐시에 해당하는 이미지가 없는경우, 서버는 원본 서버에 요청하여 파일을 가져온다. 원본서버는 웹서버일수도 있고 아마존 S3와 같은 온라인 저장소 일수도 있다.
- 원본 서버가 파일을 CDN서버에 반환한다. 응답의 HTTP 헤더에는 해당 파일이 얼마나 오래 캐시될 수 있는지를 설명하는 TTL 값이 들어 있다.
- CDN 서버는 파일을 캐시하고 사용자 A에게 반환한다. 이미지는 TTL에 명시된 시간이 끝날때 까지 캐시된다.
- 사용자 B가 같은 이미지에 대한 요청을 CDN 서버에 전송한다.
- 만료되지 않은 이미지에 대한 요청은 캐시를 통해 처리된다.
CDN 사용시 고려해야할 사항
- 비용
- CDN은 보통 서드파티에 의해 운영되며 CDN 이용자는 CDN으로 들어가고 나가는 데이터 전송 양에 따라 요금을 내게 된다.
- 자주 사용되지 않는다면 CDN에서 제외하도록 하자.
- 적절한 만료 시한 설정
- 시의성이 중요한 컨텐츠의 경우 만료 시점을 잘 정해야한다. 너무 길지도 짧지도 않아야 하는데
- 너무 길면 컨텐츠의 신선도가 떨어지고 너무 짧으면 원본 서버에 번번히 접속하게 되어서 좋지 않다.
- CDN 장애에 대한 대처 방안
- CDN 자체가 죽었을 경우 웹사이트/애플리케이션이 어떻게 동작해야 하는지 고려한다.
- 가령 일시적으로 CDN이 응답하지 않더라도 해당 문제를 감지하여 원본 서버로부터 직접 컨텐츠를 가져오도록 클라이언트를 구성하는 것이 필요할 수도 있다.
- 컨텐츠 무효화
- 아직 만료되지 않은 컨텐츠라 하더라도 아래 방법 가운데 하나를 쓰면 CDN에서 제거할 수 있다.
- CDN서비스 사업자가 제공하는 API를 이용하여 컨텐츠 무효화
- 컨텐츠의 다른 버전을 서비스 하도록 오브젝트 버저닝 이용
- 컨텐츠의 새로운 버전을 지정하기 위해서는 URL 마지막에 버전 번호를 인자로 주면 된다.
- 예를 들어 image.png?v=2와 같은 방식이다.
- 아직 만료되지 않은 컨텐츠라 하더라도 아래 방법 가운데 하나를 쓰면 CDN에서 제거할 수 있다.
CDN 사용시 변화된 부분
- 더이상 정적 컨텐츠를 웹서버를 통해 서비스 하지 않는다.
- 캐시가 DB부하를 줄여준다.
무상태 웹 계층
- 웹 계층을 수평적으로 확장하기 위해서는 상태정보 ( 사용자 세션 데이터와 같은)를 웹 계층에서 제거하여야 한다.
- 바람직한 전략은 상태 정보를 RDB나 noSql같은 지속성 저장소에 보관하고 필요할 때 가져오도록 하는것이다.
- 이렇게 구성된 웹 계층을 무상태 웹 계층이라 부른다.
상태 정보 의존적인 아키텍처
- 상태 정보를 보관하는 서버는 클라이언트 정보 즉 상태를 유지하여 요청들 사이에 공유되도록 한다.
- 무상태 서버와는 반대
- 로드밸런서 사용시 사용자 정보를 가지고 있는 서버에 접속해야 상태정보가 유지된다.
- 로드밸런서가 이를 지원하기 위해 고정 세션(stickey session)이라는 기능을 제공하는데
- 이는 로드밸런서에 부담을 준다.
- 게다가 로드밸런서 뒷단에 서버를 추가하거나 제거하기도 까다로워진다.
- 이들 서버의 장애를 처리하기도 복잡하다.
무상태 아키텍처
- 무상태 아키텍처는 사용자로부터의 HTTP 요청은 어떤 웹서버로도 전달될 수 있다.
- 웹서버에서 상태정보가 필요할 경우 공유 저장소에서 데이터를 가져온다.
- 상태정보가 분리되어 있기때문에 구조가 단순하고 안정적이며 규모 확장이 쉽다.
- 이 공유 저장소는 rdb일수도 있고 멤캐시드나 레디스같은 캐시 시스템일수도 있고 nosql일수도 있다.
데이터 센터
- 장애가 없는 상황에서 사용자는 가장 가까운 데이터 센터로 안내되는데 통상 이 절차를 지리적 라우팅이라 부른다.
- 지리적 라우팅에서 geoDNS는 사용자의 위치에 따라 도메인 이름을 어떤 IP주소로 변환할지 결정할수 있도록 해주는 DNS 서비스다
- 로드밸런서에 의해 지리적 라우팅이 작동할수도 있고
- 다른 시스템에 의해 라우팅이 작동할수도 있다.
- 다중 데이터센터 아키텍처를 만드려면 몇가지 기술적 난제를 해결해야 한다.
- 트래픽 우회
- 올바른 데이터 센터로 트래픽을 보내는 효과적인 방법을 찾아야 한다.
- GeoDNS는 사용자에게서 가장 가까운 데이터 센터로 트래픽을 보낼수 있도록 해준다.
- 데이터 동기화
- 데이터 센터마다 별도의 데이터베이스를 사용하기 때문에 장애가 자동으로 복구되어 트래픽이 다른 데이터베이스로 우회된다 해도 해당 데이터센터에는 찾는 데이터가 없을 수 있다.
- 이런 상황에서는 데이터를 여러 데이터센터에 걸쳐 다중화 하는것이다.
- 테스트와 배포
- 여러 데이터센터를 사용하도록 시스템이 구성된 상황이라면 웹 사이트 또는 애플리케이션을 여러 위치에서 테스트해보는것이 중요하다.
- 한편 자동화된 배포 도구는 모든 데이터센터에 동일한 서비스가 설치되도록 하는데 중요한 역할을 한다.
- 트래픽 우회
메시지 큐
- 메시지의 무손실을 보장하는 비동기 통신을 지원하는 컴포넌트
- 메시지의 버퍼 역할을 하며 비동기적으로 전송한다.
- 메시지 큐의 기본 아키텍처는 생산자 또는 발행자 ( 프로듀서/퍼블리셔 ) 라고 불리는 입력 서비스가 메시지를 만들어 메시지 큐에 발행한다.
- 큐에는 소비자 혹은 구독자 ( 컨슈머 / 섭스크라이버 ) 라고 불리는 서비스 혹은 서버가 연결되어 있는데 메시지를 받아 그에 맞는 동작을 수행하는 역할을 한다.
- 메시지 큐를 이용하면 서비스 또는 서버간 결합이 느슨해져서 규모 확장성이 보장되어야 하는 안정적 애플리케이션을 구성하기 좋다.
- 생산자는 소비자 프로세스가 다운되어 있어도 메시지를 발행할 수 있고, 소비자는 생산자 서비스가 가용한 상태가 아니더라도 메시지를 수신할 수 있다.
로그 메트릭 그리고 자동화
- 로그
- 에러 로그를 모니터링 하는것은 중요하다.
- 시스템의 오류와 문제를 쉽게 찾을 수 있기 때문
- 에러 로그를 서버단위로 모니터링 할 수도 있지만 로그를 단일 서비스로 모아주는 도구를 활용하면 더 편리하게 검색하고 조회할 수 있다.
- 메트릭
- 메트릭을 잘 수집하면 사업현황에 관한 유용한 정보도 얻고 시스템의 현재 상태를 손쉽게 파악할 수도 있다.
- 메트릭 가운데 유용한 메트릭 몇가지
- 호스트 단위 메트릭
- CPU, 메모리, 디스크 I/O에 관한 메트릭이 여기 해당한다.
- 종합 메트릭
- 데이터베이스 계층의 성능, 캐시 계층의 성능 같은 것이 여기 해당한다.
- 핵심 비지니스 메트릭
- 일별 능동 사용자 ( daily active user ), 수익, 재방문 같은것이 여기 해당한다.
- 호스트 단위 메트릭
- 자동화
- 시스템이 크고 복잡해지면 생산성을 높이기 위해 자동화 도구를 활용해야 한다.
- 가령 지속적 통합을 도와주는 도구를 활용하면 개발자가 만드는 코드가 어떤 검증 절차를 자동으로 거치도록 할 수 있어서 문제를 쉽게 감지할 수 있다.
- 이외에도 빌드, 테스트, 배포 등의 절차를 자동화 할 수 있어서 개발 생산성을 크게 향상시킬수 있다.
데이터 베이스의 규모 확장
- 저장할 데이터가 많아지면 DB에 대한 부하도 증가한다.
- 그때가 오면 DB를 증설할 방법을 찾아야 한다.
- 규모확장에는 두가지가 있다.
- 수평적 확장, 수직적 확장
수직적 확장
- 스케일 업이라고 불리우며 서버의 사양을 고성능으로 증설하는 방법이다.
- 스택오버플로는 2013년 한해 동안 방문한 천만명의 사용자 전부 단 한대의 마스터 데이터베이스로 처리하였다.
- 하지만 수직적 접근법에는 약점이 있다.
- 무한히 서버의 사양을 증설할 수 없다.
- SPOF
- 단일 실패지점이 될 확률이 크다.
- 단일실패지점: 실패했을경우 서버가 전부 멈춰버리는 지점
- 비용이 많이 든다.
수평적 확장
- 데이터베이스의 수평적 확장은 샤딩이라고 불리운다.
- 많은 서버를 추가함으로써 성능을 향상시킬수 있도록 한다.
- 샤딩은 대규모 데이터베이스를 샤드라고 부르는 작은 단위로 분할하는 기술을 일컫는다.
- 모든 샤드는 같은 스키마를 쓰지만 샤드에 보관되는 데이터사이에는 중복이 없다.
- 사용자 데이터를 어느 샤드에 넣을지는 사용자 ID에 따라 정한다.
- 예제는 사용자 아이디를 4로 나눈것을 해시함수로 사용하여 데이터가 보관되는 샤드를 정한다.
- 결과가 0이면 0번 샤드, 1이면 1번 샤드
- 샤딩 전략을 구현할 떄 고려해야 할 가장 중요한 것은 샤딩 키를 어떻게 정하느냐 하는것이다.
- 샤딩키는 파티션 키라고도 부르는데 데이터가 어떻게 분산될지 정하는 하나 이상의 칼럼으로 구성된다.
- 그럼 위의 예제 같은 경우 샤딩키는 사용자 ID 이다.
- 샤딩키를 통해 올바른 데이터베이스에 쿼리를 보내어 데이터 조회나 변경을 처리하므로 효율을 높일 수 있다.
- 샤딩은 디비 규모 확장을 실현하는 훌륭한 기술이지만 완벽하진 않다.
- 샤딩을 도입하면 시스템이 복잡해지고 풀어야할 문제도 늘어난다.
- 데이터의 재 샤딩
- 데이터가 너무 많아져서 하나의 샤드로는 더이상 감당하기 어려울 때
- 샤드간 데이터 분포가 균등하지 못하여 어떤 샤드에 할당된 공간 소모가 다른 샤드에 비해 빨리 진행될 때 ( 샤드 소진이라고 부른다 ) 이런 현상이 발생하면 샤드 키를 계산하는 함수를 변경하고 데이터를 재 배치 해야 한다. 안정 해시 기법을 활용하면 이 문제를 해결 할 수 있다.
- 셀레브리티 문제
- 핫스팟 키 문제라고도 부르는데 특정 샤드에 쿼리가 집중되어 서버에 과부하가 걸리는 문제다.
- 가령 자주 조회되는 데이터가 한 샤드에 몰려있다고 생각해보면 된다.
- 이럴 경우 샤드에는 읽기 연산 때문에 과부하가 걸리게 될것이다.
- 자주 접속되는 데이터를 균등하게 분배해야 할수도 있다. 아니면 각 샤드당 하나씩 분배해야 할수도 있다.
- 조인과 비정규화
- 하나의 디비를 여러 샤드 서버로 쪼개고 나면 여러 샤드에 걸친 데이터를 조인하기가 힘들어진다.
- 이를 해결하는 한 가지 방법은 디비를 비정규화하여 하나의 테이블에서 질의가 수행될수 있도록 하는 것이다.
- 데이터의 재 샤딩
백만 사용자, 그리고 그 이상
- 웹 계층은 무상태 계층으로
- 모든 계층에 다중화 도입
- 가능한한 많은 데이터를 캐시 할것
- 여러 데이터 센터를 지원할 것
- 정적 콘텐츠는 CDN을 통해 서비스 할것
- 데이터 계층은 샤딩을 통해 그 규모를 확장할 것
- 각 계층은 독립적 서비스로 분할할 것
- 시스템을 지속적으로 모니터링하고 자동화 도구들을 활용 할 것
'book > 대규모 시스템 설계 기초' 카테고리의 다른 글
4장 처리율 제한 장치의 설계 (0) | 2021.08.31 |
---|---|
3장 시스템 설계 면접 공략법 (0) | 2021.08.31 |
2장 개략적인 규모 추정 (0) | 2021.08.31 |
Uploaded by Notion2Tistory v1.1.0