강의

멘토링

커뮤니티

Inflearn Community Q&A

choing's profile image
choing

asked

Learning Large-Scale System Design by Building Directly with Spring Boot - Bulletin Board

Like Count Design - Concurrency Issues

좋아요 동시성처리 최적의 선택?

Resolved

Written on

·

29

·

Edited

0

  1. 강의에서는 비관적 락과 낙관적 락을 다루셨는데, 일반적으로 대규모 서비스가 아닌이상 좋아요 자체가 순식간에 많은 트래픽이 몰릴것같지않아 낙관락으로 처리하는 것이 더 효율적일것같다고 생각이듭니다. 그래도

    극단적인 상황을 대비해서, 뒤에서 나오는 조회수 처리처럼 레디스로 좋아요 수를 증가시키고 스케줄링같은걸로 RDB에 백업하는 방식은 어떤가요?

  2. 동시성처리에서 비관적 락으로만 처리해야 하는 상황이 있을까요? 레디스의 분산 락을 사용하는 것이 성능 측면에서 비관락보다 유리할 때도 있을 것 같은데, 실제로 비관락을 반드시 써야 하는 예시나 사례가 궁금합니다.

  3. RDB 트랜잭션(@Transactional) 내부에서 레디스를 함께 업데이트하는 경우, RDB에서 장애가 발생해서 롤백이됬는데 Redis 만 데이터가 업데이트 되는 경우도 발생할수도 있을것같은데. 이런 경우를 어떻게 처리하는지, 2PC를 적용하는지 아니면 다른 방법이 있는지도 궁금합니다.

javamysqlspring-bootkafkaredis

Answer 2

0

kuke님의 프로필 이미지
kuke
Instructor

쵸잉님, 안녕하세요!

 

 

1.

강의에서는 비관적 락과 낙관적 락을 다루셨는데, 일반적으로 대규모 서비스가 아닌이상 좋아요 자체가 순식간에 많은 트래픽이 몰릴것같지않아 낙관락으로 처리하는 것이 더 효율적일것같다고 생각이듭니다.

말씀하신대로 트래픽이 엄청 몰리지 않는다면 낙관적 락으로도 충분할 수 있습니다. 다만, 낙관적 락 특성 상 정상 사용자도 동시 요청 시에 실패 응답을 받을 수 있으므로, 사용성과 시스템 신뢰에 문제가 생길 수 있습니다. 이를 위해 간단하게 재처리 1~2회 정도만 넣어줘도 실패할 확률은 대폭 줄일 수 있게 되네요. 근데 또 다시 생각해보면, 어차피 트래픽이 적다면 비관적 락으로도 충분할 수 있는 것이고요. 굳이 낙관적 락으로 사용자에게 실패 상황을 만들어줄 필요는 없을 것 같습니다!

그래도 극단적인 상황을 대비해서, 뒤에서 나오는 조회수 처리처럼 레디스로 좋아요 수를 증가시키고 스케줄링같은걸로 RDB에 백업하는 방식은 어떤가요?

조회수처럼 레디스/RDB 백업 전략을 취할 수도 있겠지만, 조회수에서 제시한 전략은 유실에 대해 열려 있었습니다. 그리고 좋아요를 위한 RDB와 좋아요 수를 위한 Redis는 트랜잭션 통합을 지원하지 않습니다.

또, 레디스와 스케줄링 시스템을 위해서 시스템 및 구현 복잡도는 더욱 올라갈 수 있는 것이고요. RDB만으로 충분하다면, 인프라 복잡도를 올리는 것보다 현재 가용한 자원을 활용하는 것이 좋다고 생각됩니다!

 

2.

동시성처리에서 비관적 락으로만 처리해야 하는 상황이 있을까요? 레디스의 분산 락을 사용하는 것이 성능 측면에서 비관락보다 유리할 때도 있을 것 같은데, 실제로 비관락을 반드시 써야 하는 예시나 사례가 궁금합니다.

락을 위해 레디스 등을 활용할 수도 있고 RDB에서 락에 대한 부하를 감소시킬 수 있다는 장점은 있겠지만, 인프라 복잡도와 서버 및 운영 비용 증가에 대한 부분도 고려해야할 것 같습니다.

레디스도 결국에 네트워크 통신을 거쳐서 락을 획득해야 합니다. 이러한 경우에 RDB로 처리하는게 오히려 더 빠른 선택지가 될 수 있습니다.

