inflearn logo
강의

Khóa học

Chia sẻ kiến thức

Thiết kế hệ thống máy chủ chịu được lưu lượng tăng đột biến - Dịch vụ phát hành Coupon

[Thực hành] Hoàn thiện việc phát hành coupon bất đồng bộ dựa trên Kafka

kafka 이벤트 발행 실패 시 at-least-once를 보장하는 방법이 궁금합니다.

Đã giải quyết

71

clw86799822

21 câu hỏi đã được viết

1

안녕하세요! 강의 잘 듣고 있습니다.

아래 issue 메서드 관련해서 질문드립니다.

@Transactional
fun issue(couponId: Long, userId: Long): Issuance {
    val policy = couponIssuePolicyReader.get(couponId)

    val now = LocalDateTime.now()
    if (!policy.isBookingOpen(now)) {
        throw NotStartedException()
    }

    val expiresAt = now.plusDays(policy.validityDays.toLong())
    couponIssuer.tryIssue(couponId, userId)
    issuanceRequestProducer.publish(
        IssuanceRequested(
            couponId = couponId,
            userId = userId,
            issuedAt = now,
            expiresAt = expiresAt,
        )
    )

    return Issuance(
        userId = userId,
        couponId = couponId,
        issuedAt = now,
        expiresAt = expiresAt,
    )
}

해당 코드에서 couponIssuer.tryIssue()(Redis)는 성공했는데 바로 다음 issuanceRequestProducer.publish()(Kafka)가 실패하는 경우 재고는 차감됐는데 이벤트는 유실된 불일치 상태가 될 수 있을 것 같습니다.

만약 재고를 DB로 관리한다면 아웃박스 패턴으로 같은 트랜잭션 안에서 이벤트를 아웃박스 테이블에 적재하고 별도 워커가 Kafka에 발행하는 방식으로 원자성을 보장할 수 있을 것 같습니다.

그런데 지금처럼 재고 자체를 Redis로 관리하는 구조에서는 Redis와 Kafka 각각에 대한 이중 쓰기 문제가 생기고 아웃박스 패턴을 그대로 적용하기는 어려워 보입니다.

만약 해당 구조에서 at-least-once를 보장하려면 어떤 전략을 택해야 하는지 궁금합니다!

java kotlin mysql docker spring-boot kafka redis

Câu trả lời 1

1

apiece

안녕하세요 이찬원님!

좋은질문 감사드립니다. 예리하게 잘 잡아주셨네요.
말씀하신 대로 현재 코드는 Redis 차감 후 Kafka 발행 전에 장애가 발생하면 이벤트가 유실될 수 있습니다.

따라서 신뢰성이 높은 구조를 만들기 위해, 여러 방법을 떠올려볼 수 있을 것 같아요.

첫번째로는 Redis 에서도 Outbox 패턴처럼 사용하는 방법을 사용하는 것입니다.

Lua → Redis Stream → Connector → Kafka Topic같은 방식으로,
Lua 스크립트(원자연산) 안에서 재고 차감 후, Redis Stream 으로 이벤트발행을 함께 실행합니다. 그리고 별도 워커나 Connector가 Stream을 읽어 Kafka에 발행합니다.
커넥터가 발행에 실패하거나 워커가 중단되면 메시지가 미처리 상태로 남으므로, 다시 처리할 수 있습니다. (at-least-once 등 여러 옵션을 지원합니다.)
다만, 이 구조는 본 환경에서 검증이 필요하며, Redis에는 AOF와 복제를 적용하고, 처리되지 않은 Stream 메시지가 삭제되지 않도록 보존 정책도 관리해야 합니다. Redis 에 대한 관리포인트도 늘어납니다.


두번째로는, 5단원 정합성에서 다루게 되는 대사입니다. (벌써 3단원이니 곧 만나실 것 같습니다.)
주기적으로 Redis 와 DB 쿠폰발급 데이터를 점검하여 데이터를 바로잡는 방식인데요. 해당 단원에서도 위의 케이스는 저희가 다루지는 않지만, 위 문제의 경우 예를들어 이벤트가 재발행되도록 하는 조치를 해볼 수 있을 것 같습니다.


사실 이런 문제를 해결하는 건 명확한 답이 있다기 보다는, 그 상황에 맞는 적절한 방법을 선택해서 구현하게 됩니다. 그래서 이 외에 다른 더 좋은 방법이 있을 수도있어요. 찬원님 질문덕에 저도 여러가지를 떠올려보다가 괜찮은 방법을 한번 답변드렸고, 실무라면 결국에는 좀 더 관리하기 편하고 신뢰성있는 방법을 고를 것 같습니다!


감사합니다.

1

clw86799822

답변 감사합니다!

섹션2, 대화&세션관리 수업 자료 누락

0

9

1

영상 다운로드는 안되나요?

0

11

0

Producer의 동기 전송 및 비동기 전송 관련 질문

0

13

1

IntelliJ IDEA 체험 만료

0

12

1

부하 테스트 시 설정 관련 질문드립니다

1

30

1

HelloSpringApplication.java 클래스 실행 오류

0

12

1

섹션 2

0

17

1

"도커 이미지 생성" 18:59부분에 텍스트 파일로 정리 된거는 어디서 볼수 있나요?

0

19

1

pub/sub의 연결 객체에 대해 질문 드립니다.

0

22

2

build 시 에러 해결방법 공유(docker.desktop 업데이트 -> 의존성 버전 수정)

0

32

2

예외처리 3강 문의

0

32

1

챌린지 시작일 문의

0

39

0

Inner class로 Config를 지정하는 이유

0

29

1

sakila 실전 17번 문제

0

23

1

Request Failed 가 뜹니다.

0

29

2

복합인덱스 설계 질문

0

55

1

Hive metastore setup중에 오류 발생

0

36

2

26년2회 실기기출은 언제쯤...

0

59

2

네이버 API | '검색 - 책' API 제공 중단

0

42

2

ArticleReadService 관련 질문

0

30

1

domain에 @Entity 와 Repository를 함께 둔 이유가 궁금합니다

1

52

1

Jib 이미지 빌드에서 docker credential 관련으로 이슈가 있다면

1

82

1

스크립트에 대해 질문 있습니다.

1

60

1

같은 사용자가 연속된 중복 호출할 경우 어떻게 되는지 궁금합니다!

2

74

1