Rocks DB 스토리지 구현 4)

Tasker_Jang·2024년 9월 21일
0

RaftError(Store(SnapshotTemporarilyUnavailable) 에러


1. 문제 상황

Raft 기반 분산 시스템을 개발하던 중, memstore-static-members 실행 시 Raft 노드를 부팅하는 과정에서 다음과 같은 오류 메시지가 발생했습니다.

Error: RaftError(Store(SnapshotTemporarilyUnavailable))

로그에 기록된 정보는 다음과 같습니다:

INFO RaftNode bootstrapped. Config { raft_config: ... , snapshot_interval: None, ... }
Error: RaftError(Store(SnapshotTemporarilyUnavailable))

이 오류는 스냅샷과 관련된 문제로 보였으며 이를 해결하기 위한 디버깅 과정을 아래에 정리했습니다.

2. 원인 분석

이번 오류는 Raft에서 스냅샷을 다루는 과정에서 발생한 문제입니다. snapshot() 함수가 스냅샷을 가져오지 못하는 경우, 에러를 던지면서 프로그램이 중단 되었습니다. 특히 초기화된 노드에서 스냅샷이 없을 때 이 문제가 발생했습니다.

2.1 문제 발생 원인

코드에서 스냅샷이 존재하지 않으면 SnapshotTemporarilyUnavailable라는 에러를 던지도록 설계되어 있었는데, 이를 처리하지 않으면 프로그램이 종료됩니다.

초기 코드에서는 스냅샷이 없을 때 바로 에러를 던지며, 아래와 같이 Err를 반환하는 방식이었습니다:

fn snapshot(&self, request_index: u64, to: u64) -> crate::raft::Result<Snapshot> {
    if let Some(value) = self.db.get("snapshot").unwrap() {
        let snapshot = Snapshot::decode(&*value).unwrap();
        Ok(snapshot)
    } else {
        Err(crate::raft::Error::Store(
            crate::raft::StorageError::SnapshotTemporarilyUnavailable,
        ))
    }
}

위 코드에서는 스냅샷이 존재하지 않으면 바로 SnapshotTemporarilyUnavailable 에러를 던집니다. 하지만 시스템 부트스트랩 시점이나 초기화 시점에서 스냅샷이 없을 수 있기 때문에 이 방식은 문제가 됩니다.

2.2 해결 방법

해결 방법은 스냅샷이 존재하지 않으면 기본값인 Snapshot::default()를 반환하는 방식으로 수정하는 것이었습니다. 기본 스냅샷을 반환하면 프로그램이 정상적으로 진행되며, 이후 스냅샷이 생성되면 문제 없이 작동하게 됩니다.

fn snapshot(&self, request_index: u64, to: u64) -> crate::raft::Result<Snapshot> {
    match self.db.get("snapshot") {
        Ok(Some(value)) => {
            let snapshot = Snapshot::decode(&*value)?;
            Ok(snapshot)
        },
        Ok(None) => {
            println!("Warning: Snapshot not available. Handling accordingly.");
            Ok(Snapshot::default())  // 스냅샷이 없으면 기본값 반환
        },
        Err(e) => {
            println!("Error fetching snapshot: {:?}", e);
            Err(crate::raft::Error::Store(
                crate::raft::StorageError::SnapshotTemporarilyUnavailable,
            ))
        }
    }
}

이 코드에서는:

  • 스냅샷을 가져오지 못했을 때 에러를 던지지 않고, 대신 Snapshot::default()를 반환하여 프로그램이 크래시되지 않도록 처리하였습니다.
  • 만약 데이터베이스에서 에러가 발생했을 때는 기존처럼 에러 메시지를 출력하고 SnapshotTemporarilyUnavailable 에러를 던집니다.

2.3 해결 결과

이제 노드 부트스트랩 시 스냅샷이 없더라도 프로그램이 정상적으로 작동하며, 이후 스냅샷이 생성되면 문제없이 작동하게 됩니다. 로그에 "Warning: Snapshot not available." 메시지를 출력하여 스냅샷이 없는 상황을 처리하게 됩니다.

profile
터널을 지나고 있을 뿐, 길은 여전히 열려 있다.

0개의 댓글