[SSA] Redis의 특징을 활용한 동시성 제어 (Redis 분산 락 아님)

2025. 9. 13. 01:50·SSA/Back

이전 글(특강에 대한 수강신청 동시성 처리)에서 다음과 같은 락에 대해 고민하며

프로젝트에 적합한 락을 적용하려고 여러 테스트를 진행해 봤습니다.

  • Redis 분산 락
  • DB 낙관적/비관적 락
  • MySQL 네임드 락

 

그러던 중 "Redis의 특징에 대해서 한 번 고민해 보셔라"라는 조언을 듣고 문득 떠오르는 것이 있었습니다.

 

Redis는 싱글 쓰레드로 동작한다

 

 

싱글 쓰레드로 동작한다는 특성 때문에 여러 요청이 들어와도 들어온 순서대로 처리하게 됩니다.

 

따라서 Redis 분산 락/DB 비관적 락 등의 Lock을 활용하지 않고,

특강에 대한 수강신청 동시성을 제어해 보려고 합니다.

 

 

Redis를 활용해서 특강 동시성을 제어하려면

  • 특강 개설 시 해당 강의의 수강정원을 미리 Redis에 로드하거나 수강신청 개시 때 수강정원을 Redis에 로드
    • 특강 정보를 Redis에 너무 많이 담아 두면 메모리가 부족할 수 있으므로 타임아웃 같은 걸 설정해 보는 것도 좋을 것 같음
  • API 요청 시 Redis에 해당 특강의 고유 정보를 통해 수강정원에서 0으로 줄이거나 0에서 수강정원까지 늘리거나 처리
    • "special-lecture:{specialLecutreId}:capacity"
    • "special-lecture:{specialLecutreId}:enrolled_count" 와 같은 고유 정보로 key를 저장
  • Redis는 API 요청과 응답만을 담당하고 실제 DB에 저장하는 것은 Kafka를 활용
    • Kafka에 토픽이 발행되고 소비돼서 DB에 쓰이기까지 지연 시간이 발생
    • 특강 수강신청에 성공한 사람이 바로 특강 수강 정보를 조회할 경우 수강신청이 완료되지 않은 것으로 보일 수도 있음
      1. 이 부분은 특강 수강신청 전에 완료까지 시간이 걸릴 수도 있다고 미리 알리거나
      2. 수강신청에 성공했다면 해당 사용자에게 알림을 보내서 조회까지 시간이 조금 걸릴 수도 있다고 알려 줘도 될 것 같음

 

 

위 내용으로 다음 내용을 구현하고 테스트해 보겠습니다.

  1. 특강 개설 시 해당 강의의 수강정원을 미리 Redis에 로드하거나 수강신청 개시 때 수강정원을 Redis에 로드
  2. API 요청 시 Redis에 해당 특강의 고유 정보를 통해 수강정원에서 0으로 줄이거나 0에서 수강정원까지 늘리거나 처리
  3. Redis는 API 요청과 응답만을 담당하고 실제 DB에 저장하는 것은 Kafka를 활용

 

 

# Redis - 싱글 쓰레드 활용 > Kafka 메시지 전송

모니터링입니다.

 

 

 

이전에 테스트했을 때 제일 성능이 좋았던 DB 비관적 락을 다시 보겠습니다.

 

 

 

 

조금 더 핵심적인 부분을 살펴 보자면,

Redis 싱글 쓰레드 성능 지표

 

DB 비관적 락 성능 지표

 

 

 

# 시스템 전체 흐름도 (중간 점검, 최종 적용 아님)

  

  • 수강 신청 요청 (빠른 응답)
    • 1. 사용자(Client)가 Course 서버(Course 모듈)로 특정 특강에 대한 수강 신청 API를 호출합니다.
    • 2. Course 서버는 DB 대신 Redis의 고유 key를 사용해 해당하는 값의 수강 인원을 1 증가시키고, 정원 마감을 확인합니다.
    • 3. 신청이 가능하면, 사용자에게 신청 완료 응답(200 OK)을 보냅니다.
  • DB 저장 요청 (비동기)
    • 4. Course 서버는 사용자에게 응답을 보낸 후, 백그라운드에서 Kafka에 "수강 신청 성공" 메시지를 보냅니다.
  • DB 작업 처리
    • 5. 구독 중인 컨슈머(Consumer)가 Kafka로부터 "수강 신청 성공" 메시지를 받아 옵니다.
    • 6. 컨슈머는 데이터베이스에 트랜잭션(여기서 트랜잭션을 사용해 줘야 함)을 열고, 실제 special_lecture 테이블의 수강 인원을 1 증가시킨 후 special_lecture_enrollment 테이블에 수강생 정보를 최종적으로 저장합니다.
  • 알림 요청 (비동기)
    • 7. DB 작업이 성공적으로 커밋되면, 컨슈머는 다시 Kafka에 "알림 발송" 메시지를 보냅니다.
    • 8. 컨슈머는 Kafka에 메시지 처리가 모두 완료되었음을 알립니다(Acknowledge).
  • 알림 발송
    • 9. Notification 서버는 Kafka로부터 "알림 발송" 메시지를 받아, 해당 사용자에게 "특강 신청이 최종 완료되었습니다" 등의 SSE 또는 FCM 알림 등을 발송합니다.

 

 

 

 

 

 

 

 

 

# Redis - 싱글 쓰레드 활용 > DB 쓰기

 카프카 말고 직접 DB에 쓰는 기본적인 방법을 활용하는 경우입니다.

 

 

 

 

 

 

