반응형

Spring 16

장애 대응 문서

현업에서 장애는 예상치 못한 곳에서 항상 발생한다.피할 수 없다면 적극적으로 예방하고, 장애 발생 시 유연하고 빠르게 대처해야 하며, 같은 장애가 재발되지 않도록 조치를 취해야 한다.현업에서의 장애 대응 프로세스는 보통 장애 탐지 및 전파장애 분류 및 해결장애 복구 및 보고장애 회고이렇게 진행된다고 보면 된다.현업에서 장애를 빠르게 감지하기 위해서는 로깅, 모니터링 등의 방법이 있는데, 장애 상황을 감지하기 위해 다양한 조건을 설정하고 모니터링을 통해 장애 확산을 방지할 수 있다.그럼 우리가 자주 볼 수 있는 장애는 어떤 것들이 있고, 어떻게 대응을 하면 좋을지 같이 살펴보자. 외부 서비스 장애 Kafka 사례: 디스크 공간 부족으로 인해 Kafka Broker를 사용할 수 없음실패 원인: Kafka 브..

부하 테스트

목적서비스의 기본적인 성능 테스트 및 예상치 못한 병목 현상이나 장애 상황에 대비하기 위해서 진행한다. 대상 API 콘서트 대기열 시나리오 에 있는 모든 API를 대상으로 테스트를 진행한다.GETapi/v1/concertsapi/v1/concerts/{concertId}api/v1/concerts/{concertId}/datesapi/v1/concerts/dates/{concertDateId}/seatsapi/v1/users/{userId}/balanceapi/v1/reservations/{userId}POSTapi/v1/payments/payapi/v1/reservationsapi/v1/queues/tokenPATCHapi/v1/{userId}/chargeDELETEapi/v1/reservations/..

트랜잭션의 범위 및 내부 로직 융합에 따른 문제점 파악

