O0oO0Oo / netty-reservation-service

트랜잭션, 동시성을 공부하기 위한 토이 프로젝트입니다.
0 stars 0 forks source link

feat: integration and optimization of saga pattern in each service module #23

Closed O0oO0Oo closed 2 months ago

O0oO0Oo commented 2 months ago

PR 설명

  1. 카프카 producer, consumer, processor ( consume, produce 를 하는) 구현
  2. 도메인 모듈에서 사가 패턴 통합,
  3. 도메인 리팩토링, 패키지 구조 변경

변경 사항

모듈 추가

도메인 모듈 리팩토링

messaging-adapter 모듈 - 카프카

  1. 간단한 producer, consumer 구현
  2. 오케스트레이션 사가 패턴에서는 각 서비스에서 이벤트를 소비후 응답을 해야한다. Processor 를 도입하여 메시지 소비 - 처리 - 생산하는 클래스 구현

saga-orchestrator, reservation 최적화

배경

UUID 를 기본키로 사용시 문제점

  1. UUID 의 데이터 크기 : UUID 는 기존의 Long 을 사용할때보다 2배가 크다, 이는 디스크에 한번 접근시 인덱스 페이지를 더 적게 불러오기 때문에 조회 성능이 저하된다.
  2. B+ tree 인덱스 문제 : UUID 는 무작위로 생성되기 떄문에 Auto Increment 처럼 순서대로 생성되는 키보단, 페이지 분할을 자주 유발할 수 있다. 이는 삽입 성능의 저하로 이어진다.

TSID 의 특징

  1. TSID 는 Long 과 같이 8byte 를 가진다.
  2. TSID 는 42-bit time component 와 22-bit random component 를 가지기 때문에 시간 순서대로 생성된다는 특징이 있다.

모듈의 구성

image

위와 같이 모듈을 구성하였으며, saga-orchestrator 는 messaging-core 모듈의 인터페이스를 사용하고, messaging-adapter 모듈은 messaging-core 의 인터페이스를 구현한다.

각 도메인 모듈에서는 messaging-adapter, saga-orchesrator 를 의존하여 사용하도록 하여서, 메시지 기술과 오케스트레이션 사가 모듈간의 결합도를 낮췄다.

예약 생성 로직

예약 생성 로직은 다음과 같이 동작한다. image

2024-08-21T02:15:54.500+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.user.app.UserMessageEventService.consumerVerifyUserEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2024-08-21T02:15:54.501+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(748374353<open>)] for JPA transaction
2024-08-21T02:15:54.512+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@22adc03]
2024-08-21T02:15:54.513+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(748374353<open>)] for JPA transaction
2024-08-21T02:15:54.513+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction

// user 검색
Hibernate: select u1_0.user_id,u1_0.amount,u1_0.created_time,u1_0.last_modified_time,u1_0.name from user u1_0 where u1_0.user_id=?
2024-08-21T02:15:54.520+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.520+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(748374353<open>)]
2024-08-21T02:15:54.527+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-7-thread-3] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(748374353<open>)] after transaction
2024-08-21T02:15:54.554+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.business.app.BusinessMessageEventService.consumeVerifyBusinessEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2024-08-21T02:15:54.554+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(809772755<open>)] for JPA transaction
2024-08-21T02:15:54.563+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@6ea3a0ac]
2024-08-21T02:15:54.563+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(809772755<open>)] for JPA transaction
2024-08-21T02:15:54.563+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction

// business 검색
Hibernate: select b1_0.business_id,b1_0.created_time,b1_0.last_modified_time,b1_0.detail_category,b1_0.major_category,b1_0.sub_category,b1_0.closed,b1_0.name from business b1_0 where b1_0.business_id=?
2024-08-21T02:15:54.569+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.569+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(809772755<open>)]
2024-08-21T02:15:54.576+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-2-thread-2] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(809772755<open>)] after transaction
2024-08-21T02:15:54.632+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-3-thread-3] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.reservableitem.app.ReservableItemMessageEventService.consumeVerifyReservableItemEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-08-21T02:15:54.632+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-3-thread-3] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(909367079<open>)] for JPA transaction
2024-08-21T02:15:54.637+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-3-thread-3] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@593d9b4b]

// reservable item 검색
Hibernate: select ri1_0.reservable_item_id,ri1_0.created_time,ri1_0.last_modified_time,ri1_0.business_id,ri1_0.is_item_available,ri1_0.max_quantity_per_user,ri1_0.name,ri1_0.amount,rt1_0.reservable_item_id,rt1_0.reservable_time_id,rt1_0.is_time_available,rt1_0.quantity,rt1_0.unit,rt1_0.time from reservable_item ri1_0 join reservable_time rt1_0 on ri1_0.reservable_item_id=rt1_0.reservable_item_id where ri1_0.reservable_item_id=? and ri1_0.business_id=? and rt1_0.reservable_time_id=?
2024-08-21T02:15:54.644+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-3-thread-3] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.645+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-3-thread-3] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(909367079<open>)]
2024-08-21T02:15:54.650+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-3-thread-3] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(909367079<open>)] after transaction
2024-08-21T02:15:54.669+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.reservation.app.ReservationMessageEventService.consumeCheckReservationLimitEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-08-21T02:15:54.669+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1934117138<open>)] for JPA transaction
2024-08-21T02:15:54.672+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@6904ea37]

