인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

chlghksdyd31님의 프로필 이미지

작성한 질문수

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

Transactional Outbox 모듈 구현

레디스의 동적 서버 리스트와 샤딩 범위 중복 문제 질문

해결된 질문

작성

·

100

0

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

분산 시스템에서 균등 샤딩 부분을 듣다가 궁금한 점이 생겨서 질문드립니다.

각 서버는 자신의 @Scheduled에 의해 레디스 서버로 조회하여 자신의 인덱스를 찾은 후 이를 기반으로 각자 서버 로컬에서 샤딩 범위를 계산하는 것으로 이해했는데요.

여기서 궁금한 점은 각 서버마다 @Scheduled가 동작하는 시점도 다를테고, 레디스의 저장된 서버 리스트가 동적으로 변하기도 하는데, 이러한 이유로 서로 다른 서버가 부분적으로 겹치는 샤딩 범위를 각자 계산하여 카프카로 중복 전송하는 시나리오가 발생하지는 않는 것인가요?

ex)

A의 @Scheduled 동작 시점에서는 서버가 3개 뿐이었지만 B의 @Scheduled 동작 시점에는 서버가 5개로 늘어난 경우

서버 A가 계산한 자신의 샤딩 범위 0~20

서버 B가 계산한 자신의 샤딩 범위 13 ~ 27

 

답변 주시면 감사하겠습니다.😊

답변 2

1

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

chlghksdyd31님, 안녕하세요!

 

동시성 문제에 깊게 고민해보고 계시군요! 아주 좋은 질문입니다!

 

각 서버마다 @Scheduled가 동작하는 시점도 다를테고, 레디스의 저장된 서버 리스트가 동적으로 변하기도 하는데,

맞습니다!

 

겹치는 샤딩 범위를 각자 계산하여

맞습니다!

Coordinator를 통해서 각 서버 애플리케이션은 자신의 ID를 레디스에 전송합니다.

레디스는 실행 중인 애플리케이션 목록을 저장하고 있습니다.

그리고 각 애플리케이션은 실행 중인 애플리케이션 목록을 통해서 자신의 인덱스 번호를 할당 받습니다.

각 애플리케이션은 로컬에서 전체 애플리케이션 수/전체 샤드 수/자신의 인덱스 번호를 통해서,

자신이 처리할 수 있는 샤드를 계산 및 중복 없이 할당받는 셈입니다.

 

카프카로 중복 전송하는 시나리오가 발생하지는 않는 것인가요?

대부분의 경우에는 중복 전송되지 않는 것입니다.

하지만 엄격하게 말하면 중복 전송은 발생할 수 있습니다.

카프카 전송 이후에 db 장애로 인해 outbox delete가 안되는 상황일 수도 있고(outbox는 남아있으니 발송 안되었다고 보고 재처리),

스케일 아웃 시점에 일시적으로 A 애플리케이션에 할당된 샤드가 B 애플리케이션에도 할당되어 있는 상황일 수도 있습니다.

이게 말씀하신 “서버가 늘어난 경우”에 대한 상황이 되겠네요. 이러한 상황에 대해서는 시간이 지난 후에 샤드를 다시 할당받고 나서야 균등하게 맞춰집니다.

위 전략은 평시에 중복 전송을 최대한 막기 위한 것이고, 중복을 엄격하게 막으려면 부가적인 전략이 필요할 수 있습니다.(전송한 eventId를 일시적으로 기억하고 필터링 한다든지 등)

그런데 이러한 비용을 프로듀서에서 감당하기에는 비용이 클 수 있습니다.

컨슈머 측에서 직접 막을 수도 있고, 멱등하게 개발할 수도 있고, 이벤트 중복이 문제되지 않는 상황일 수도 있거든요!

그래서 강의에서도 프로듀서의 이벤트 발행 중복에 초점을 맞추기 보단 유실 방지에 초점을 맞춘 구성(transactional outbox)이고,

컨슈머는 멱등하게 처리되어 있는 구성입니다! (생성 이벤트 두개 들어온다고 해서 컨슈머에서 레디스에 데이터 두 개 생성하지 않음. 그냥 기존 key에 업데이트)

샤드를 균등하게 할당하는 부분은, 재처리에 대한 확장성/처리량을 유연하게 늘리기 위한 구성이라고 봐주시면 됩니다!

 

그리고 추가로 첨언하자면,

강의에서는 단순화를 위해 API 용도로 사용하는 서버 애플리케이션에 재처리 스케줄러를 포함해두었는데요,

실제로는 재처리 애플리케이션은 별도 애플리케이션으로 분리하여 구성하는게 좋습니다.

그래야 필요한 만큼만 리소스를 할당하고, 문제 시에 재처리 서버만 유연하게 확장하여 재처리 처리량을 늘릴 수 있거든요.

이 부분은 대략적인 컨셉만 이해하고 있다면, 애플리케이션 분리하여 구성하는 것도 큰 어려움 없이 진행해볼 수 있을겁니다!

 

혹시 더 궁금한 점 있으시면 편히 문의 주세요!

chlghksdyd31님의 프로필 이미지
chlghksdyd31
질문자

인기글 서비스의 consume 코드를 다시 살펴보니, 말씀하신대로 createOrUpdate 방식으로 멱등하게 연산하도록 구현되어 있어 중복 전송이 발생하더라도 데이터의 일관성이 깨질 가능성은 낮을 것 같습니다. 다만, 중복 전송 시나리오가 발생할지 궁금했는데, 답변을 듣고 궁금증이 해결됐습니다. 정성스러운 답변 주셔서 감사합니다! 😊😊

1

인프런 AI 인턴님의 프로필 이미지

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

분산 시스템에서 샤딩의 동적인 특성으로 인해 발생할 수 있는 중복 전송 문제에 대해 좋은 질문 주셨습니다. 샤딩 시스템에서 각 서버가 자체적으로 샤딩 범위를 계산하고, 레디스의 서버 리스트가 동적으로 변화함에 따라 일부 샤딩 범위가 중복될 수 있다는 우려가 생길 수 있습니다.

이런 상황을 막기 위해서는 다음과 같은 방법을 사용할 수 있습니다:

  1. 중앙 집권적인 샤딩 매니저를 사용하는 방법입니다. 중앙에서 샤딩 범위를 계산하고 관리하며, 각 서버는 이 정보를 참조하여 중복되지 않도록 할 수 있습니다. 이 방식은 모든 서버들이 동일한 상태정보를 가지도록 보장해 줄 수 있습니다.

  2. 콘시스턴트 해싱(Consistent Hashing)을 사용하는 것도 방법입니다. 콘시스턴트 해싱은 노드 추가/제거가 일어날 때 최소 재배치를 보장하며, 특정 키의 변경 횟수를 줄여줍니다. 이를 통해 노드가 추가되거나 제거될 때 발생할 수 있는 문제를 최소화할 수 있습니다.

  3. 분산 락 시스템을 도입하여 샤딩 범위 계산 작업을 조율할 수 있습니다. 각 서버가 샤딩을 계산하기 전에 락을 획득해 작업을 조율하여 중복을 방지할 수 있습니다.

레디스와 같은 KV-스토어에서 결과의 일관성을 중요시할 경우 추가적인 동기화 메커니즘을 통해 중복 처리를 미연에 방지하는 것이 추천됩니다.

더 많은 정보가 필요한 경우, 레디스 샤딩 메커니즘 설명 (게시글 제목)에서 관련 내용을 자세히 다루고 있습니다. 참고해 보시기 바랍니다.

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