강의

멘토링

커뮤니티

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

songso0412님의 프로필 이미지
songso0412

작성한 질문수

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

게시글 생성 로직에서 오류 발생시 redis 게시글 수 되돌리기

해결된 질문

작성

·

44

0

게시글 생성 로직에서 만약 오류 발생시에 db는 롤백이 되는데 만약 redis에 저장된 게시글수가 이미 증가됐다면 감소를 시켜야 하는데 어떻게 처리하는게 좋을까요

답변 2

0

쿠케님의 프로필 이미지
쿠케
지식공유자

songso0412님, 안녕하세요!

 

강의에서는 게시글 생성과 게시글 수의 정합성을 위해 모두 rdb에 저장하고 단일한 트랜잭션으로 관리하는 전략을 취하고 있는데요,

그와 별개로 redis에 게시글 수를 저장하는 상황을 말씀하시는 것일까요?

rdb 트랜잭션이 커밋된 후에 redis 증가가 실패하거나,

redis 증가된 후에 rdb 트랜잭션이 롤백되는 경우가 있겠네요.

 

정합성을 반드시 100% 완벽하게 지켜야하는지에 대해서도 고민해볼 수 있을 것 같습니다.

이러한 상황이라면 트랜잭션이 롤백될 때의 예외를 캐치해서, 애플리케이션에서 redis 카운트를 다시 감소시켜주면 됩니다.

물론 이렇게 하면 redis 감소 코드가 실패할 수도 있기 때문에 정합성은 완벽하게 보장되진 않습니다.

하지만 오류로 인해 정합성이 깨지는 상황이 흔하게 발생하는 것도 아니고, 어떤 데이터인지에 따라서 깨지는게 문제되지 않을 수도 있습니다.

후처리 보정을 넣는 전략도 겸할 수 있는 것이고요. 감지가 되었을 때, 문의가 들어왔을 때, 주기적으로 검사(샘플링 등)할 때 등 데이터의 정합성을 뒤늦게 보정 시켜줘도 시스템 운영에 크게 문제가 없을 수 있습니다.

무튼 이렇게 애플리케이션에서 보상 트랜잭션을 수행해서 해결할 수 있습니다. (별도의 트랜잭션 또는 로직으로 정합성을 맞춘다는 의미입니다. 하지만 보상 트랜잭션에 대한 실패에 대한 고려도 필요하네요.)

 

근데 정합성이 주요하다면, rdb 트랜잭션으로 묶어내는게 가장 간단하고 확실한 해결책일 수 있습니다.

정합성을 위한 다른 방법으로는, 마지막 챕터에서 소개하는 Transactional Outbox 전략과 컨슈머의 멱등 또는 중복 방지 전략을 취할 수도 있습니다.

게시글 생성 트랜잭션이 완벽하게 종료되었을 때에 이벤트를 유실 없이 보내고, 컨슈머에서는 게시글 수를 증가시켜줍니다. 물론 중복 이벤트에 대한 문제가 발생할 수 있기 때문에 일정 시간 버퍼해두거나 처리한 이벤트에 대해서는 관리하는 전략을 겸해야겠네요.

 

어떠한 사유로 redis에 관리하시려는 의도인지 정확히 파악한건 아니지만,

저라면 정합성이 필요한 데이터를 rdb/redis에 분리 저장하면서까지 인프라와 운영 복잡도를 높일 바에야 rdb 단일 트랜잭션을 이용할 것 같습니다.

조회 성능에 대한 우려가 있다면(공간에 대한 우려는 오히려 없을 것이고요), rdb에 먼저 쓰기 작업을 한 뒤에 redis에 읽기용으로 따로 데이터를 캐시해둘 수도 있는 것이고요.

 

딱히 정답은 없고 시스템 운영 방식에 따라서 해결책도 다양할 수 있어서, 상황에 알맞게 적당한 방법을 찾아나가는게 좋을 것 같네요!

0

안녕하세요, 인프런 AI 인턴입니다. songso0412님.

게시글 생성 로직에서 오류 발생 시, Redis에 저장된 게시글 수를 되돌리는 문제는 트랜잭션 관리 및 데이터 일관성을 유지하는 데 중요한 이슈입니다.

가능한 해결 방법

  1. 트랜잭션 전략:

    • Redis와 데이터베이스에 대해 하나의 트랜잭션 범위로 묶는 것은 어렵기 때문에 보통 보상 트랜잭션(Compensating Transaction) 방식을 사용합니다. 이는 오류가 발생했을 때 이미 수행된 작업을 취소하는 로직을 포함하는 것입니다.
  2. 보상 트랜잭션 구현:

    • 게시글 생성 트랜잭션이 실패하면, Redis에 이미 증가한 게시글 수를 감소시키는 로직을 추가합니다. 이때 Redis의 decrement 연산을 사용할 수 있습니다.
    • 예를 들어, Spring의 @TransactionalEventListener를 사용하여 트랜잭션 실패 시 특정 이벤트를 발생시키고, 그에 대응하는 보상 동작을 수행할 수 있습니다.
  3. Redis 트랜잭션 사용:

    • Redis 자체에서 트랜잭션 기능(MULTI/EXEC)을 사용하여 여러 명령을 하나의 트랜잭션으로 묶어서 실행할 수 있습니다. 그러나 이 방법은 단일 Redis 명령 블록 내에서만 적용 가능하므로 복잡한 보상 트랜잭션에는 한계가 있습니다.

추가적인 고려사항

  • 결과 일관성: 비즈니스 로직의 일관성을 유지하기 위해 반드시 트랜잭션의 성공/실패에 따라 Redis의 데이터도 정확하게 조정되어야 합니다.
  • 장애 대응성: 만약 Redis 연결 장애가 있더라도, 자동 복원이나 재시도 로직을 통해 데이터를 정확히 조정할 수 있습니다.

추가적으로 확인할 수 있는 참고 자료로는 다음 링크를 추천드립니다:
- Redis와 Database의 일관성 문제 해결 방법

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

songso0412님의 프로필 이미지
songso0412

작성한 질문수

질문하기