// 이전 예약기록 검색
Hibernate: select coalesce(sum(r1_0.quantity),0) from reservation r1_0 where r1_0.user_id=? and r1_0.reservable_item_id=? and r1_0.reservation_status in ('RESERVED','COMPLETED','PENDING')
2024-08-21T02:15:54.679+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1934117138<open>)] for JPA transaction
2024-08-21T02:15:54.679+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction

// tsid 를 직접 생성하여 넣기떄문에 id 가 존재하는지 select 쿼리가 나가게됨.
Hibernate: select r1_0.reservation_id,r1_0.created_time,r1_0.last_modified_time,r1_0.business_id,r1_0.quantity,r1_0.reservable_item_id,r1_0.reservable_time_id,r1_0.reservation_status,r1_0.user_id from reservation r1_0 where r1_0.reservation_id=?
2024-08-21T02:15:54.684+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.684+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1934117138<open>)]

// pending 상태의 예약 레코드 생성
Hibernate: insert into reservation (created_time,last_modified_time,business_id,quantity,reservable_item_id,reservable_time_id,reservation_status,user_id,reservation_id) values (?,?,?,?,?,?,?,?,?)
2024-08-21T02:15:54.699+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-5-thread-3] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(1934117138<open>)] after transaction
2024-08-21T02:15:54.718+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.user.app.UserMessageEventService.consumeUpdateUserBalanceEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-08-21T02:15:54.718+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1547711304<open>)] for JPA transaction
2024-08-21T02:15:54.721+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@64ecf688]
2024-08-21T02:15:54.721+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1547711304<open>)] for JPA transaction
2024-08-21T02:15:54.721+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction

// user 검색
Hibernate: select u1_0.user_id,u1_0.amount,u1_0.created_time,u1_0.last_modified_time,u1_0.name from user u1_0 where u1_0.user_id=?
2024-08-21T02:15:54.726+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.726+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1547711304<open>)]

// user balance 감소
Hibernate: update user set amount=?,last_modified_time=?,name=? where user_id=?
2024-08-21T02:15:54.738+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-8-thread-3] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(1547711304<open>)] after transaction
2024-08-21T02:15:54.787+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-4-thread-3] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.reservableitem.app.ReservableItemMessageEventService.consumeUpdateReservableItemQuantityEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-08-21T02:15:54.787+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-4-thread-3] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(2127678446<open>)] for JPA transaction
2024-08-21T02:15:54.788+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-4-thread-3] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@6a41b187]

// reservable item 검색
Hibernate: select ri1_0.reservable_item_id,ri1_0.created_time,ri1_0.last_modified_time,ri1_0.business_id,ri1_0.is_item_available,ri1_0.max_quantity_per_user,ri1_0.name,ri1_0.amount,rt1_0.reservable_item_id,rt1_0.reservable_time_id,rt1_0.is_time_available,rt1_0.quantity,rt1_0.unit,rt1_0.time from reservable_item ri1_0 join reservable_time rt1_0 on ri1_0.reservable_item_id=rt1_0.reservable_item_id where ri1_0.reservable_item_id=? and rt1_0.reservable_time_id=?
2024-08-21T02:15:54.792+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-4-thread-3] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.792+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-4-thread-3] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(2127678446<open>)]

// reservable item 재고 감소
Hibernate: update reservable_time set is_time_available=?,reservable_item_id=?,quantity=?,unit=?,time=? where reservable_time_id=?
2024-08-21T02:15:54.801+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-4-thread-3] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(2127678446<open>)] after transaction
2024-08-21T02:15:54.817+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [org.server.rsaga.reservation.app.ReservationMessageEventService.consumeCreateReservationFinalEvent]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2024-08-21T02:15:54.817+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1580938216<open>)] for JPA transaction
2024-08-21T02:15:54.819+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@4f8ae1e4]
2024-08-21T02:15:54.819+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1580938216<open>)] for JPA transaction
2024-08-21T02:15:54.819+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction

// reservation 검색
Hibernate: select r1_0.reservation_id,r1_0.created_time,r1_0.last_modified_time,r1_0.business_id,r1_0.quantity,r1_0.reservable_item_id,r1_0.reservable_time_id,r1_0.reservation_status,r1_0.user_id from reservation r1_0 where r1_0.reservation_id=?
2024-08-21T02:15:54.822+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2024-08-21T02:15:54.822+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1580938216<open>)]

// reservation pending 에서 reserved 상태로 변경
Hibernate: update reservation set last_modified_time=?,business_id=?,quantity=?,reservable_item_id=?,reservable_time_id=?,reservation_status=?,user_id=? where reservation_id=?
2024-08-21T02:15:54.831+09:00 DEBUG 12024 --- [rsaga.netty-core] [pool-6-thread-1] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(1580938216<open>)] after transaction
2024-08-21T02:15:54.837+09:00  INFO 12024 --- [rsaga.netty-core] [       Thread-7] o.s.r.s.s.impl.InMemorySagaStateManager  : Correlation id : 0H14RPJYZBZ5V is succeed.

관련 이슈

18

추가 정보