Skip to content

김현수 9주차 개인 회고

Kim Hyunsu edited this page Aug 25, 2024 · 3 revisions

목록: 김현수
특이사항: pair coding with @june-777

대규모 트래픽에서 정합성 보장 및 DB 부하 최소화

대안1: 낙관적 Lock 사용 + (비동기 스레드)

낙관적 Lock 고민 배경

  • 비관적 Lock을 사용하는 경우, 주문 트래픽이 몰릴 경우 DB 부하가 심해질 수 있음
  • 낙관적 Lock을 사용하여, DB 부하를 애플리케이션 레벨로 분산시키자.

비동기 스레드 고민 배경

  • 낙관적 Lock을 사용 시, 동시성 이슈에 대해 재처리 로직을 수행해야 한다.

  • 주문 3회 재시도 등 재처리 로직을 수행하면, 해당 응답을 수행하는 만큼 톰캣 커넥션 풀을 물고 있어야 함

  • 이를 비동기 워커 스레드로 분리하여 해결할 수 있지 않을까

    • 클라이언트가 요청이 처리가 되었는지 알려면 결국 서버와 연결이 되어 있거나 요청을 계속 보내야하기 때문에 결국 서버 부하가 생긴다.
    • 결제 완료/실패 알림은 1-2분 뒤에 와도 된다고 가정하고 풀링 간격을 1분으로 해 요청 빈도를 낮춘다.
  • 동적으로 전략을 바꾸는 방법도 고려해보는 것도 좋겠다.

    1. 비동기로 처리하는 서비스, 2)동기로 처리하는 서비스로 나누어서 구현하고 각각의 서비스가 효율적인 TPS 지점을 확인해보자.
  • 트래픽을 기준으로 요청을 분기하는 방식

  • 결제 API

대안2: 하이브리드 락 기법 사용

  • 낙관적 락을 사용하다가 재고가 임계치 이하로 줄어들면 비관적 락을 적용하는 방법

단일 서버에서는 쉽게 해결될 수 있음/ 하지만 분산 서버일 때도 고려는 해보자

  • 일반적인 상황에서는 낙관적 락 사용, 재고가 임계치 이하로 떨어지면 비관적 락으로 전환

재고 수 캐시에 대한 논의

1. 재고 수량 Redis 캐싱 시점

방안1. 서버 로드 시점에, 모든 메뉴의 재고 수량을 웜업

단점: 불필요한 Redis 메모리 사용률 증가

  • 750만건의 메뉴에 대한 재고 수량을 Redis에 웜업하면, 불필요하게 Redis 메모리 사용량이 증가함

방안2. 서버 로드 시점에, 인기 가게 메뉴의 재고 수량만 웜업

단점: 성능 테스트가 어려움, 서비스 운영 시점에 고려해볼만 함

방안3. 카트에 메뉴를 넣는 시점에 재고 수량을 캐싱

  1. Redis에 메뉴의 재고가 캐싱되어 있으면, 캐싱된 데이터는 최신정보이므로, 캐싱받은 재고로 장바구니에 메뉴를 추가한다.
  2. Redis에 메뉴의 재고가 캐싱되어 있지 않으면, 메뉴 ID에 분산락을 걸고 메뉴의 재고를 캐싱한다.
    1. 분산락을 거는 이유: 주문하기 API에서 Redis에 재고를 최신화하는 과정에서, 재고 정합성 불일치가 발생할 수 있기 때문
  3. 분산락이 이미 걸려있으면, 메뉴의 재고가 캐싱되어 있는지 다시 확인한다.
    1. 분산락이 걸려있다는 것은 카트담기API 혹은 주문하기API에서 메뉴 재고를 최신화하고 있다는 의미이므로.
