목록Architecture/Application (10)
ecsimsw
대기에 DB Connection 을 점유하는 비관적 락이전 글 에서 프로젝트에서 생긴 동시성 문제가 왜 발생했는지 소개하고 이를 해결할 수 있는 락 종류를 소개했다. 추가적인 인프라와 적은 코드 수정, 그리고 확실한 동시성 문제 처리를 원했기에 비관적 락을 선택했다. 인덱스 조건을 수정하여 사용자별 로우락을 유도해 불필요한 대기를 없앴다. 그리고 얼마 후 DB 락 대기 시간 동안 커넥션을 점유하고 있음을 로그로 확인했다. 사용자 간 독립적으로 락 처리를 했지만, 한 사용자가 락으로 모든 커넥션을 물고 있으면 결국 락이 걸린 로우와 독립적인 다른 사용자는 그 사용자를 대기해야 했다. 이 글에서는 동시성 문제를 해결하기 위해 여러 락 방식을 적용하면서 발생했던 에러 사항들과 해결 과정을 소개한다. 목..
Mysql InnoDB 의 RepeatableRead Mysql 의 기본 Transaction isolate 수준은 RepeatableRead 이다. RepeatableRead 는 트랜잭션이 시작된 시점 이후로 여러 번 Select Row 를 확인해도 동일한 값을 갖는다는 것이다. Mysql 은 SnapShot을 사용해서 이를 보장한다. 트랜잭션마다 별도의 스냅샷을 기록하여 다른 트랜잭션이 값을 변경하고 Commit 해도 이 스냅샷을 이용해서 동일한 값을 읽게 되는 것이다. Phantom read 문제 Repeatable Read 는 데이터의 추가, 삭제의 변경은 막지 못해 Phantom read 문제가 발생한다. 한 트랜잭션 내에서 전과 다른 조회 결과 row 수를 조회하게 된다는 것이다. InnoDB..
기존의 문제점PicUp 프로젝트에선 서비스 간 통신 방법으로 메시징을 이용한다. 서비스 간 처리가 필요할 때 이벤트를 발행, 메시지 큐에 담아두고 처리를 맡는 다른 서비스에서 이를 리스닝하여 처리한다. 픽업 프로젝트에선 앨범 삭제 기능이 좋은 예시이다. 사용자가 앨범을 삭제할 때 관련 사진 파일들을 전부 삭제하는 처리 시간까지 사용자 요청 주기에 포함해선 안되므로 요청 주기 내에선 DB 데이터만 삭제하고 이 이벤트를 메시지 큐에 담았다가 비동기로 파일을 삭제하게 된다. 문제는 메시징과 DB 트랜잭션이 다른 원자성을 갖는다는 것이다. 원자성은 한 작업의 단위 내에서 세부 작업들은 모두 성공하거나 모두 실패해야 함을 말한다. 메시징과 DB 트랜잭션은 원자성이 보장되지 않기 때문에 ..
0. AS IS 기존에는 이 메인 / 백업 스토리지 업로드를 동기로 처리했다. 400KB의 이미지를 업로드할 때 main 33ms, backup 1680ms 정도가 필요했고, 사용자 응답은 이 둘을 더한 값 + ⍺ 가 될 것이다. 이미지 업로드 시에 각 스토리지 업로드를 비동기로 처리하되 모든 업로드가 정상일 경우에만 사용자에게 정상으로 응답하고자 한다. 그리고 동시에 비동기식 업로드 과정에서 생길 수 있는 더미 파일을 사용자 흐름에 포함하지 않고 처리하고자 한다. 이 글에선 위 요구 사항을 만족하기 위한 작업 과정을 소개한다. 목차는 다음과 같다. 1. 단순 비동기 처리 2. Future로 비동기 / 블록킹 방식으로 처리하는 경우, 그 문제점 3. CompletableFuture으로 쉽게 구현하는 다양..
캐시로 조회 성능 개선 Pic-up 은 앨범 기반 사진 스토리지이다. Picup 은 페이지네이션이 적용되어 있고, 서비스 특성상 사용자는 앨범을 조회 시 항상 첫 페이지의 사진들부터 확인한다. 전체 앨범 조회에도 마찬가지다. 사용자의 앨범 목록을 조회할 때도 항상 첫 페이지의 사진들부터 조회한다. 그리고 그 앨범, 사진들은 수정될 여지가 적다. 일반 게시물과는 다르게 사진을 앨범으로 한번 만들어두면 그 이후로는 사진을 삭제하거나 수정하는 요청보다는 단순 조회가 다수일 것이다. 그래서 조회 성능을 개선하고 DB에 접근하는 네트워크 비용을 아끼고자 캐시를 도입하게 되었다. 이 글에선 어떤 전략으로 캐시를 사용했고, Spring 에서의 설정 방법을 소개한다. 어떤 캐시를 사용할까 1 : 지역 캐시와 전역 캐시..
0. 메시지 큐 사용 이유와 전략, 재앙 시나리오 소개 Picup 프로젝트에선 메시지 큐로 RabbitMQ 를 사용한다. 이 글에서는 Message queue 를 사용하게 된 이유부터 Rabbit mq의 주요 설정 옵션들 그리고 프로젝트 내에서 MQ 사용 시나리오를 소개하려 한다. 1. Message queue 도입 배경 2. Rabbit MQ 의 주요 옵션, Dead letter 3. 프로젝트에서의 사용 시나리오 / 재앙 시나리오 1. Message queue 도입 배경 Picup 에서는 사진 파일을 한 번에 많은 양 삭제할 수 있어야 한다. 사용자가 앨범 삭제를 요청하면 서버에선 앨범 내에 들어있는 관련 사진들을 삭제해야 한다. 이때 사용자가 그 파일들이 실제로 삭제 처리 될 때까지 그 시간을 기다릴..
Rabbit MQ 재시도 정책과 Dead letter queue 설정 방법 Pic up 에서 서버간 비동기 통신을 위해 그리고 두 서버의 직접 통신을 피하기 위해 Message queue 로 Rabbit MQ 를 사용하고 있다. Message consumer 가 메시지를 처리하는 도중에 처리 실패하는 경우 큐에서 메시지는 제거되지만 실제 메시지는 처리가 안되는 문제를 해결하기 위한 정책을 고민한다. 재시도 정책 Consumer 가 메시지 처리 도중 예외가 발생하는 경우 정책에 따라 Message queue 에 다시 해당 메시지를 추가하도록 한다. RabbitListenerContainerFactory 를 재정의하고 Rabbit listener 가 이를 사용하는 것으로 RetryInterceptorBuil..
도메인 이벤트로 의존성 분리? 우아한테크코스 지원 플랫폼 개발을 하면서 제이슨한테 배운 개념이다. 그 당시에는 '오 멋진걸~, 이렇게도 할 수 있구나 🤩' 정도였도로 지나쳤었다. 패키지간의 의존, 리팩토링을 위한 분리를 고민하기 시작하면서 이제는 좀 더 와닿아서 이렇게 대박 기술인 양 정리하게 되었다. 문제와 요구 사항 커머스 서버를 만드는 프로젝트를 발전시키는 중이었다. 기존에는 없었던 명세였는데, 각 상품별 주문 횟수를 기록할 수 있다는 요구 사항이 추가되었다. 1. 사용자가 주문(Order)을 생성하게 되면, 그 장바구니에 포함된 각 제품(Product)에 orderedCount를 증가시킨다. 이 이전까지는 OrderService는 Product 관련 도메인을 분리해둔 상황이었다. 이번 요구 사항을..