본문 바로가기
📕 Spring Framework/Spring Project

동시성 조회 문제 해결 및 성능에 관한 고민 [Lock, Queue, Redis]

by GroovyArea 2022. 9. 14.

주문 건에 대한 상품 재고 파악 동시성 관련 이슈에 대해 고민한 하루다.

프로젝트 리팩토링을 시작하며 지난 도메인들은 기본 crud API만을 다루었다.

5일동안 JPA 강의들을 수강하며 본격적으로 주문 및 결제 API 리팩토링에 다시 착수했다.

 

아무래도 프로젝트의 토픽이 쇼핑몰이니 주문 및 결제 파트에서 단순 CRUD가 아닌 핵심 비즈니스를 고려하고 싶어, 외부 결제 API 및 디자인 패턴을 적용한 깔끔한 코드들을 고려하며 작성하는 중이다.

 

대략적인 틀을 만든 뒤, 본격적으로 주문을 구현하던 중, 동시성 이슈 문제에 직면했다.

 

기존 동시성 문제 해결 방법

MSA를 고려했기에, 데이터 정합성 문제를 해결하기 위해 Outbox pattern을 이용중이었다. 

이 방식을 통해 상품 동시성 문제를 해결했었다.

 

하지만 예외 처리 및 트랜잭션 처리가 미흡했었다.

 

동시성 이슈에 대한 고민 방안

  • 해당 DB 레코드에 Lock을 거는 방법
  • 메시지 큐의 형식을 가진 Queue를 직접 구현하여 대기열을 만들어 해결
  • Outbox pattern과 동일하게 DB에 주문 관련 정보들을 저장하여 조회하여 순차적으로 해결

첫 번째 방법 : 

- 웬만해서 추천하지 않는 방법이다. DB 자체에 락을 점유하는 것은 실 서비스 환경에서 심각한 문제를 일으키므로, 가뿐히 넘겼다.

 

두 번째 방법 :

- 큐를 이용해 대기열을 만드는 것이 괜찮을 거란 생각을 했다. 하지만 모든 주문 요청건에 하나의 큐를 이용하게 되면, 주문건이 많을 수록 심각하게 느려진다. (유사 수강신청..)

 

세 번째 방법 : 

- 괜찮은 방법이라고 생각한다. 하지만 DB 조회를 계속적으로 이루어야 하고 주문 건이 많을 때 한번에 다 조회할 경우 성능 상 좋지 못한 방법이라고 생각했다. 무엇보다 MSA가 아니기 때문에 불필요한 테이블을 설계할 이유도 없다.

 

Redisson을 이용하는 방식

내가 구상한 환경 내에서 동시성 문제 해결 및 성능을 충족 시키는 방식을 계속 찾아보다보니 Redis를 이용한 분산락에 대한 내용이 많이 보였다. 

 

인메모리 DB이기 때문에 조회 시 성능상 유리한 점이 있을 거라 생각했었지만, Redisson이라는 라이브러리를 통해 Redis를 이용하여 분산락을 걸 수 있다는 장점이 있었다.

 

상품 단건 주문, 장바구니 주문이 있었기에 상품에 대한 재고 수량 파악이 동시성 문제의 발단이었지만, Redisson을 이용하면 상품과 그 재고량을 redis에 저장하고 키를 통해 분산 Lock을 걸게 되면 싱글 스레드 기반으로 동작하기에 동시성 문제도 해결되고 성능도 어느정도 가져가게 될 수 있겠다는 생각을 했다.

 

반응형