인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

W-Hand님의 프로필 이미지
W-Hand

작성한 질문수

재고시스템으로 알아보는 동시성이슈 해결방법

Redis 를 이용한 분산 락 구현의 성능 관련 질문

작성

·

1.3K

0

[상황 예시]
한정판 상품 A의 재고 수량 : 2000개 (1인당 1개씩만 구매 가능)

[구매 로직]
1. 데이터 베이스에서 상품 A를 조회
2. A의 재고 수량 확인
3. 재고 수량이 0보다 큰 경우 재고를 1 감소시키고 구매 완료 처리

[테스트]
2000개 스레드 생성해서 동시에 구매 요청 후 잔여 재고 확인
테스트 코드에서 2000개의 스레드가 동작하기 전 System.nanoTime() 과 모두 동작이 끝난 후 System.nanoTime() 을 통해 처리 시간을 계산하여 비교해보고 있습니다.
테스트 환경 - h2 database

 

위와 같은 방식으로 현재 프로젝트를 구현 중에 있습니다. 한정판 상품 구매의 특성 상 충돌이 잦을 것이라고 생각해서 다음과 같은 후보군으로 실험을 하고 있습니다.

1. 비관적 락
2. Lettuce 를 이용한 분산락
3. Redisson 을 이용한 분산락

제가 알아본 바나 다른 사례들을 봤을 때 Redis를 거친다고 해서 DB에서 제공해주는 락 기능을 사용하는 것과 속도면에서 차이가 거의 없는 것으로 알고 있었는데 실제 실험 결과가 다음과 같습니다.

1. 비관적 락 - 평균 6초
2. Lettuce - 평균 34초
3. Redisson - 평균 12초

Redis를 이용한 분산락 구현 코드는 강사님의 강의를 따라했는데 혹시 이런 결과가 나오는 이유가 무엇일까요?

제 추측으로는 Lettuce 를 이용하는 방식에서는 2000개의 스레드가 반복적으로 락 획득 요청을 보냄에 따라 Redis에 부하가 심해서 속도가 느려질 수 있을 것 같은데 Redisson 을 이용한 방식은 왜 느린지 전혀 모르겠습니다.

답변 2

0

최상용님의 프로필 이미지
최상용
지식공유자

W-Hand 님 안녕하세요.

데이터의 양, 요청수의 양에 따라서 성능이 다를 수 있습니다.

데이터와 요청수가 적다면 보시는 것과 같이 비관적락이 성능이 더 좋을 수 있으며 데이터 수가 많고 요청수가 많아질수록 redis 의 성능이 우수할 것입니다.

2000개의 스레드는 사실 많은 요청이 아니라 redis 가 느리게 보일수도 있습니다.

감사합니다.

W-Hand님의 프로필 이미지
W-Hand
질문자

답변 감사합니다.
말씀해주신 바로는 요청 수의 양이 많이질수록 DB에서 제공하는 비관적 락 보다는 Redis 를 이용해 분산 락을 구현하는 것이 더 성능면에서 뛰어날 것이라고 이해됩니다.

그럼 현업에서 동시성 문제를 해결하기 위해 적용 가능한 수단들을 놓고 비교할 때 우리 서비스에서 동시에 발생 가능한 최대 트래픽이 많지 않고 서비스 로직이 단순해 데드락 발생 가능성이 없다고 판단되면 비관적 락을 이용하기도 하나요?

최상용님의 프로필 이미지
최상용
지식공유자

최대 트래픽이 많지 않을 때는 비관적락 또는 낙관적락을 고려해볼 수 있을 것 같습니다 :)

W-Hand님의 프로필 이미지
W-Hand
질문자

염치 불구하고 질문 하나만 더 드리겠습니다.

Redis를 이용한 분산 락 구현 시
1. Redis 를 통해 락 획득
2. 트랜잭션 시작
3. 서비스 로직 수행
4. 트랜잭션 종료
5. 락 반납

DB를 이용한 비관적 락 구현 시
1. 트랜잭션 시작
2. 락 획득
3. 서비스 로직 수행
4. 트랜잭션 종료
5. 락 반납

과 같은 과정을 거칠 것으로 예상이 됩니다.

결국 Redis 를 이용한 방식은 인 메모리 저장소라고 하더라도 Redis 에 접근하는 과정이 추가되는 것이고 아주 약간의 시간 소요라도 있을 것으로 생각됩니다.

그럼에도 요청이 많아질 수록 Redis 를 이용하는 것이 성능 면에서 우수한 것은
'DB 락 획득-반납 소요 시간' > 'Redis 락 획득-반납 소요 시간' 이기 때문인 건가요?

0

안녕하세요, 인프런 AI 인턴이에요.

Redis를 이용한 분산락 구현의 성능 개선을 원하신다면 다음과 같은 방법들을 고려해보실 수 있습니다.

  1. Redis 클러스터를 사용하는 것을 고려해보세요. 클러스터를 사용하면 Redis에 대한 부하가 분산되어 더욱 효과적으로 분산락을 사용할 수 있습니다.
  2. Redis 클라이언트 풀링을 도입하여 클라이언트의 수를 제어해보세요. 클라이언트 수가 너무 많아질 경우 Redis에 대한 부하가 크게 증가할 수 있습니다.
  3. Redis 클러스터 내의 레플리카를 사용하여 성능을 개선할 수 있습니다. 레플리카를 사용하면 Redis 클러스터 내의 여러 노드에서 데이터의 일관성을 유지하면서 부하를 분산할 수 있습니다.

또한, 성능 향상을 위해 Redis 클러스터의 구성과 관리 방법에 대해 잘 고민하고 구현하셔야 합니다. 이를 위해 Redis 공식 문서와 관련 책 등을 참고하시면 도움이 될 것입니다.

성능 향상에 대한 시도를 하시다가 문제가 생길 경우 Redis의 설정도 살펴봐야 합니다. Redis의 설정을 최적화하면 더욱 원활한 분산락 구현이 가능할 것입니다.

추가적으로, 코드에서 사용하는 Redis 클라이언트 라이브러리와 버전에 따라 성능이 차이가 날 수 있으니 해당 부분도 신경써보세요.

마지막으로, Redisson을 사용할 경우 Lettuce보다는 성능이 향상되지만 Redisson이 제공하는 다양한 기능들로 인해 추가적인 리소스가 필요할 수 있습니다. 이 부분도 고려하셔서 적절한 구현 방법을 선택하시면 될 것 같습니다.

저희가 도움이 되었길 바랍니다. 감사합니다.

W-Hand님의 프로필 이미지
W-Hand

작성한 질문수

질문하기