스냅샷은 앞장 이벤트소싱에서도 부분적으로 사용이되었습니다. 스냅샷은 다양한곳에서 사용될수 있으며 그 컨셉은 간단합니다.
무수히 발생하는 이벤트로 인해 우리가 설계한 어떠한 객체의 상태는 지속적으로 변경된다는 점이며
복원관점에서 연속된 이벤트를 재생을 하여 상태를 복원하기위해 모든 이벤트자체를 모두 기록하는것과
모든 이벤트를 기록할필요없이 특정시점의 상태를 복원하기위해, 주기적으로 상태를 원하는 만큼 찍는 기능이 스냅샷입니다.
주로 게임 리플리와같이 게임시작부터 종료까지 게임플레이를 재생하려면 모든 이벤트를 기록해야 하는 반면
장바구니기능의 경우는 넣고빼고한 모든것을 기록할 필요없이 마지막 정보만 특정시점 저장을 하여 서비스에 활용될수 있습니다.
예를들어 한달전 라면+계란 장바구니를 이용한 사용자에게 금일 라면만 장바구니에 담는다고 하면 계란구매하는것을 잊은 사용자에게 그것을 추천하는 기능입니다.
모두를 기록해야하나? 특정시점을 기록해야하냐? 저장소(DB)를 포함하여 IT전반적으로 고민을하는 주제이며
주로 저장소의 한계와 성능의문제 때문에 적절하게 상호운영이 된다란 점이며
아래의 검색 키워드를 통해서 그 차이를 파악할수가 있습니다. 보통 Redo와 Snapshot의 차이이며
여기서 오라클을 붙인다던지, 작업을 돌리는 redo task 를 붙인다던지 다양한 주제에 접근할수 있습니다.
연관 키워드 : difference between redo and snapshot
스냅샷 구현
final case class SnapshotMetadata(persistenceId: String, sequenceNr: Long, timestamp: Long = 0L) private Object state; private int snapShotInterval = 1000; // 스냅샷을 지원하는 메시지 정의 @Override public Receive createReceive() { return receiveBuilder(). match(SaveSnapshotSuccess.class, ss -> { SnapshotMetadata metadata = ss.metadata(); // ... }). match(SaveSnapshotFailure.class, sf -> { SnapshotMetadata metadata = sf.metadata(); // ... }). match(String.class, cmd -> { persist( "evt-" + cmd, e -> { updateState(e); if (lastSequenceNr() % snapShotInterval == 0 && lastSequenceNr() != 0) saveSnapshot(state); }); }).build(); }
스냅샷 저장에 필요한 메타정의(SnapshotMetadata) 후 자신이 원하는 타이밍에
카메라 셔터(saveSnapshot) 를 누르기만 하면됩니다.
스냅샷 복원
private Object state; @Override public Receive createReceiveRecover() { return receiveBuilder(). match(SnapshotOffer.class, s -> { state = s.snapshot(); // ... }). match(String.class, s -> {/* ...*/}).build(); } 또는 @Override public Recovery recovery() { return Recovery.create( SnapshotSelectionCriteria .create(457L, System.currentTimeMillis())); }
마지막 상태를 복원(SnapshotOffer)할수도 있고,
각 시간대별 스냅샷은 고유 아이디가 존재함으로
특정 스냅샷(SnapshotSelectionCriteria)을 복원할수도 있습니다.
스냅샷 시도에따른 반응 메시지
Method | Success | Failure message |
---|---|---|
saveSnapshot(Any) | SaveSnapshotSuccess | SaveSnapshotFailure |
deleteSnapshot(Long) | DeleteSnapshotSuccess | DeleteSnapshotFailure |
deleteSnapshots(SnapshotSelectionCriteria) | DeleteSnapshotsSuccess | DeleteSnapshotsFailure |
스냅샷은 다양한 이유로(디스크풀및 메모리풀등) 실패가 있을수 있으며
그에 대응하는 코드작성도 가능합니다.
다양한 활용 샘플 검색: