목록Architecture/Application (11)
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..
만약 DB 서버가 다운된다면? 이전 글 에서 DB 데이터 백업과 부하분산을 목적으로 DB replication 을 적용하고 Transactional readOnly 여부에 따라 DataSource 를 분기했다. 이 글에선 Master, Replica 중 하나라도 Connection 에 문제가 생기는 상황을 고민한다. DB 서버를 단순히 쿼리가 readOnly 인지 여부만으로 분기한다면 둘 중 하나라도 문제가 생길 경우 서비스의 읽기가 안되거나 쓰기가 안 되는 심각한 문제가 발생할 것이다. 다른 Stand by Master node 를 만들어두고 Master 가 다운 되었을 때 교체하는 방식, Master 가 죽었을 때 Slave 를 Master 로 승격시키는 방식 등 여러 정책을 고민했다. 그중에서도 아..
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 에서는 사진 파일을 한 번에 많은 양 삭제할 수 있어야 한다. 사용자가 앨범 삭제를 요청하면 서버에선 앨범 내에 들어있는 관련 사진들을 삭제해야 한다. 이때 사용자가 그 파일들이 실제로 삭제 처리 될 때까지 그 시간을 기다릴..
커서 기반 페이지네이션으로 전환 PicUp 프로젝트는 앨범 기반의 사진 클라우드 스토리지 서비스이다. 프로젝트에서 기존 Offset 기반의 페이지네이션에서 Cursor 기반의 페이지 네이션으로 방식을 변경하는 과정을 정리하려고 한다. 이 글에선 세가지 키워드를 다룬다. - Offset based 의 성능 문제 - 100 만개 더미 데이터 생성 / LOAD DATA INFILE 방식 업로드 - 쿼리 테스트 결과 Offset based vs Cursor based Offset 기반 페이지네이션에는 유명한 2가지 문제가 있다. 데이터 중복 / 누락 조회 문제, 퍼포먼스 문제. 데이터 중복 / 누락 문제는 일상에서 만나기 쉬워 예상하기 쉬울 것 같다. 3 페이지를 보던 와중에 다른 글이 많이 추가되면 4 페이지..
Rabbit MQ 재시도 정책과 Dead letter queue 설정 방법 Pic up 에서 서버간 비동기 통신을 위해 그리고 두 서버의 직접 통신을 피하기 위해 Message queue 로 Rabbit MQ 를 사용하고 있다. Message consumer 가 메시지를 처리하는 도중에 처리 실패하는 경우 큐에서 메시지는 제거되지만 실제 메시지는 처리가 안되는 문제를 해결하기 위한 정책을 고민한다. 재시도 정책 Consumer 가 메시지 처리 도중 예외가 발생하는 경우 정책에 따라 Message queue 에 다시 해당 메시지를 추가하도록 한다. RabbitListenerContainerFactory 를 재정의하고 Rabbit listener 가 이를 사용하는 것으로 RetryInterceptorBuil..