26. 읽기 복제본 분산과 세션 일관성(비단조 읽기) (C#)
난이도 상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ============================================================================
// [코드리뷰 문제] C# — 읽기 복제본 분산과 반복 조회의 일관성
// ----------------------------------------------------------------------------
// 시나리오:
// 프로필/랭킹 점수 읽기 부하를 분산하려고 여러 읽기 복제본(read replica)에 라운드
// 로빈으로 질의한다. 복제본들은 주(primary)로부터 비동기 복제되며 각자 복제 지연이
// 다르다(어떤 복제본은 최신, 어떤 복제본은 몇백 ms 뒤처짐). 클라이언트는 같은 값을
// 짧은 간격으로 반복 조회한다(예: 점수 획득 직후 내 점수를 다시 확인).
//
// 요구사항:
// - 한 클라이언트(세션)가 이미 관측한 값보다 "더 과거"의 값을 다시 보지 않아야 한다.
// 특히 자기 갱신 직후의 조회에서 그 갱신이 사라져 보이면 안 된다.
//
// 과제: (A) (B) 지점의 동작을 설명하고 수정안을 제시하라.
// ============================================================================
using System.Collections.Generic;
public interface IReplica
{
// (score, 복제된 버전) 반환. 버전은 단조 증가.
(long score, long version) Read(long playerId);
}
public sealed class ScoreReadRouter
{
private readonly List<IReplica> _replicas;
private int _next; // 라운드로빈 커서
public ScoreReadRouter(List<IReplica> replicas) { _replicas = replicas; }
public long GetScore(long sessionId, long playerId)
{
var replica = _replicas[_next]; // (A)
_next = (_next + 1) % _replicas.Count;
var (score, version) = replica.Read(playerId); // (B)
return score;
}
} 결함 코드 · C++
// ============================================================================
// [코드리뷰 문제] C++ — 읽기 복제본 분산과 반복 조회의 일관성
// ----------------------------------------------------------------------------
// 시나리오:
// 프로필/랭킹 점수 읽기 부하를 여러 읽기 복제본에 라운드로빈으로 분산한다. 복제본은
// 주(primary)로부터 비동기 복제되며 각자 복제 지연이 다르다(최신/뒤처짐 혼재).
// 클라이언트는 같은 값을 짧은 간격으로 반복 조회한다(점수 획득 직후 재확인 등).
//
// 요구사항:
// - 한 세션이 이미 관측한 값보다 "더 과거"의 값을 다시 보지 않아야 한다.
// 자기 갱신 직후의 조회에서 그 갱신이 사라져 보이면 안 된다.
//
// 과제: (A) (B) 지점의 동작을 설명하고 수정안을 제시하라.
//
// 빌드: g++ -std=c++17 problem.cpp
// ============================================================================
#include <cstdint>
#include <vector>
struct ReadResult { int64_t score; int64_t version; }; // version 은 단조 증가
struct IReplica {
virtual ~IReplica() = default;
virtual ReadResult read(int64_t playerId) = 0;
};
class ScoreReadRouter {
public:
explicit ScoreReadRouter(std::vector<IReplica*> replicas)
: replicas_(std::move(replicas)) {}
int64_t getScore(int64_t sessionId, int64_t playerId) {
IReplica* replica = replicas_[next_]; // (A)
next_ = (next_ + 1) % static_cast<int>(replicas_.size());
ReadResult r = replica->read(playerId); // (B)
(void)sessionId;
return r.score;
}
private:
std::vector<IReplica*> replicas_;
int next_ = 0; // 라운드로빈 커서
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.