목차
단일 서버
- 가장 간단한 시스템
- 모든 컴포넌트(웹 앱, 데이터베이스, 캐시 등)가 단 한 대의 서버에서 실행되는 시스템
- 사용자 → 웹 서버 접속
- 도메인 이름 (ex. api.mysite.com) → 도메인 이름 서비스 DNS 질의 → IP 주소 변환 (ex. 15.125.23.214)
- DNS는 보통 제 3사업자가 제공하는 유료 서비스 이용
- IP 주소로 HTTP 요청 전달
- 요청 받은 서버는 HTML페이지나 JSON 형태 응답 반환
- 도메인 이름 (ex. api.mysite.com) → 도메인 이름 서비스 DNS 질의 → IP 주소 변환 (ex. 15.125.23.214)
- 사용자 단말
- 웹 애플리케이션: 서버 구현용 언어(자바, 파이썬등), 클라이언트 구현용 언어(HTML, 자바스크립트 등) 사용
- 모바일 앱: 통신을 위해 HTTP 프로토콜 이용. 응답 데이터 포맷 JSON
- 사용자 → 웹 서버 접속
데이터베이스
- 사용자 증가 → 여러 서버
- 웹/모바일 트래픽 처리 서버(웹 계층) & 데이터베이스 서버(데이터 계층)
- 데이터베이스 유형
- RDBMS 관계형 데이터베이스
- 테이블과 열, 컬럼으로 표현, 조인 연산 O
- NoSQL 비관계형 데이터베이스
- 조인 연산 X
- 필요 상황: 낮은 응답 지연 시간 latency, 비정형 unstructured 데이터, 데이터의 직렬화 및 역직렬화만 필요한 경우, 큰 데이터 양
- 1) 키-값 저장소 key-value store
- 2) 그래프 저장소 graph store
- 3) 칼럼 저장소 column store
- 4) 문서 저장소 document store
- RDBMS 관계형 데이터베이스
수직적 규모 확장 vs 수평적 규모 확장
- 수직적 규모 확장 vertical scaling = 스케일 업 scale up
- 서버에 고사양 자원 (더 좋은 CPU, 더 많은 RAM 등)을 추가하는 행위
- 서버 유입 트래픽 양 적을 때, 좋은 선택
- 장점: 단순함
- 단점:
- 현실적 한계 (CPU, 메모리 무한 증설 불가)
- 장애에 대한 자동복구 failover 방안이나 다중화 redundancy 방안 제시 X (웹, 앱 중단 가능성 O)
- 수평적 규모 확장 = 스케일 아웃 scale out
- 더 많은 서버를 추가해 성능을 개선하는 행위
- 대규모 애플리케이션 지원, 좋은 선택
- 앞 설계 = 사용자 ↔ 웹 서버
- 다운 시 접속 불가
- 많은 사용자 → 응답 속도 느려짐, 접속 불가
- → 해결법: 부하 분산기 또는 로드 밸런서 load balancer 도입
로드밸런서
- 부하 분산 집합 load balancing set에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할
- 사용자 → 서버 : 로드밸런서의 공개 IP 주소 public IP adress로 접속
- 웹 서버: 클라이언트 접속 직접 처리 X
- 서버 ↔ 서버: 사설 IP 주소 private IP address 이용됨
- 사설 IP 주소: 네트워크에 속한 서버 사이의 통신에만 쓰이는 IP 주소, 인터넷 통해 접속 불가
- 로드밸런서 ↔ 서버: 사설 IP 주소 사용
- 부하 분산 집합에 하나의 웹 서버 추가 시
- 자동복구 문제 no failover 해소
- 웹 계층 가용성 availability 향상
- 서버 1 다운 시 모든 태래픽 서버 2로 전송됨 = 전체 사이트 다운 x
- 트래픽 급증으로 인해 감당 불가 시점, 웹 서버 계층에 더 많은 서버 추가 → 로드밸런스가 자동적으로 트래픽 분산
데이터베이스 다중화
- 많은 데이터베이스 관리 시스템이 다중화를 지원
- 서버 사이에 주 master - 부 slave 관계 설정, 데이터 원본은 주 서버에, 사본은 부 서버에 저장하는 방식
- 쓰기 연산 write operation : 마스터에서만 지원
- 주 데이터베이스: 사본 전달 → 부 데이터베이스(읽기 연산 read operation만 가능)
- 데이터베이스 변경 명령어(insert, delete, update 등)은 주 데이터베이스로만 전달됨
- 쓰기 연산 < 읽기 연산 → 주 데이터베이스 < 부 데이터베이스
- 이점
- 더 나은 성능: 읽기 연산이 부 데이터베이스 서버로 분산됨. 병렬 처리 쿼리 수 ↑
- 안전성 reliability: 데이터베이스 서버 일부 파괴 시에도 데이터 보존 가능
- 가용성 availability: 하나의 데이터베이스 서버 장애 발생 시에도 다른 서버 데이터 가져오기 가능
캐시
- 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 뒤이은 요청이 빨리 처리될 수 있도록 하는 저장소
- 웹 페이지 새로고침 할 때마다, 데이터 가져오기 위해 한 번 이상의 데이터베이스 호출 발생
- 애플리케이션 성능: 데이터베이스 얼마나 자주 호출하느냐에 따라 좌우 → 캐시: 문제 완화
캐시 계층 cahce tier
- 데이터가 잠시 보관되는 곳. 데이터베이스보다 훨씬 빠름
- 캐시 계층 사용시, 성능 개선 및 데이터베이스 부하 감소, 캐시 계층 규모 독립적으로 확장 가능
- 캐시 전략
- 읽기 주도형 캐시 전략 read-through caching strategy
- 요청 받은 웹 서버: 캐시에 응답 저장 유무 확인
- 저장 o → 데이터 클라이언트에 반환
- 저장 x → 데이터베이스 쿼리 → 캐시 저장 → 클라이언트에 반환
- 요청 받은 웹 서버: 캐시에 응답 저장 유무 확인
- 캐시할 데이터, 크기, 액세스 패턴에 맞게 전략 선택
- 읽기 주도형 캐시 전략 read-through caching strategy
- 캐시 서버 이용 방법
- API 제공
캐시 사용 시 유의할 점
- 데이터 갱신은 자주 일어나지 않지만, 빈번하게 참조 발생 시 고려
- 영속적으로 보관 데이터의 경우 캐시에 두는 것은 바람직 X
- 캐시 서버 재시작 시, 캐시 내의 모든 데이터 사라짐
- 만료 정책 필요
- 일관성: 데이터 저장소의 원본과 캐시 내의 사본이 같은지
- 장애 대처
- 캐시 서버를 한 대만 두는 경우 해당 서버가 단일 장애 지점 SPOF Single Point of Failure 이 될 수 있기 때문에
- 여러 지역에 걸쳐 캐시 서버 분산 필요
- 캐시 메모리
- 캐시 메모리가 너무 작으면 액세스 패턴에 따라, 데이터가 너무 자주 캐시에서 밀려나버려 eviction → 캐시 성능 저하
- 데이터 방출 eviction 정책
- 캐시가 꽉 차버렸을 때, 추가로 캐시에 데이터를 넣어여 할 경우, 기존 데이터 방출 필요
- LRU Least Recently Used: 마지막으로 사용된 시점이 오래된 데이터 내보내는 정책. 가장 널리 쓰이는 정책
- LFU Least Frequently Used: 사용 빈도가 가장 낮은 데이터를 내보내는 정책
- FIFO First In First Out: 가장 먼저 캐시에 들어온 데이터를 가장 먼저 내보내는 정책
콘텐츠 전송 네트워크 CDN
- 정적 콘텐츠 전송 시 사용. 지리적으로 분산된 서버의 네트워크
- 이미지, 비디오, CSS, JavaScript 파일 등 캐시 가능
- cf) 동적 콘텐츠 캐싱: (상대적 새로운 개념, 책 다루지 x) 요청 경로 request path, 질의 문자열 query string, 쿠기 cookie, 요청 헤더 request header 등의 정보에 기반해 HTML 페이지 캐싱
- 작동 방식
- 사용자 → 웹사이트 방문 → 가장 가까운 CDN 서버가 정적 콘텐츠 전달
- 사용자가 CDN 서버로부터 멀면 멀수록 웹사이트 천천히 로드
- 예)
- 사용자 A → image.png 액세스
- CDN 서버의 캐시에 해당 이미지 x → 원본 서버(ex. aws S3)에 요청해 파일 가져옴
- 원본 서버 → CDN 서버 반환. 응답 HTTP 헤더에는 해당 파일이 얼마나 오래 캐시되는지에 대한 값인 TTL Time to Live 포함
- CDN 서버 → 사용자 A 반환
- 사용자 B → 같은 이미지 image.png 액세스 → CDN 서버 전송
- 만료되지 않은 이미지에 대한 요청 → 캐시를 통해 처리
- 사용자 → 웹사이트 방문 → 가장 가까운 CDN 서버가 정적 콘텐츠 전달
CDN 사용 시 고려해야 할 사항
- 비용
- 적절한 만료 시한 설정
- CDN 장애에 대한 대처 방안
- 콘텐츠 무효화 방법
무상태 stateless 웹 계층
- 웹 계층을 수평적으로 확장하려면, 상태 정보(ex. 사용자 세션 데이터)를 웹 계층에서 제거 필요
- 바람직한 전략
- 상태 정보를 관계형 데이터베이스나 NoSQL과 같은 지속성 저장소에 보관
- 필요시 가져오도록 하는겂
- = 무상태 웹 계층
상태 정보 의존적인 아키텍처
- 상태 정보를 보관하는 서버
- 클라이언트 정보, 즉 상태를 유지하여 요청들 사이에 공유되도록 함
- 사용자의 세션 정보나 프로파일 이미지 같은 상태 정보가 서버에 저장됨
- 사용자 A를 인증하기 위해 HTTP 요청은 반드시 서버 1로 전송 필요
- 서버 2로 전송 시 실패
- 같은 클라이언트로부터의 요청: 항상 같은 서버 전송 필요
- 로드밸러서: 고정 세션 sticky session 기능 제공.
- 로드밸런서에 부담. 로드밸런서 뒷단 서버 추가 및 제거 난해
무상태 아키텍처
- 사용자로부터의 HTTP 요청은 어떤 웹 서버로도 전달 가능
- 웹 서버: 공유 저장소 shared storage 에서 데이터 가져옴
- 상태 정보: 웹 서버로부터 물리적 분리. 단순, 안정적, 규모 확장 용이
데이터 센터 data center
- 지리적 라우팅 geoDNS-routing, geo-routing
- 사용자 → 가장 가까운 데이터 센터로 안내
- geoDNS
- 사용자의 위치에 따라 도메인 이름을 어떤 IP 주소로 변환할지 결정할 수 있도록 해주는 DNS 서비스
- 다중 데이터센터 아키텍처의 난제
- 트래픽 우회: 올바른 데이터 센터로 트래픽을 보내는 효과적인 방법 필요
- 데이터 동기화 synchronization
- 테스트와 배포
메세지 큐
- 메세지의 무손실 durability을 보장하는 비동기 통신 asynchronous communication을 지원하는 컴포넌트
- 메세지의 무손실 durability: 메세지 큐에 일단 보관된 메세지는 소비자가 꺼낼 때까지 안전히 보관된다는 특성
- 메세지의 버퍼 역할
- 비동기적 전송
- 아키텍처
- 생산자(발행자. 입력 서비스) → 메세지 만들어, 메세지 큐에 발행 publish
- 큐: 소비자 혹은 구독자라고 불리는 서비스 또는 서버가 연결되어 있음
- 메세지 큐 이용 → 서비스 또는 서버 간 결합 느슨, 규모 확장성이 보장되어야 하는 안정적 애플리케이션 구성에 이점
- 생산자: 소비자 프로세스 다운 시에도 메세지 발행 가능
- 소비자: 생산자 가용 상태 아니여도 메세지 수신 가능
- 예) 사진 보정 애플리케이션
- 웹 서버: 사진 보정 작업(job) → 메세지 큐에 넣음
- 사진 보정 작업 worker 프로세스: 작업을 메세지 큐에서 꺼내어 비동기적으로 완료
- = 생산자, 소비자 서비스의 규모 독립적 확장 가능
- 큐 크기 ↑ → 작업 프로세스 ↑
- 큐 크기 ↓ → 작업 프로세스 ↓
로그, 메트릭 그리고 자동화
- 로그: 에러 로그 모니터링 중요.
- 서버 단위 모니터링 가능하지만, 단일 서비스로 모아주는 도구 활용 시 편리
- 메트릭: 사업 현황, 시스템 현재 상태 파악 용이
- 호스트 단위 메트릭, 종합 aggregataed 메트릭, 핵심 비즈니스 메트릭
- 자동화: 시스템 크고 복잡해지면 생산성 향상을 위해 자동화 도구 활용 필요
- ex. 지속적 통합 CI 도와주는 도구
- 개발 생산성 향상 가능
데이터베이스의 규모 확장
- 확장 두 가지 접근법: 수직적 규모 확장법, 수평적 규모 확장법
수식적 확장
- 기존 서버에 더 많은, 고성능 자원 증성
- 약점
- 데이터베이스 서버 하드웨어 한계 존재. CPU, RAM 등 무한 증설 불가
- SPOF Single Point of Failure 위험성
- 비용
수평적 확장
- 더 많은 서버 추가 → 성능 향상
- 샤딩 sharding 이라고도 부름
- 대규모 데이터베이스를 샤드 shard라고 부르는 작은 단위로 분할
- 모든 샤드는 같은 스키마 사용
- 샤드에 보관되는 데이터 사이에 중복 X
- 샤딩 키 설정
- 샤딩 키 = 파티션 키 partition key: 데이터가 어떻게 분산될지 정하는 하나 이상의 컬럼으로 구성됨
- 데이터 고르게 분할할 수록 하는 게 가장 중요
- 샤딩 도입 시 직면 문제
- 데이터의 재 샤딩 필요 경우
- 데이터가 너무 많아져서 하나의 샤드로 감당 불가
- 샤드 간 데이터 분포 불균등 → 어떤 샤드에 할당된 공간 소모가 빨리 진행 될 때
- 샤드 소진 shard exhaustion → 샤드 키 계산 함수 변경 → 데이터 재배치
- 유명인사 문제 (= 핫스팟 키 hotspot key): 특정 샤드에 쿼리 집중, 서버 과부하
- 조인과 비정규화 join and de-normalization:
- 여러 샤드 서버 분리 시, 여러 샤드에 걸치 데이터 조인 난해
- 해결) 데이터베이스 비정규화 → 하나의 테이블에서 쿼리 수행
- 데이터의 재 샤딩 필요 경우
'Boaz > Real-time Data and Kafka' 카테고리의 다른 글
[카프카 핵심 가이드 #2] 3장 카프카 프로듀서: 카프카에 메시지 쓰기 (0) | 2024.08.22 |
---|---|
[카프카 핵심 가이드 #1] 1장 카프카 시작하기 (0) | 2024.08.22 |
[대규모 실시간 데이터 처리 #4] 대규모 시스템 설계 기초. 12장 채팅 시스템 설계 (0) | 2024.08.04 |
[대규모 실시간 데이터 처리 #3] 대규모 시스템 설계 기초. 9장 웹 크롤러 설계 (0) | 2024.08.04 |
[대규모 실시간 데이터 처리 #2] 대규모 시스템 설계 기초. 2장~3장 개략적인 규모 추정, 시스템 설계 면접 공략법 (0) | 2024.07.28 |