2024. 9. 25. 10:03ㆍ대규모스트림처리
2024/09/25
※ 대규모 시스템에 대해 알아보자.
▶ 대규모 시스템이란?
● 대규모 시스템이란 무엇일까?
○ 인터넷 환경에서는 수백만 명의 사용자가 동시에 접속하고 상호작용할 수 있는 시스템을 구축해야 하는 상황이 자주 발생한다.
○ 이러한 시스템은 단순히 많은 사용자를 처리하는 것뿐만 아니라, 안정성과 신뢰성을 유지하면서 고성능을 제공해야 한다.
○ 대규모 시스템을 설계하고 구축하는 과정에서 고려해야 할 중요한 요소들을 한번 알아보자.
● 큐를 통한 대규모 스트림 처리에 대해 집중해보자.
○ 큐를 사용하면 대규모 처리를 할수 있다라는 이야기를 많이 들어봤을 것이다.
○ 모든 상황에서 큐를 사용해야 할까❓ 큐를 사용해야 하는 상황과 사용하지 않아도 되는 상황이 있을 것이다.
○ 어떠한 상황에서 큐를 사용하고 또, 큐를 효과적으로 관리하는 방법을 알아보자. 또한 큐 라우팅을 통해 서비스를 설계하고 개발해보자.
● 개발한 애플리케이션의 성능 테스트는 필수❗
○ 애플리케이션을 개발한 후에는 반드시 테스트를 거쳐야 한다.
○ 기능에 대한 테스트를 통해 애플리케이션이 정상적으로 동작하는것을 확인하는 것은 당연하다.
○ 성능 테스트를 통해 애플리케이션의 성능을 측정하여 애플리케이션이 실제 환경에서 어떻게 동작하는지 미리 검증하고, 신뢰성 있는 시스템을 구축해보자.
▶ 대규모 시스템
📌 메시징 시스템을 개발하는 것을 예로 들어보자. 어떠한 기준으로 시스템을 설계해야 할까❓
● 동시 접속자와 초당 요청량(TPS)
1️⃣ 사용자 수
👉 대규모 시스템을 설계할 때 가장 중요한 요소 중 하나는 사용자 수다.
○ 얼마나 많은 사용자가 시스템을 사용할 것인지 파악하는 것이 중요하다.
○ 기존 시스템에 새로운 기능을 추가하는 경우, 시스템 모니터링을 통해 하루에 몇 명의 사용자가 접속하는지 알 수 있다.
○ 그러나 단순히 하루 접속량을 파악하는 것만으로는 충분하지 않다.
○ 더 중요한 것은 동시 접속자의 요청 수다.
2️⃣ TPS(TPS, Transactions Per Second)
📌 TPS란?
TPS (Transactions Per Second)는 초당 처리되는 트랜잭션의 수를 나타내는 지표다. 이는 시스템의 성능을 평가하는 중요한 지표 중 하나로, 특히 대규모 시스템에서 중요한 역할을 한다. TPS는 시스템이 얼마나 많은 요청을 동시에 처리할 수 있는지를 나타내며, 시스템의 처리 능력을 가늠할 수 있게 해준다.
○ 시스템이 초당 요청량(TPS, Transactions Per Second)을 견딜 수 있어야 한다.
▪ 이를 위해서는 일간 접속량이 아닌, 특정 시간대에 초당 접속자 요청량이 가장 많은 시간을 파악해야 한다.
▪ 이 정보는 시스템의 용량 계획을 세우는 데 매우 중요하다.
➡️ 예를 들어, 기존 시스템이 오전 9시 30분에 초당 200건의 요청을 처리했다고 가정해 보자. 이러한 데이터를 기반으로 시스템의 용량을 결정해야 한다. 우리의 목표는 시스템이 예상치 못한 최대 부하를 견딜 수 있도록 하는 것이다. 따라서 200건을 기준으로 1.5배인 300건을 처리할 수 있도록 시스템을 설계하는 것이 바람직하다. 이는 시스템이 예기치 않은 트래픽 급증에도 견딜 수 있는 여유를 제공할 것이다.
○ 예상치 못한 이벤트로 인해 설계 예상 이상의 요청이 몰린다면 시스템이 중단될 수 있다.
▪ 이러한 상황을 대비하기 위해서는 다양한 방법을 고려해야 한다.
▪ 이러한 방법들을 통해 시스템의 안정성을 높일 수 있다.
✅ 첫째, 애플리케이션의 수를 늘리는 방법이 있다.
✅ 둘째, 오류 상황에서 사용자가 대기할 수 있도록 대기열을 설정하는 것도 하나의 방법이다.
✅ 셋째, 자동 스케일링을 통해 시스템의 자원을 동적으로 할당하여 부하를 분산시키는 것도 중요하다.
● 요청 종류에 따른 개발
📌 시스템이 읽기 전용인지, 쓰기 및 업데이트를 위한 것인지도 중요하다. 이를 파악하고 처리 속도를 빠르게 하여 응답한다면 보다 많은 사용자를 수용할 수 있다.
● 데이터 제공 및 저장에서 가장 많은 시간을 소모하는 부분은 DB에서 데이터를 조회하거나 쓰는 것이다.
● 요청 종류에 따라 이 부분의 허들을 최소화하는 것이 중요하다.
1️⃣ 읽기 요청 최적화
○ 캐시 사용
▪ 모든 사용자가 같은 데이터를 요청하는 경우, 이를 해소하기 위해 DB의 데이터를 레디스 같은 캐시에 올려두면 요청에 대한 응답 속도를 빠르게 할 수 있다.
▪ 캐시를 사용하면 데이터를 빠르게 제공할 수 있으며, DB의 부하를 줄일 수 있다.
▪ 개인화 데이터가 아니라면 캐시를 사용하여 데이터 로드에 시간 소요를 최소화 하는 방법이 중요하다.
▪ 데이터에서 필터된 데이터를 가져오는것보다 레디스에서 필터된 데이터를 가져오거나 애플리케이션 로직에서 필터링을 수행하는것이 더 큰 성능상의 이점을 가질 것이다.
▪ 엣지 단에서 캐싱을 처리하면 시스템의 요청 처리량이 줄어들어 적은 수의 애플리케이션으로도 요청을 처리할 수 있다. 엣지 캐싱은 사용자와 가까운 곳에서 데이터를 제공하므로 네트워크 지연을 최소화하고, 사용자 경험을 향상시킬 수 있다.
▪ 캐싱 전략을 설계할 때는 캐시 갱신 정책도 중요하다.
➡️ 예를 들어, 공지사항이 자주 변경되지 않는 경우에는 캐시의 유효 기간을 길게 설정할 수 있다. 반면, 변경이 잦은 경우에는 짧은 유효 기간을 설정하거나, 변경 시점에 캐시를 무효화하여 최신 데이터를 제공할 수 있도록 해야 한다. 이러한 캐싱 전략을 통해 시스템의 효율성을 극대화할 수 있다.
▪ 데이터 소실의 위험을 줄이기 위해 데이터의 유효성을 지속적으로 검증하고, 데이터가 손실되지 않았는지 확인해야 한다. 또한, 캐시 계층에서 데이터 소실 시 재요청을 통해 데이터베이스에서 데이터를 다시 가져올 수 있도록 해야 한다.
🔥 레디스 캐시를 사용할때 무엇을 조심해야 할까?
○ 데이터 베이스 사용 최적화
✅ 데이터베이스 인덱싱 : 데이터베이스 인덱싱은 조회 성능을 크게 향상시킬 수 있는 방법이다. 인덱스를 사용하면 데이터베이스는 데이터를 빠르게 검색할 수 있다. 올바르게 설계된 인덱스는 읽기 성능을 최적화하고 쿼리 응답 시간을 줄인다. 주의할 점은 인덱스가 너무 많으면 쓰기 성능이 저하될 수 있다는 것이다.
✅ 데이터베이스 샤딩 : 데이터베이스 샤딩은 데이터베이스를 여러 샤드로 분할하여 각각의 샤드가 독립적으로 쿼리를 처리하도록 하는 방법이다. 이를 통해 단일 데이터베이스에 대한 부하를 분산시킬 수 있으며, 읽기 요청에 대한 응답 속도를 향상시킬 수 있다. 예를 들어, 사용자 데이터를 여러 샤드에 분산 저장하여 읽기 성능을 최적화할 수 있다.
▪ 예를 들어 테이블 파티셔닝을 생각해볼 수 있다. 이는 기본적인 형태의 샤딩으로, 데이터베이스 수준에서 데이터를 분할한다.
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
order_date DATE,
amount DECIMAL
) PARTITION BY RANGE (order_date);
CREATE TABLE orders_2023_01 PARTITION OF orders FOR VALUES FROM ('2023-01-01') TO ('2023-02-01');
CREATE TABLE orders_2023_02 PARTITION OF orders FOR VALUES FROM ('2023-02-01') TO ('2023-03-01');
✅ 읽기 전용 데이터베이스 : 읽기 전용 데이터베이스는 주로 읽기 요청을 처리하는 데이터베이스 인스턴스다. 데이터를 주기적으로 동기화하여 최신 상태를 유지하면서 읽기 요청을 처리한다. 이 방법은 주 데이터베이스에 대한 읽기 부하를 줄이고 성능을 최적화할 수 있다.
✅ 쿼리 최적화 : 쿼리 최적화는 SQL 쿼리를 효율적으로 작성하여 데이터베이스의 읽기 성능을 향상시키는 방법이다. 예를 들어, 불필요한 조인을 줄이고, 필요한 컬럼만 선택하며, 적절한 조건을 사용하는 것이 중요하다. 쿼리 실행 계획을 분석하여 병목 지점을 찾아내고, 이를 최적화할 수 있다.
2️⃣ 쓰기 요청 최적화
○ 쓰기에서 가장 많은 시간을 소요하는 부분은 DB에 데이터를 생성하는 부분이다. 이를 해결하기 위한 다양한 방법이 있다.
✅ 비동기 처리
▪ 쓰기 요청을 비동기 방식으로 처리하면 DB에 직접 접근하지 않고도 빠르게 응답을 반환할 수 있다.
▪ 예를 들어 메시지를 바로 DB에 쓰지 않고, 큐에 넣어 나중에 처리하는 방법이 있다.
▪ 이를 통해 애플리케이션은 요청을 빠르게 처리할 수 있다.
▪ 비동기 처리는 특히 높은 트래픽을 처리할 때 유용하다.
▪ 사용자는 요청을 보낸 후 즉시 응답을 받기 때문에, 사용자 경험이 향상된다.
▪ 비동기 처리 시 데이터 소실이나 오류를 방지하기 위해 큐에 데이터를 넣을 때 적절한 검증을 수행하고, 큐에 쌓인 데이터를 지속적으로 모니터링하여 실패한 요청을 재시도할 수 있는 메커니즘을 마련해야 한다.
▪ 또한, 데이터의 순서를 보장하고, 중복 처리를 방지하기 위한 고유 식별자(ID)를 사용해야 한다.
✅ 배치 처리
▪ 실시간으로 처리할 필요가 없는 쓰기 요청은 배치 처리를 통해 한꺼번에 처리할 수 있다.
▪ 예를 들어 일정 시간마다 큐에 쌓인 메시지를 DB에 쓰는 방법이 있다.
▪ 예를 들어, 매일 자정에 하루 동안 수집된 로그 데이터를 한 번에 DB에 저장하는 방식으로 사용할 수 있다.
▪ 이를 통해 실시간 처리의 부담을 줄이고, 시스템 자원을 효율적으로 사용할 수 있다.
▪ 배치 처리 시에도 데이터 소실을 방지하기 위해 배치 작업 중 오류가 발생한 경우 이를 기록하고, 재시도할 수 있는 메커니즘을 마련해야 한다.
▪ 또한, 배치 작업의 상태를 모니터링하고, 배치 작업이 완료되었는지 확인하는 프로세스를 마련해야 한다.
✅ 분산 DB
▪ 단일 DB로 모든 쓰기 요청을 처리하기 어렵다면, 분산 DB를 사용하여 부하를 분산시킬 수 있다.
▪ 예를 들어 여러 개의 DB 인스턴스를 사용하여 각 인스턴스가 특정 사용자 그룹의 데이터를 처리하도록 할 수 있다.
▪ 분산 DB는 데이터를 여러 개의 노드에 분산 저장하여 고가용성과 확장성을 제공한다.
▪ 또한, 샤딩(Sharding) 기법을 통해 데이터베이스를 수평으로 분할하여 각 샤드가 독립적으로 쓰기 작업을 처리하도록 할 수 있다. 이를 통해 단일 노드의 부하를 줄이고, 시스템의 전체 성능을 향상시킬 수 있다.
📌 분산 DB 사용 시 데이터 일관성을 유지하기 위해 트랜잭션 관리와 데이터 동기화에 신경 써야 한다. 예를 들어, 분산 트랜잭션이나 이벤트 소싱을 사용하여 데이터 일관성을 유지할 수 있다.
'대규모스트림처리' 카테고리의 다른 글
Kafka란? (3) | 2024.10.01 |
---|---|
RabbitMQ란? (0) | 2024.09.30 |
대규모 시스템이란?(3) (3) | 2024.09.29 |
대규모 시스템이란?(2) (2) | 2024.09.26 |