세 가지 동시성 제어 방식에 대한 성능 테스트 결과는 다음과 같습니다.

지표 (Metric) Redis + DB Redis + Kafka DB 비관적 락
초당 처리량 (Throughput) 609 req/s 415 req/s 106 req/s
총 처리 요청 수 24,114건 17,057건 12,493건
성공한 요청 100건 100건 100건
전체 요청 평균 응답 시간 0.734.s 5.27s 9.18s
성공한 요청 평균 응답 시간 75.8ms 125ms 1.03s
 

 

 

 

# 결론: Redis + DB 사용, (Kafka 아키텍처 적용 X)

DB의 비관적 락을 활용하는 경우는 데이터 정합성이 무엇보다 중요할 경우 사용할 수 있을 것 같습니다.

그러나, 성능상으로는 이점을 챙길 수 없습니다.

 

Redis + Kafka의 경우 카프카에 메시지를 발행하는 시간 동안

사용자가 본인의 특강 수강신청 결과를 조회할 수 없다는 문제가 발생할 수 있습니다.

특강 같은 경우에 조금 더 신경써서 신청하는 만큼 결과를 즉각적으로 확인하고 싶어할 것이기 때문에

즉각적인 확인이 더 중요한 경우에는

 

Redis + DB를 사용할 것 같습니다.

Kafka로 발행하는 경우가 현재로서는 굳이 이유가 없을 뿐더러,

즉각적인 확인이 불가한 만큼 카프카 대신 DB에 직접 쓰는 작업을 사용할 것 같습니다.

 

 

만약에 만약에,

비즈니스적인 요구사항으로 매우 즉각적인 확인보다

'조금 유연한 확인(살짝 늦게 확인해도 됨)'이 가능할 경우에는

정말 대량의 요청이 들어올 때를 고려한다면

Redis + Kafka를 활용해서 Redis의 속도적인 측면과 Kafka(데이터를 디스크에 저장)로 데이터 유실의 문제를 어느 정도

해결해 보는 등의 절충안은 적용해 볼 만도 할 것 같습니다.

 

 

 

 

 

 

 

 

'SSA > Back' 카테고리의 다른 글

[SSA] 스케줄러를 통해 Retry를 하게 될 경우 트랜잭션 처리  (0) 2025.12.11
[SSA] 카프카 메시지를 발행할 때 ZERO-PAYLOAD ? 아니면 Event-Carried State Transfer ?  (0) 2025.12.11
[SSA] 특강 개설 시 선착순 동시성 이슈 해결  (2) 2025.09.10
[SSA] 수강 로직에 대한 간단한 고민 ..  (0) 2025.09.09
[SSA] 락의 종류와 활용 가능한 상황  (0) 2025.09.09
'SSA/Back' 카테고리의 다른 글
  • [SSA] 스케줄러를 통해 Retry를 하게 될 경우 트랜잭션 처리
  • [SSA] 카프카 메시지를 발행할 때 ZERO-PAYLOAD ? 아니면 Event-Carried State Transfer ?
  • [SSA] 특강 개설 시 선착순 동시성 이슈 해결
  • [SSA] 수강 로직에 대한 간단한 고민 ..
하가네
하가네
  • 하가네
    하 렌
    하가네
  • 전체
    오늘
    어제
    • 분류 전체보기 (128) N
      • Computer Science (23)
        • 운영체제 (7)
        • 데이터통신 (6)
        • 자료구조 (4)
        • 논리회로 (0)
        • 확률 및 통계 (0)
        • 데이터베이스 (2)
        • AI소프트웨어 (3)
        • 컴퓨터네트워크 (1)
      • Design (5) N
        • OOP - 객체 지향 프로그래밍 (3) N
        • DDD - 도메인 주도 개발 (데이터베이스 주도 .. (0)
        • EDA - 이벤트 기반 아키텍처 (1)
        • MSA - 마이크로서비스 아키텍처 (0)
        • ADD - AI 주도 개발 (1)
      • Language (2)
        • Java (0)
        • TypeScript (2)
      • Framework (12)
        • Spring (9)
        • NestJS (3)
      • Engine (3)
        • Elasticsearch (1)
        • GraphQL + Apollo Federation (2)
      • Plugin - Extension (1)
        • VS Code (1)
        • IntelliJ (0)
      • Tips (2)
        • 터미널 명령어 (1)
        • 우분투 명령어 에러 (1)
      • SSA (26)
        • Front (1)
        • Back (23)
        • DB (1)
        • 기획 (1)
      • CNU SW 아카데미 (42)
        • 1주차 (5)
        • 2주차 (5)
        • 3주차 (2)
        • 4주차 (1)
        • 5주차 (3)
        • 6주차 (2)
        • 7주차 (0)
        • 8주차 (1)
        • 9주차 (14)
        • 10주차 (0)
        • 11주차 (1)
        • 12주차 (0)
        • 13주차 (2)
        • 14주차 (2)
        • 15주차(최종 프로젝트) (3)
        • 최종 프로젝트 이후 (1)
      • 모각코 (6)
        • 2023 동계 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    릴리스엔지니어링
    ESLint
    DX(DeveloperExperience)
    프론트엔드/백엔드
    아키텍처
    lint-staged
    Typescript
    생산성
    개발자경험(DX)
    Husky
    ci/cd
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.
하가네
[SSA] Redis의 특징을 활용한 동시성 제어 (Redis 분산 락 아님)
상단으로

티스토리툴바