partitioning을 정해진 수의 Stream들에 적용해 보았다

김형준·6일 전
0

1. 초기 기획

  • Restaurant 테이블의 row 수와 Stream 수를 1:1로 만들려 했다.
  • 각 Restaurant 예약에 대한 경합을 완전히 분리하기 위함
    • 예) 완전히 분리 시 1변 Restaurant에 요청이 몰릴 경우에도 2, 3, 4, 5번 Restaurant에 대한 예약은 영향받지 않음
  • 하지만 row 수와 Stream 간 1:1 매핑을 위해서는 Restaurant 추가/삭제에 Stream 측이 민감하게 반응해야 했다.
    • Consumer들은 Restaurant 수 변경에 따라 Consumer group에 대한 구독/구독 취소를 실시간으로 수행해야 함
    • Restaurant 추가/삭제 서비스에서도 이에 대한 이벤트를 발행하도록 수정되어야 하기에 코드가 많이 복잡해짐
  • 또한 row가 무한정 늘어나면 Stream 또한 무한정 늘어나기에 Redis가 Memory를 필요 이상으로 사용한다.

2. 수정사항

Stream이 무한정 늘어나는 것을 방지하면서도 각 Restaurant 별 예약 요청을 최대한 분리해서 처리하기 위해 아래와 같은 기획사항을 도입하였다.

  1. Spring 실행 시 설정값(고정된 수)만큼의 Stream 생성

    1-1. 생성되는 Streams의 이름은 reservation-create-N가 됨

  2. 각 Consumer들은 모든 Stream에 구독

  3. Producer가 Message 발행 시 요청 객체의 restaurant id가 전체 restaurant의 count 값 중 어느 partition에 속하는지 확인

    3-1. Math.ceil([restaurant Id] * [stream number] / [restaurant count]) 값을 기반으로 발행할 Stream을 결정

    3-2. 발행 전 publisher가 restaurant count 값을 조회하도록 함

    a. [count 조회] → [메시지 발행] 과정 중간에 restaurant 추가/삭제되어서 count 값이 바뀌어도 사용하게 될 메시지 큐만 조금 달라지기에 큰 문제는 없다고 판단함

요약하자면, Stream 별로 담당하는 Restaurant들을 나누도록 구현해 특정 식당에 예약이 몰릴 경우 다른 식당 예약에 대한 영향을 최소화하도록 구현하였다.

3. 테스트 수행

partitioning 적용 전과 성능 측면에서 어떤 차이가 있는지 비교 테스트를 진행해보았다.

테스트 세팅





테스트 결과

  • partitioning 적용 전

  • 적용 후

여러 식당들에 예약하는 시나리오 기준 속도가 1.7배 정도 향상되었다.

0개의 댓글

관련 채용 정보