개요
MSA 프로젝트를 진행하기에 앞서 대규모 시스템 설계에 필요한 사항들에 대해 알아볼 것이다.
대규모 시스템(Large-Scale System)?
대량의 데이터를 처리하고, 높은 트래픽을 감당하며, 분산 환경에서 확장 가능한 설계를 통해 신뢰성과 성능을 보장하는 시스템
특징
- 확장성 (Scalability): 사용량이 증가함에 따라 시스템 성능을 유지하기 위해 수평적/수직적 확장이 가능.
- 고가용성 (High Availability): 장애가 발생하더라도 시스템이 지속적으로 작동할 수 있도록 설계.
- 분산 처리 (Distributed Processing): 데이터를 여러 서버에 분산 저장 및 처리하여 부하 분산.
- 신뢰성 (Reliability): 데이터 손실 방지와 일관성 보장을 위해 장애 복구 메커니즘 활용.
주요 구성 요소
- 로드 밸런싱 (Load Balancing): 트래픽을 여러 서버로 분산하여 부하를 관리.
- 분산 데이터 저장소 (Distributed Databases): 데이터베이스를 샤딩하거나 복제하여 처리 속도 향상.
- 캐싱 시스템: Redis, Memcached 등으로 데이터 접근 속도를 최적화.
- 마이크로서비스 아키텍처: 서비스를 독립적으로 분리하여 유지보수성과 확장성을 향상.
대규모 스트림 처리(Large-Scale Stream Processing)
실시간으로 발생하는 대량의 데이터를 처리하고 분석하기 위한 시스템. IoT, 금융거래, 로그 분석, 추천 시스템 등에 사용.
특징
- 실시간 처리 (Real-Time Processing): 데이터가 발생하자마자 분석 및 반응.
- 확장성 (Scalability): 증가하는 데이터 양에 따라 처리 성능을 유지.
- 연속 처리 (Continuous Processing): 데이터 스트림의 끝이 없으며 지속적인 분석이 필요.
- 분산 처리 (Distributed Processing): 데이터를 여러 노드에서 병렬로 처리.
주요 구성 요소
- 데이터 스트림 플랫폼: Kafka, RabbitMQ와 같은 메시지 브로커를 통해 데이터를 전송.
- 스트림 처리 엔진: Apache Flink, Apache Spark Streaming, Apache Storm 등.
- 분산 저장소: HDFS, S3 등으로 데이터를 영구적으로 저장.
- 모니터링 및 알림: 실시간 데이터에 대한 상태 확인 및 이벤트 트리거 설정.
예제 흐름
- 데이터 소스 (센서, 로그 등)에서 이벤트가 발생.
- 메시지 브로커를 통해 스트림 데이터가 스트림 처리 엔진으로 전달.
- 처리 엔진이 데이터를 필터링, 집계, 변환 등 처리.
- 처리 결과를 저장소에 저장하거나 대시보드/알림 시스템에 전달.
요약 비교
동시 접속자와 TPS(Transactions Per Second)
1. 동시 접속자(Concurrent Users)
- 정의
- 특정 시점에 시스템에 동시에 접속하여 활동 중인 사용자 수를 의미.
- 모든 사용자가 항상 요청을 보내는 것은 아니며, 대기 상태인 경우도 포함.
- 특징
- 시스템의 부하(Load)를 측정하는 주요 지표.
- 트래픽 패턴 분석에 중요:
- 피크 타임(최대 트래픽) 동안 동시 접속자가 시스템에 미치는 영향 분석.
- 캐시 활용 및 세션 관리 최적화에 기여.
- 관련 기술
- 로드 밸런서: 트래픽을 서버에 균등하게 분산.
- 세션 관리: 메모리나 분산 캐시(Redis 등)를 활용한 동시 사용자 세션 유지.
2. TPS(Transactions Per Second)
- 정의
- 초당 처리 가능한 **트랜잭션(요청)**의 수를 나타냄.
- 트랜잭션: 데이터베이스 읽기/쓰기, API 요청, 파일 처리 등 단위 작업.
- 특징
- 시스템의 **처리 능력(Throughput)**을 나타내는 주요 성능 지표.
- TPS는 다음과 같은 요소에 의해 결정됨:
- 네트워크 대역폭
- 서버의 CPU와 메모리 성능
- 데이터베이스의 쿼리 처리 속도
- 애플리케이션의 코드 최적화 수준
- 일반적으로 동시 접속자 수와 밀접한 관계를 가짐:
- 동시 접속자가 증가하면 TPS 요구량도 증가.
3. 동시 접속자와 TPS 관계
- 동시 접속자는 시스템 부하를 결정하고, TPS는 그 부하를 처리하는 시스템의 능력을 평가.
- 예: 동시 접속자가 1,000명이고 1초당 20%의 사용자가 요청을 보낸다면 TPS는 200이 됨.
4. 최적화를 위한 고려 사항
- 동시 접속자
- 세션 클러스터링: 사용자를 여러 서버로 분산.
- 캐싱: 자주 조회되는 데이터를 메모리 캐시로 제공.
- TPS
- 데이터베이스 튜닝: 인덱스 최적화, 쿼리 개선.
- 비동기 처리: 요청 병렬화를 통해 처리 속도 향상.
- 메시지 큐 활용: RabbitMQ, Kafka 등으로 부하 완화.
요약
- 동시 접속자는 시스템 부하의 크기를 나타내고, TPS는 시스템이 해당 부하를 얼마나 잘 처리하는지 측정하는 지표
- 대규모 시스템 설계 시, 동시 접속자 증가에 따른 TPS 요구량을 충족하도록 아키텍처를 최적화해야 함
DB 최적화(읽기 요청 최적화/ 쓰기 요청 최적화)
1. 읽기 요청 최적화(Read Optimization)
- 목표
- 데이터베이스에서 읽기 속도를 높이고 부하를 분산하여 빠른 응답 제공.
- 방법
- 인덱스 최적화
- 자주 조회되는 열에 적절한 인덱스를 생성.
- 복합 인덱스 사용으로 여러 열을 동시에 검색 최적화.
- 캐싱 사용
- Redis, Memcached 등 캐시 시스템 활용.
- 자주 읽히는 데이터를 메모리에 저장해 DB 부하 감소.
- 쿼리 최적화
- 불필요한 데이터 조회 제거 (SELECT * 대신 필요한 열만 선택).
- 서브쿼리 대신 조인(Join) 사용.
- 쿼리 실행 계획(Explain)을 통해 병목 현상 분석.
- 읽기 복제 (Read Replica)
- 데이터베이스를 복제하여 읽기 전용 요청을 분산 처리.
- Master-Slave 구조로 주 서버 부하 감소.
- 데이터 파티셔닝
- 데이터를 논리적으로 나누어 특정 쿼리의 검색 범위를 축소.
- 인덱스 최적화
2. 쓰기 요청 최적화 (Write Optimization)
- 목표
- 데이터 입력, 업데이트, 삭제 요청의 처리 속도 향상과 동시성 관리.
- 방법
- 트랜잭션 크기 최소화
- 단일 트랜잭션에서 처리하는 작업을 최소화하여 잠금 시간 단축.
- 배치 작업 활용
- 대량의 데이터 쓰기 시 Batch Insert/Update를 사용해 한 번에 처리.
- 예: INSERT INTO ... VALUES (...), (...), (...);
- 인덱스 관리
- 불필요한 인덱스를 제거하여 쓰기 성능 저하 방지.
- 쓰기 요청 시 과도한 인덱스 갱신을 피하도록 설계.
- 비동기 쓰기
- 메시지 큐(Kafka, RabbitMQ 등)를 통해 쓰기 작업을 비동기로 처리하여 응답 시간 단축.
- 데이터 파티셔닝
- 쓰기 요청이 특정 파티션에 집중되지 않도록 데이터를 나누어 저장.
- 샤딩 (Sharding)
- 데이터를 여러 데이터베이스로 분산 저장하여 동시 쓰기 성능 향상.
- 쓰기 지연 처리
- 쓰기 요청을 일괄적으로 처리하기 위해 데이터 변경 사항을 캐시에 저장 후, 일정 주기로 DB에 반영.
- 트랜잭션 크기 최소화
3. 읽기와 쓰기 최적화의 균형
- 읽기 위주 시스템: 캐싱, 읽기 복제, 인덱스를 적극적으로 활용.
- 쓰기 위주 시스템: 샤딩, 배치 작업, 트랜잭션 최소화로 쓰기 성능 향상.
- 혼합된 시스템: 읽기와 쓰기 부하를 분석하여 적절한 분산 전략과 캐시 구조 설계.
4. 요약
데이터 일관성(Consistency) 유지 방법
분산 환경에서는 네트워크 지연, 노드 장애 등으로 인해 데이터 불일치가 발생할 수 있으므로, 다양한 기법과 전략을 활용해 일관성을 유지한다.
1. 데이터 일관성의 유형
- 강한 일관성 (Strong Consistency)
- 모든 노드가 항상 동일한 데이터를 보장.
- 데이터 변경 즉시 모든 복제본에 반영.
- 예: 은행 시스템(잔고 관리), 금융 거래.
- 최종 일관성 (Eventual Consistency)
- 시간이 지나면 모든 노드가 동일한 상태로 수렴.
- 실시간 강한 일관성이 필요 없는 경우 적합.
- 예: 소셜 미디어(게시물 좋아요 수).
- 약한 일관성 (Weak Consistency)
- 데이터 읽기 시 최신 상태를 보장하지 않음.
- 성능을 우선시하는 시스템에 적합.
- 예: 캐싱 시스템.
2. 데이터 일관성을 유지하기 위한 방법
- 분산 트랜잭션 관리
- 2PC (Two-Phase Commit)
- 모든 관련 노드에서 트랜잭션을 준비(Prepare)한 후, 커밋(Commit) 또는 롤백(Rollback)을 수행.
- 장점: 강한 일관성을 보장.
- 단점: 느린 성능과 높은 네트워크 비용.
- 3PC (Three-Phase Commit)
- 2PC의 단점을 보완하여 네트워크 장애 시 트랜잭션 상태를 더 명확히 관리.
- 2PC (Two-Phase Commit)
- 데이터 복제
- 리더-팔로워(Primary-Replica) 복제
- 리더 노드에서 데이터를 쓰고, 팔로워 노드에서 읽기.
- 일관성 유지 방법: 쓰기 작업 완료 후 복제본으로 데이터 복사.
- 쿼럼 기반 복제
- 읽기/쓰기 쿼럼을 설정해 다수 노드가 응답하면 요청 처리.
- 예: Cassandra, MongoDB.
- 리더-팔로워(Primary-Replica) 복제
- 데이터 충돌 해결
- 버전 관리
- 데이터에 버전을 부여하여 최신 데이터 결정.
- 예: DynamoDB의 벡터 클럭(Vector Clock).
- 자동 병합
- 충돌 발생 시, 미리 정의된 규칙에 따라 데이터 병합.
- 예: 최신 업데이트 시간 기준.
- 버전 관리
- 이벤트 소싱과 CQRS
- 이벤트 소싱(Event Sourcing)
- 데이터 변경 이력을 이벤트로 저장하여 언제든지 재구성 가능.
- 일관성 유지: 이벤트 순서를 보장.
- CQRS (Command Query Responsibility Segregation)
- 쓰기와 읽기 모델을 분리하여 최적화.
- 데이터 변경 시 읽기 모델을 비동기적으로 업데이트.
- 이벤트 소싱(Event Sourcing)
- 지연 보상 전략
- Saga 패턴
- 분산 트랜잭션을 작은 단계로 분리하여 보상 작업을 수행.
- 일관성 유지: 실패 시 이전 상태로 되돌림.
- 이중 쓰기 방지
- 같은 데이터를 여러 서비스에서 동시에 변경하지 않도록 동기화.
- Saga 패턴
- 정합성 검사
- 백그라운드 정합성 검사
- 주기적으로 데이터의 일관성을 확인하고 불일치 데이터를 수정.
- 예: 예약 시스템의 중복 예약 확인.
- 백그라운드 정합성 검사
- 데이터 파티셔닝과 샤딩
- 데이터를 논리적으로 분할하여 특정 노드에서만 일관성을 유지하도록 설계.
- 관련 요청이 특정 파티션/샤드에서만 발생하도록 제약.
3. 데이터 일관성 유지의 설계 고려 사항
- CAP 이론 이해
- Consistency (일관성), Availability (가용성), Partition Tolerance (분할 허용성) 중 하나를 포기해야 함.
- 대규모 시스템에서는 최종 일관성을 선택하는 경우가 많음.
- 트레이드오프
- 강한 일관성: 성능과 지연 시간에 악영향.
- 최종 일관성: 속도는 빠르지만, 데이터 일시적 불일치 발생 가능.
- 애플리케이션 요구사항 분석
- 금융 시스템: 강한 일관성 필수.
- 소셜 미디어: 최종 일관성 허용.
4. 요약
- 강한 일관성은 데이터 정확성을 보장하지만 성능 저하 우려.
- 최종 일관성은 성능과 확장성을 확보하면서 시간이 지나면 일관성을 유지.
- 분산 트랜잭션, 복제 전략, 이벤트 소싱, Saga 패턴 등을 활용해 대규모 시스템에서 요구사항에 맞는 일관성 모델을 선택해야 함.
모니터링(Monitoring)과 로깅(Logging)
시스템의 성능을 추적하고, 장애를 빠르게 탐지하며, 문제를 해결하는 데 필수적인 요소
1. 모니터링 (Monitoring)
- 목표
- 시스템의 상태를 실시간으로 추적하고, 성능 지표를 분석하여 이상 징후를 조기에 발견하고 대응.
- 주요 요소
- 성능 지표
- CPU 사용량: 시스템이 과부하 상태인지 모니터링.
- 메모리 사용량: 메모리 리소스가 부족한지 확인.
- 디스크 I/O: 디스크 읽기/쓰기 속도 모니터링.
- 네트워크 트래픽: 네트워크 대역폭 사용량 추적.
- TPS (Transactions Per Second), 응답 시간: 애플리케이션 성능 추적.
- 애플리케이션 모니터링
- 헬스 체크(Health Check): 애플리케이션의 정상 작동 여부를 확인.
- 업타임: 시스템 가용성을 추적.
- 슬로우 쿼리 추적: 데이터베이스에서 느리게 처리되는 쿼리 확인.
- 알림 및 경고 시스템
- 설정된 임계값을 초과하면 즉시 알림을 전송.
- 예: Prometheus + Alertmanager를 사용한 알림 설정.
- 분산 추적 (Distributed Tracing)
- Jaeger, Zipkin 등 도구를 활용해 마이크로서비스 간의 요청 흐름을 추적.
- 전체 시스템의 성능 병목 현상을 파악.
- 시계열 데이터 수집
- Prometheus, Grafana 등을 사용하여 시간에 따른 성능 데이터를 수집하고 대시보드로 시각화.
- 자동화된 복구 (Auto-Scaling)
- 시스템의 부하에 따라 자동으로 리소스를 확장하거나 축소.
- 성능 지표
- 모니터링 도구
- Prometheus: 시계열 데이터를 수집하고, Grafana와 연동해 대시보드 시각화.
- Grafana: 다양한 지표를 대시보드 형태로 시각화.
- Nagios, Zabbix: 서버의 상태 및 네트워크 트래픽 모니터링.
2. 로깅 (Logging)
- 목표
- 시스템에서 발생하는 이벤트를 기록하여 문제를 추적하고, 디버깅 및 분석을 용이하게 함.
- 주요 요소
- 로그 수준 (Log Level)
- DEBUG: 디버깅 정보 (개발 환경에서 주로 사용).
- INFO: 일반적인 정보 (시스템 상태, 시작/종료 메시지).
- WARN: 경고 (문제가 발생할 가능성 있음).
- ERROR: 오류 (문제가 발생했으며, 해결이 필요).
- FATAL: 치명적인 오류 (시스템이 중단될 수 있음).
- 중앙 집중식 로깅 (Centralized Logging)
- 로그를 여러 서버에서 수집해 중앙 서버로 모은 후, 분석을 용이하게 함.
- ELK Stack: Elasticsearch, Logstash, Kibana를 사용하여 로그 데이터를 수집, 저장, 시각화.
- EFK Stack: Elasticsearch, Fluentd, Kibana를 활용.
- 로그 집계 및 분석
- Logstash나 Fluentd와 같은 도구로 여러 로그를 실시간으로 집계하고 변환.
- 로그 분석을 통해 시스템 동작을 이해하고, 문제를 진단.
- 지속적인 로그 저장
- 중요한 로그는 장기간 보관하여 히스토리를 분석하고, 장애 발생 시 원인 분석을 진행.
- 예: S3, HDFS에 로그를 저장하여 장기 보관.
- 로그 포맷과 구조화
- JSON 형식으로 로그를 구조화하여 일관성 있게 로그를 관리.
- 로그 메시지에 요청 ID, 에러 코드, 타임스탬프 등의 중요한 정보를 포함.
- 분석 및 대응
- 로그를 분석하여 자동화된 대응 시스템을 설정하거나, AI/ML을 사용해 이상 탐지.
- 로그 수준 (Log Level)
- 로깅 도구
- ELK Stack (Elasticsearch, Logstash, Kibana): 로그 수집 및 시각화.
- Fluentd: 다양한 소스에서 로그를 수집하고 처리.
- Splunk: 실시간 로그 분석 및 대시보드 제공.
3. 모니터링과 로깅의 차이점
대규모 시스템의 테스트와 배포
테스트와 배포가 시스템의 안정성과 확장성을 보장하기 위해 중요한 과정.
효과적인 테스트와 배포 전략을 통해 장애를 예방하고, 빠르게 기능을 추가하며, 문제를 신속하게 해결할 수 있음.
1. 테스트
- 목표
- 품질 보장: 시스템이 요구 사항을 충족하고 성능이 최적화되었는지 검증.
- 안정성 확보: 시스템 변경이 기존 기능에 영향을 미치지 않도록 하기 위해.
- 주요 테스트 종류
- 단위 테스트 (Unit Testing)
- 개별 컴포넌트나 모듈을 독립적으로 테스트.
- JUnit, Mockito 등을 사용하여 코드의 논리적 정확성 검증.
- 통합 테스트 (Integration Testing)
- 여러 모듈 간의 상호작용을 테스트.
- 데이터베이스, 외부 API, 메시지 큐 등과의 통합 확인.
- Spring Boot Test, Postman 등을 활용.
- 기능 테스트 (Functional Testing)
- 시스템의 각 기능이 사양대로 작동하는지 검증.
- Selenium, Cypress 등을 사용하여 웹 애플리케이션의 UI 및 동작을 테스트.
- 부하 테스트 (Load Testing)
- 대규모 트래픽을 시뮬레이션하여 시스템의 성능을 테스트.
- JMeter, Gatling 등을 사용하여 TPS, 응답 시간, 동시 사용자 처리 능력 테스트.
- 스트레스 테스트 (Stress Testing)
- 시스템의 한계까지 부하를 가하여 장애 발생 시 시스템의 안정성 및 회복 능력 확인.
- Locust, Artillery 등을 사용하여 성능의 극한을 테스트.
- 회귀 테스트 (Regression Testing)
- 기존 기능에 대한 변경 사항이 새로운 오류를 유발하지 않도록 검증.
- 자동화된 테스트 스크립트를 통해 빠르고 일관되게 실행.
- 사용자 수용 테스트 (UAT, User Acceptance Testing)
- 실제 사용자 환경에서 시스템이 요구사항을 충족하는지 검증.
- 사용자가 직접 시스템을 테스트하여 실제 사용 상황을 재현.
- 단위 테스트 (Unit Testing)
- 테스트 자동화
- CI/CD 파이프라인에서 자동화된 테스트를 실행하여 빠르고 지속적인 검증.
- JUnit, TestNG, Selenium 등의 테스트 도구를 사용하여 테스트 자동화.
2. 배포 방식
- 목표
- 새로운 기능을 안전하게 배포하고, 시스템의 안정성을 유지하며, 빠르게 문제를 해결.
- 주요 배포 방식
- 블루/그린 배포 (Blue/Green Deployment)
- 블루 환경(현재 운영 환경)과 그린 환경(새로운 버전)을 분리하여 동시에 운영.
- 새 버전의 애플리케이션을 그린 환경에 배포한 후, 문제 없으면 트래픽을 그린 환경으로 전환.
- 장점: 빠르고 안전한 롤백 가능, 트래픽 전환으로 다운타임 최소화.
- 카나리 배포 (Canary Deployment)
- 전체 시스템에 배포하지 않고, 일부 사용자에게만 새 버전을 배포하여 안정성을 확인.
- 점진적으로 새로운 버전을 배포하여 문제 발생 시 빠르게 대처 가능.
- 장점: 리스크를 최소화하면서 배포.
- 롤링 배포 (Rolling Deployment)
- 시스템의 일부 인스턴스를 하나씩 새로운 버전으로 교체하며 배포.
- 서버의 중단 없이 점진적으로 업데이트가 이루어짐.
- 장점: 다운타임 없이 배포 가능, 점진적인 테스트와 롤백이 가능.
- 자동화된 배포 (Automated Deployment)
- CI/CD 도구를 사용하여 코드 변경 사항이 자동으로 배포되고, 테스트가 자동으로 실행.
- Jenkins, GitLab CI, CircleCI 등의 도구를 사용하여 지속적인 통합과 배포를 실현.
- 서버리스 배포 (Serverless Deployment)
- AWS Lambda, Google Cloud Functions 등의 서버리스 플랫폼을 활용하여 관리형 환경에서 애플리케이션 배포.
- 서버 관리 없이 자동으로 확장 가능하고, 이벤트 기반으로 배포와 실행.
- 블루/그린 배포 (Blue/Green Deployment)
- CI/CD 파이프라인
- Continuous Integration (CI): 개발자들이 코드를 리포지토리에 푸시할 때마다 자동으로 빌드 및 테스트를 수행.
- Continuous Delivery (CD): 안정된 상태의 소프트웨어가 언제든지 프로덕션 환경에 배포될 준비가 되어 있는 상태로 유지.
- Jenkins, GitLab CI, ArgoCD 등을 사용하여 배포 자동화.
3. 대규모 시스템 배포 시 고려 사항
- 롤백 전략: 배포 후 문제가 발생할 경우 이전 버전으로 쉽게 되돌릴 수 있는 계획 수립.
- 모니터링 및 알림: 배포 후 시스템 상태를 실시간으로 모니터링하고 이상이 발견되면 즉시 알림을 제공.
- 스케일링: 배포 시 시스템 부하를 예측하여 적절히 리소스를 확장하거나 축소.
- 배포 후 테스트: 프로덕션 환경에 배포 후, 실제 사용자 환경에서 기능이 정상적으로 작동하는지 확인.
정리
- MSA 프로젝트를 구성할 때 동시 접속자, TPS, DB 최적화, 데이터 일관성 유지, 모니터링, 로깅, 테스트 및 배포까지 코드를 치는 것 외에도 신경 써야할 부분이 많음.
- 위 사항들을 프로젝트의 요구사항에 맞게 잘 녹여내는 작업이 필요할 것 같다.
'자바 심화 > TIL' 카테고리의 다른 글
Kafka - 기초 (0) | 2024.12.06 |
---|---|
Rabbit MQ (1) | 2024.12.05 |
Redis - Cache (0) | 2024.12.02 |
Redis - Redis Template (0) | 2024.11.29 |
Docker - 기본 사용 및 Cl / CD (5) | 2024.11.28 |