트랜잭션을 반드시 걸어야하는 이유 재고 접근 시나리오 재고 접근 시나리오
시스템 설계 트랜잭션을 반드시 걸어야하는 이유 재고 접근 시나리오
sequenceDiagram
    participant C as 클라이언트
    participant CS as 장바구니서비스
    participant CR as 장바구니저장소
    participant MR as 메뉴저장소
    participant R as 레디스
    participant DB as 관계형DB
    participant LS as 잠금서비스

    C->>CS: addMenu(AddCartCommand)
    CS->>CR: getCart(customerId)
    CR-->>CS: 고객 장바구니 반환

    CS->>DB: findByIdWithStore(menuId)
    alt 메뉴 찾음
        DB-->>CS: 메뉴 반환
        loop 메뉴ID 확인 및 저장
            CS->>R: 메뉴ID 존재 여부 확인
            alt {메뉴ID:재고}가 레디스에 존재
                R-->>CS: 존재 확인 + RDB는 과거 정보이고 Redis 는 최신 정보이기 때문에 RDB에서 반환받은 재고를 Redis 재고로 업데이트
            else {메뉴ID:재고}가 레디스에 없음
                CS->>LS: 락 확인(menuId)
                alt 락이 걸려있지 않음
                    LS-->>CS: 락 없음
                    CS->>LS: 락 설정(menuId)
                    CS->>R: 메뉴 재고 정보 저장
                    CS->>LS: 락 해제(menuId)
                else 락이 걸려있음
                    LS-->>CS: 락 존재
                    Note over CS: 짧은 대기 후 [메뉴ID 확인 및 저장]루프 처음으로 돌아가 재시도
                end
            end
        end
        CS->>CS: 장바구니에 메뉴 추가
        CS->>CR: 장바구니 저장
        CR-->>CS: 저장 완료
        CS-->>C: 성공 응답
    else 메뉴 없음
        CS->>C: MenuNotFoundException 발생
	    end
Loading

2. 재고 수량 Redis-RDB 정합성 문제

sequenceDiagram
    participant C as 클라이언트
    participant CS as 장바구니서비스
    participant R as 레디스
    participant DB as 관계형DB
    participant LS as 잠금서비스

    C->>CS: 장바구니 아이템 처리 요청
    loop 각 장바구니 아이템에 대해
        loop 메뉴ID 확인 및 처리
            CS->>R: {메뉴ID:재고} 존재 여부 확인
            alt {메뉴ID:재고}가 레디스에 존재
                CS->>R: 원자적으로 재고 감소
                alt 재고 < 0
                    CS->>R: 롤백 (재고 증가)
                    CS->>C: 재고부족 예외 발생
                    Note over CS: 재고 부족 이 발생하면 기존 재고 감소를 기록한 리스트를 돌면서 다시 재고를 증가시켜주는 로직을 추가해야함
                else 재고 >= 0
				            CS->>CS: 재고 수정 로그 리스트에 {메뉴ID:수문수량} 기록
                end
            else {메뉴ID: 재고}가 레디스에 없음
                CS->>LS: 락 확인(menuId)
                alt 락이 걸려있지 않음
                    LS-->>CS: 락 없음
                    CS->>LS: 락 설정(menuId)
                    CS->>DB: 재고 조회
                    DB-->>CS: 재고 반환
                    CS->>CS: 재고 감소
                    alt 재고 < 0
                        CS->>CS:  (재고 증가)
                        CS->>R: 재고 정보 저장
                        CS->>C: 재고부족 예외 발생
                        Note over CS: 재고 부족 이 발생하면 기존 재고 감소를 기록한 리스트를 돌면서 다시 재고를 증가시켜주는 로직을 추가해야함
                    else 재고 >= 0
	                      CS->>R: 재고 정보 저장
				            CS->>CS: 재고 수정 로그 리스트에 {메뉴ID:수문수량} 기록
                    end
                    CS->>LS: 락 해제(menuId)
                else 락이 걸려있음
                    LS-->>CS: 락 존재
                    Note over CS: 짧은 대기 후 [메뉴ID 확인 및 처리]루프 처음으로 돌아가 재시도
                end
            end
        end
        Note over CS: [주문 성공 시]<br/> RDS 동기화 옵션 고려:<br/>1. 비동기 업데이트<br/>2. 예약된 업데이트
    end
    CS->>C: 결과 반환 
Loading

비동기 where update 로 진행하고 나중에 배치 고려

재고 부족 이 발생하면 기존 재고 감소를 기록한 리스트를 돌면서 다시 재고를 증가시켜주는 로직을 추가해야함…

image image

👼 개인 활동을 기록합시다.

개인 활동 페이지

🧑‍🧑‍🧒‍🧒 그룹 활동을 기록합시다.

그룹 활동 페이지

🎤 미니 세미나

미니 세미나

🤔 기술 블로그 활동

기술 블로그 활동

📚 도서를 추천해주세요

추천 도서 목록

🎸 기타

기타 유용한 학습 링크

Clone this wiki locally