문제결제 API 쪽 비즈니스 로직의 트랜잭션 생명주기가 길다.결제 API 쪽을 한번 살펴보자.@Component@RequiredArgsConstructorpublic class PaymentFacade { private final PaymentService paymentService; private final UserService userService; private final ConcertService concertService; private final WaitingQueueService waitingQueueService; /** * 결제 요청하는 유즈케이스를 실행한다. * * @param command reservationId, userId 정보 ..

Query 분석 및 DB Index 설계

조회를 할 때 데이터가 얼마 없을 때는 상관없지만, 데이터가 수천, 수만 건의 경우 인덱스가 있냐 없냐의 따라 성능 차이가 엄청 크다고 한다.보통 인덱스는 카디널리티가 높은(중복도가 낮은) 컬럼으로 설정한다고 한다. (참고로 pk는 기본으로 인덱스로 설정되어 있음)예를 들어 주민등록번호의 경우 카디널리티가 높다고 할 수 있다.(Unique 하기 때문에)지금 나의 시나리오(콘서트 대기열)에서 인덱스 추가를 통해 성능을 개선할 수 있는 부분이 있는지 알아보자. 문제콘서트 예약 가능한 좌석을 조회하는 API 의 경우, 실제로 하나의 콘서트장에 5만명이 앉을 수 있는 대형 장소에서 하는 경우가 많다. 콘서트가 1만개만 있어도, 콘서트 좌석 조회하는 데이터는 5억개의 자리의 데이터가 들어가 있을 것이다. 원인테스..

캐시 및 Redis를 통한 성능 개선

캐시란?캐시는 자주 액세스하거나 계산 비용이 많이 드는 데이터를 일시적으로 저장하는 데 사용된다. 데이터에 액세스하는 데 걸리는 시간을 줄이고, 느린 리소스나 시스템의 로드를 줄여 성능을 향상시키는 데 도움이 된다.그럼 캐시를 사용하기 위한 적절한 데이터의 판단 기준은 무엇일까?데이터가 변경에 민감한지?데이터의 연산에 드는 비용이 비싼지?데이터의 변경이 전파가 되는지?→ 요약하자면, “잘 바뀌지 않으면서 접근할 일이 많은 데이터, 변경되더라도 다른 서비스에 큰 영향을 미치지 않는 데이터” 가 캐시에 저장하여 활용하기 적절하다.그럼 DB에서 계산 비용이 많이 드는(쿼리를 날렸을 때 시간이 오래 걸리는) 경우는 어떤 경우들이 있을까?조인이 복잡할 경우복잡한 조인 조건이 있는 여러 테이블과 관련된 쿼리, 특히..

대기열 서비스 구현(+Redis)

제가 콘서트 예약시스템에서 구현한 대기열에 대한 설계에 대해서 얘기해보겠습니다. 대기열이란?대기열 시스템은 많은 사용자들이 동시에 접근하는 상황에서, 시스템의 안정성과 성능을 보장하기 위해 필수적인 요소입니다. 특히, 티켓 예매, 상품 구매, 서비스 예약 등과 같은 상황에서 대기열 시스템이 중요한 역할을 합니다.만약 1000명의 유저가 동시에 좌석 예약을 위해 요청을 보낸다면, 정해진 선착순 100명만 예약이 가능하게 하고, 나머지는 대기열에서 대기하게 됩니다.이렇게 하면 트레픽의 유량을 제어할 수 있기 때문에 서버의 부하를 줄일 수 있습니다. 대기열에 있는 유저는 일정 시간이 지나면 좌석 예약이 가능하게 되어 콘서트 좌석을 예약할 수 있습니다. 대기열 구현 방법전통적으로? 대기열을 구현하는 방식에는 크..

동시성 이슈( Lock 비교)

동시성 문제먼저 동시성 문제가 무엇인지 간단하게 짚고 넘어가보자.동시성 문제란?여러 작업들이 **동시에 하나의 공통 자원을 점유**하려고 시도할 때 발생하는 문제그럼 이런 동시성 문제가 발생하면 무엇이 문제인가?내가 원하는 결과와 다른 결과가 발생할 수 있다.ex) 데이터를 수정하였으나 조회했을 때 내 예상과 다른 값이 반환동시성 문제로 인해 데이터 무결성이 깨지고, 이로 인해 정합성을 저해시킬 수 있다.데이터의 무결성?데이터 값이 정확한 상태데이터의 정합성어떤 데이터들의 값이 서로 일치하는 상태데이터의 무결성이 훼손 되는 경우 주문정보 테이블에서 고객번호가 모두 -1으로 입력되어 있고, 고객정보 테이블에도 -1의 값을 갖는 고객이 존재한다. (데이터의 값이 일치한다.)그러나 고객번호는 반드시 1 이상의..

Mysql 기반 선착순 쿠폰 발급 기능 개발 (5)

동시성 이슈를 해결하기 위해 다음과 같은 방식으로 순차적으로 적용해보겠다.synchronizedredis lockmysql lock각 방식을 적용함으로써 장단점도 같이 알아보겠다. 동시성 이슈 해결 - synchronized 들어가기 앞서 synchronized 가 무엇인지 알아보자.스레드 동기화란?스레드 동기화는 멀티스레드 환경에서 여러 스레드가 하나의 공유자원에 동시에 접근하지 못하도록 막는것을 말한다.공유데이터가 사용 되어 동기화가 필요한 부분을 임계영역(critical section)이라고 부르며, 자바에서는 이 임계영역에 synchronized 키워드를 사용하여 여러 스레드가 동시에 접근하는 것을 금지함으로써 동기화를 할 수 있다.  synchronized 사용 방법1) 메소드에 synchron..

Mysql 기반 선착순 쿠폰 발급 기능 개발 (4)

성능테스트에 앞서 미리 알고 있으면 좋은 것들에 대해서 설명하겠다. 성능 테스트에서 서비스가 빠른지 느린지에 대한 기준은 다음과 같이 크게 2가지로 판단할 수 있다.ThroughputLatency Throughput Throughput이란 시간당 처리량을 의미한다.TPS(Transaction Per Second), RPS(Request Per Second) 등으로도 불리며, '1초에 처리하는 단위 작업의 수' 혹은 '1초에 처리하는 HTTP 요청 수' 등으로 해석할 수 있다. 즉, 1초에 최대한 많은 작업을 처리할 수 있는 서비스가 성능 측면에서 좋은 서비스라고 볼 수 있다. 예를 들어, A 서비스는 1초에 1000개의 작업을 처리하고, B 서비스는 1초에 2000개의 작업을 처리할 수 있는 능력을 가졌..

Mysql 기반 선착순 쿠폰 발급 기능 개발 (3)

이제부터 만든 서비스를 호출하기 위해 presentation Layer 설계를 해보자. 그전까지는 다른곳에서 가져다 쓸 mycoupon-core 에서 작업하였고, 지금은 mycore-api에서 작업을 진행하겠다. CouponIssueController // mycouponapi/controller/CouponIssueController.java package com.example.mycouponapi.controller; import com.example.mycouponapi.dto.CouponIssueRequestDto; import com.example.mycouponapi.dto.CouponIssueResponseDto; import com.example.mycouponapi.service.Coup..

반응형