전체 글 (22) 썸네일형 리스트형 [MSA] MSA 구조에서의 SAGA 패턴과 분산 트랜잭션 서론지난 글에서는 모놀리식 서비스를 msa 구조로 바꿔 독립적인 서비스들로 바꾸고, 서비스간 통신을 kafka를 통한 비동기 이벤트 통신으로 하였다. 하지만, MSA 환경에서 서비스 간의 데이터 일관성을 보장하는 것은 어려운 문제다.특히 여러 서비스에 각각 다른 데이터베이스가 존재하며 트랜잭션을 유지해야하는 상황에서 ACID 원칙을 지키는 것은 쉽지 않다. 이러한 기술적 문제를 해결하기 위해 SAGA 패턴을 적용하여 Kafka 기반의 분산 트랜잭션을 구현하는 것을 목표로 하여, 트랜잭션 실패시 롤백을 구현해보려고 한다. SAGA 패턴Saga Pattern은 마이크로 서비스에서 데이터 일관성을 관리하는 방법이다.각 서비스는 로컬 트랜잭션을 가지고 있으며, 해당 서비스 데이터를 업데이트하며 메시지 또는 이벤.. [쿠러미] Redis 캐싱을 통한 성능 개선 서론현재 쿠러미 프로젝트의 메인페이지는 다음과 같다. 처음 진입점인 메인페이지에 진입하면 위와 같이 사용자에게 다양한 쿠폰 정보가 노출된다. 예를 들어:인기 쿠폰 조회(추후 추가될) 최신 쿠폰, 마감임박 쿠폰 조회이러한 데이터는 다소 복잡한 쿼리를 계산하는 API를 통해 제공된다. 문제는, 이 모든 API가 메인 페이지 로드 시마다 호출된다면 사용자는 불쾌함을 느끼게 된다. 따라서 Redis의 캐싱을 통해 개선을 해보고자 한다. 또한, 현재 API 요청은 JWT를 이용해 사용자 인증을 처리하는데, 다음과 같은 흐름이 발생한다.1. 사용자로부터 access token을 받음2. access token을 복호화하여 유저 정보를 가져옴3. 복호화한 유저 정보와 db에 저장된 유저 정보를 비교4. 정보가 일치.. [쿠러미] 쿼리 최적화를 통한 매장 조회 성능 개선 - 3 서론지금까지 복합인덱스, 명시적 타입 캐스팅 삭제로 매장 조회 기능을 개선했었다.이번 글에선 의도한 SQL 흐름과는 다른 실제 실행 흐름을 분석하고 최적화를 해보겠다. 문제 코드// 회원이 찜한 매장 페이징 조회 @Override public List findMyFavoriteMarketList(Long memberId, LocalDateTime lastModifiedAt, Integer size) { return jpaQueryFactory .select(new QMarketRes( market.id, market.name, ma.. [쿠러미] 쿼리 최적화를 통한 매장 조회 성능 개선 - 2 서론이전 글에서는 실행 계획을 통해 쿼리를 분석하고 복합 인덱스를 통해 매장 조회 성능을 개선했었다.이번 글에서는 서비스에서 특정 카테고리(예: `FOOD`)에 속한 마켓 목록을 조회하는 쿼리에 문제가 있는 걸 고쳐보겠다! Enum 필드 인덱스 미적용(카테고리 별 매장 조회)@Table(name = "category", indexes = { @Index(name = "idx_category_major", columnList = "major") // major 컬럼에 인덱스 추가 })@Entity@Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class Category { @Id .. [쿠러미] 쿼리 최적화를 통한 조회 성능 개선 시작 - 1 서론쿠러미 정식 발매가 1주일 정도 남은 상황이다!발매 후 사용자들이 불편함을 느끼지 않으려면 어떤 기능을 개선할까 생각하다가 조회 성능을 개선하기로 마음먹었다.조회를 제외한 쓰기 쿼리는 사용자에게 쿠폰발급과 찜하기 기능 정도밖에 없으므로, 빠른 조회가 생명이다. 조회가 빠르려면 Index를 통해 정확하고 신속하게 데이터를 찾아내야한다.Table-Full-scan을 하면 테이블에 있는 모든 데이터를 조회하므로 속도가 느려진다.따라서 조회 성능 개선은 Index를 타는지를 위주로 볼 예정이고, 최대한 Index를 타게끔 바꿔보고자 한다. 실행 계획쿼리의 성능을 보려면 쿼리의 실행 계획을 봐야한다.실행 계획은 두가지가 있다.EXPLAIN -> 쿼리를 실행하지 않고, 실행 과정을 예측EXPLAIN ANALY.. [MSA] CGV 예매 서비스 MSA로의 변경 - 1 서론최근에 만든 CGV 대규모 트래픽 대응 예매 서비스에서 Kafka가 쓰였지만, 서비스를 분리하지 않고 한 어플리케이션에 모두 구현 했다. 사실상 kafka 이벤트 기반 아키텍쳐와 부하 분산의 이점을 제대로 활용하지 못한 것이다.(프로젝트 기한이 정해져있고, 개발 영역을 보지않고 인프라 영역만 평가 요소가 들어가기 때문에 급하게 만들긴 했다) 대개 Kafka는 MSA 구조에서 각 서비스들을 연결하기 위한 이벤트 메시지 큐로써 활용되기에, 모놀로그 식으로 구현된 서비스를 MSA로 바꿔보고 싶었다. 우선 이번 글에서는 비지니스를 분리해 서비스들의 연결을 카프카의 메시지로 처리하고, 스프링에서 제공하는 MSA 라이브러리를 통해 아키텍처를 구성하는 것을 목적으로 한다. 서비스 분리 현재 ERD는 다음과 같다.. [쿠러미] Redis 분산락 구현, 비관적락 성능 비교 서론저번 글에 쿠폰 발급 동시성 제어의 구현방법 중 비관적락과 유니크 제약조건(중복 체크)를 통해 구현했다.한 가지 방법이 더 있었는데, 그것은 Redis를 이용한 분산락이었다.이번 시간에는 분산락을 구현해보고 어떤 방법이 더 성능이나 운영환경에서 좋은 지 트레이드 오프를 고려해보겠다. 분산락이란?Redis에서 제공하는 락 구현 방식이다. Redis는 명령 처리를 단일 스레드로 처리하기 때문에, 동시에 요청이 들어와도 순차적으로 처리를 하게된다. 하지만 여러 클라이언트가 동시에 명령을 보낼 때 명령의 순서와 원자성을 보장하는 것은 별도의 이야기이며 결론적으로 보장이 안된다.따라서, 락을 통해 동시성 제어를 해주어야 한다. Lettuce? Redisson?락을 구현하기 위해 대표적으로 많이 쓰이는 라.. [쿠러미] 쿠폰 발급 시 (동시성 제어 + 중복 체크) 문제해결 서론쿠러미 프로젝트가 출시가 임박해, 미뤄뒀던 쿠폰 발급 시 동시성 제어를 하기로 했다.지금 쿠폰의 erd는 다음과 같고, 개수가 쿠폰 테이블에 같이 있는 형태이다. @Transactional public void issuedCoupon(Long memberId, Long couponId) { Member member = findMemberById(memberId); Coupon coupon = findCouponByIdWithRock(couponId); // 쿠폰의 잔여 갯수가 0개일 경우 if (coupon.getStock() == 0 ){ throw new CustomException(COUPON_SOLD_OUT); .. 이전 1 2 3 다음