저장소 (StableDB)
Stable v1.4.0은 LevelDB 기반 상태 저장소를 MemIAVL로 대체합니다. MemIAVL은 하나의 상태 스냅샷을 메모리 매핑 파일에 유지하고 각 새 블록의 변경 사항을 순차적 쓰기 우선 로그에 기록합니다.
디스크 I/O가 병목 현상인 이유
모든 블록은 애플리케이션 상태를 변경합니다. 노드는 두 가지 관련 작업을 완료해야 합니다.
- 상태 커밋: 새 상태의 루트 해시를 계산하고 커밋합니다.
- 상태 지속성: 변경된 데이터를 저장소에 기록하여 나중에 노드가 복구할 수 있도록 합니다.
이전 LevelDB 기반 저장소는 이러한 작업을 결합했습니다. 또한 나중에 읽기를 효율적으로 만들기 위해 저장된 레코드를 재구성하는 백그라운드 압축 중에 데이터를 다시 썼습니다.
하나의 논리적 상태 업데이트가 10-50배 많은 물리적 디스크 쓰기를 유발할 수 있습니다. 이를 **쓰기 증폭(write amplification)**이라고 합니다. 그런 다음 실행은 무작위 쓰기 및 압축이 지배하는 저장소 경로를 기다려야 했습니다.
MemIAVL이 저장소를 변경하는 방법
메모리 매핑 파일 또는 mmap를 사용하면 운영 체제가 메모리 주소를 통해 파일 내용을 노출할 수 있습니다. 노드는 포인터를 따라 상태를 읽을 수 있으며, 운영 체제는 필요한 페이지를 페이지 캐시에 로드합니다.
MemIAVL은 두 가지 구조를 결합합니다.
- 스냅샷: 지속된 상태 트리의 단일 메모리 매핑 표현.
- 쓰기 우선 로그 (WAL): 해당 스냅샷 이후에 발생한 원시 변경 사항에 대한 추가 전용 기록.
쓰기 경로
각 블록은 변경 세트를 WAL에 순서대로 추가합니다. MemIAVL은 업데이트를 LevelDB를 통해 라우팅하거나 압축을 트리거하지 않습니다. 따라서 쓰기 증폭은 10-50배에서 약 1회 쓰기로 감소합니다.
MemIAVL은 또한 트리 노드를 두 가지 범주로 나눕니다.
PersistedNode는 스냅샷에 이미 저장된 변경되지 않은 서브트리를 나타냅니다.MemNode는 현재 업데이트에 의해 메모리에서 변경된 서브트리를 나타냅니다.
MemIAVL이 다음 루트 해시를 계산할 때, 변경되지 않은 PersistedNode 서브트리에서 멈춥니다. 새 MemNode 데이터를 포함하는 경로만 해시합니다.
읽기 경로
현재 상태 읽기는 메모리 매핑된 스냅샷의 포인터를 따릅니다. 자주 액세스되는 페이지는 운영 체제의 페이지 캐시에 남아 있으므로 노드는 각 트리 노드에 대해 별도의 데이터베이스 조회를 피합니다.
기록 상태 및 VersionDB
MemIAVL은 현재 상태와 노드가 유지하는 스냅샷을 제공합니다. 보조 VersionDB는 RocksDB 사이드카에 기록 버전을 저장합니다.
노드가 가장 이른 MemIAVL 스냅샷보다 오래된 기록 상태 쿼리에 응답해야 하는 경우 VersionDB가 필요합니다. 이는 아카이브 노드 및 장거리 쿼리를 노출하는 RPC 서비스에 특히 중요합니다.
마이그레이션 고려 사항
기존 노드는 v1.4.0을 채택할 때 LevelDB 상태를 마이그레이션해야 합니다. 권장 경로는 로컬 스냅샷 내보내기 및 복원입니다.
벤치마크는 표준 복원에 대해 검증자당 평균 19.4초의 다운타임을 측정했습니다. 병렬 복원 변형은 평균을 약 2.6초로 줄였습니다.
검증자는 라운드 로빈 순서로 하나씩 마이그레이션할 수 있습니다. 투표권의 최소 3분의 2를 온라인 상태로 유지하면 네트워크는 마이그레이션 중에 블록을 계속 생성할 수 있습니다.
추가 읽을거리
더 자세한 기술적 심층 분석 및 구현 세부 정보는 다음을 참조하세요.
다음으로 이동할 곳
- 고성능 RPC: RPC 계층이 쓰기와 경쟁하지 않고 상태 읽기를 노출하는 방법을 확인하세요.
- 실행: 실행이 여기에 설명된 저장소 계층에 어떻게 쓰는지 이해합니다.
- 노드 업그레이드: 조정된 업그레이드 후에 백업을 준비하고 노드를 확인합니다.
- 네트워크 업그레이드: 전체 v1.4.0 범위 및 출시 상태를 검토합니다.