또, 레디스에 장애가 발생 시에 락이 유실될 수 있는 것이고요. 이 경우에 데이터에 대한 정합성을 반드시 보장할 수 없을 수 있고, 레디스 복구까지 작업 처리에 지연이 생길 수 있습니다. 이러한 경우 RDB로만 처리하는 것이 유리할 것으로 생각되네요!

예를 들어, 레디스 락 획득 -> 결제 -> 레디스 장애로 락 유실(장애 시에 복구까지 아예 지연시킬 수 있으나, 레플리카가 마스터로 승격되어서 장애는 복구되었지만 비동기 복제 지연으로 인해 유실되는 상황을 가정할 수도 있겠음) -> 중복된 요청이 다시 레디스 락 획득 -> 결제.. 이러한 시나리오를 생각해볼 수 있을 것 같습니다.

 

3.

RDB와 레디스는 트랜잭션이 통합되지 않기 때문에(다른 시스템이고, 레디스는 준비 과정 없고 트랜잭션 지원 안하기 때문에 2PC 지원 안함) @Transactional로 묶을 필요도 없고 묶지 않는 것이 좋습니다. 레디스에서 응답 지연이 생긴다면, 트랜잭션을 계속 점유하며 레디스 응답을 기다리게 되고, 여러 비슷한 요청이 중첩된다면 커넥션 풀도 고갈나고, 결국 DB 또는 애플리케이션까지 장애가 전파될 수 있는 위험이 있습니다.

이러한 문제를 방지하기 위해서 레디스 요청은 트랜잭션 범위 바깥으로 꺼내는 것이 일반적이고요.

유실에 대해 별다른 위험성이 없는 경우를 가정한다면, 꼭 트랜잭션을 통합으로 관리할 필요는 없습니다.

대부분의 상황에는 유실이 발생하지 않고, 드물게 발생하는 문제 시에 로그나 원본 데이터 기반으로 복구하면 충분할 수 있습니다.

정합성을 반드시 맞춰야 한다면, 강의에서 제시한 Outbox 패턴 등을 활용해서 이벤트를 발행하고 레디스에 동기화해줄 수 있습니다. 다만, 이 경우는 비동기에 대한 고려가 필요하기 때문에 시스템 정책에 대한 검토가 필요할 수는 있습니다!

0

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

질문해주신 내용은 데이터베이스의 동시성 문제 해결 방안과 Redis를 활용한 최적화 방법에 대한 것입니다. 특히 대규모 시스템에서의 좋아요 처리 방법과 관련된 다양한 처리 방안을 탐색하고자 하신 것 같네요. 각 질문에 대해 아래와 같이 정리해 드립니다.

1. 낙관적 락 및 Redis 활용 방안

  • 일반적으로 낙관적 락은 충돌 발생 가능성이 낮은 경우 유리하며, 성능 측면에서 효율적입니다. Redis를 활용하여 일시적으로 좋아요 수를 저장하고 스케줄링 또는 배치 프로세스를 통해 RDB에 백업하는 방식은 확장성과 성능을 개선할 수 있습니다.
  • 이 접근법은 주기적으로 데이터를 동기화하여 일관성을 유지할 수 있게 하며, 특정 시점에 데이터 동기 문자체가 지연될 수 있다는 점을 염두에 두어야 합니다.

2. 비관적 락 사용해야 하는 경우와 Redis의 분산 락

  • 비관적 락은 트랜잭션이 데이터의 충돌을 피하고 싶을 때 사용됩니다. 예를 들어, 금융 거래재고 관리와 같은 안전이 중요한 시스템에서는 비관적 락이 적합할 수 있습니다.
  • 분산 시스템에서는 Redis의 분산 락이 위와 같은 락을 피할 수 있도록 도움을 줄 때도 있습니다. 분산 락을 통해 여러 서버에 걸쳐 락을 관리할 수 있으며, 이는 특정한 성능 상 이점을 줄 수 있습니다.

3. Redis와 RDB의 트랜잭션 처리

  • Redis와 RDB가 같은 트랜잭션에 속하는 경우, 2PC (Two-Phase Commit Protocol) 를 적용할 수 있으나 이는 복잡성과 성능 이슈가 있을 수 있습니다.
  • 대신, 보상 트랜잭션을 도입하여 실패 시 롤백을 수동으로 설계하거나 가능한 데이터 불일치를 허용하고 비동기적으로 동기화 처리를 확인하여 처리할 수도 있습니다.

더 많은 정보를 원하시면 아래 링크를 참고하시길 바랍니다:

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

choing's profile image
choing

asked

Ask a question