ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RocksDB WAL (Write-Ahead Log) 알아보기
    Database/RocksDB 2024. 1. 10. 16:56
    728x90
    반응형

    - 목차

     

    들어가며.

    RocksDB 는 스토리지 엔진으로써 LSM-Tree 를 사용합니다.

    LSM-tree 는 구조적으로 Write-Ahead log 를 취하게 되는데, Write-Ahead Log (WAL log) 에 의해서 Recovery 가 가능해집니다.

    먼저 Write-Ahead Log (WAL log) 에 대해서 간단하게 알아보도록 하겠습니다.

     

    클라이언트는 RocksDB API 를 통해서 데이터를 삽입합니다.

    ( 참고로 RocksDB 에서 취급하는 데이터의 형태는 Key-Value Pair 모양을 따릅니다. )

    클라이언트의 데이터 생성 요청을 WAL log 에 로그 형태로 삽입됩니다.

    그리고 MemTable 과 SSTable 로 생성 요청이 전달되죠.

    아래의 이미지처럼 Write Log 가 먼저 Write-Ahead Log 에 저장이 된 이후에

    MemTable 과 SSTable 로의 저장 작업이 수행됩니다.

     

    이 과정에서 주목할 점은 MemTable 과 SSTable 의 관계인데요.

    SSTable 은 데이터의 영구적인 저장을 책임지는 디스크 영역이고,

    MemTable 은 퍼포먼스를 위한 메모리 영역이 위치합니다.

    그리고 Client 의 데이터 생성 요청이 SSTable 로의 Flush 는 즉각적으로 발생하지 않고, 딜레이가 발생합니다.

    만약 SSTable 로의 Flush 가 이루어지기 이전에 RocksDB 가 종료된다면,

    메모리 영역인 MemTable 에 저장되어있던 데이터들은 모조리 휘발되는 상황에 처합니다.

    그리고 Data Loss 가 발생하죠.

    Write-Ahead Log 는 이러한 상황에서 Data Recovery 를 위해서 사용됩니다.

    Write-Ahead Log 는 모든 Transaction Log 를 저장하고 있기 때문이죠.

     

     

    WAL Log 확인해보기.

    아래 java 코드를 실행하여 WAL Log 의 생성을 확인해보려고 합니다.

     

    rocksdbjni ( Java RocksDB Module ).

    제가 사용한 rocksdbjni 모듈은 아래와 같습니다.

    dependencies {
        // https://mvnrepository.com/artifact/org.rocksdb/rocksdbjni
        implementation group: 'org.rocksdb', name: 'rocksdbjni', version: '7.0.3'
    
    }

     

    RocksDB Java Module 은 아래 링크에서 자세한 사용법을 확인하실 수 있으십니다.

    https://github.com/facebook/rocksdb/wiki/RocksJava-Basics

     

    RocksJava Basics

    A library that provides an embeddable, persistent key-value store for fast storage. - facebook/rocksdb

    github.com

     

    Write-Ahead Log 생성해보기.

    아래 코드를 간략히 설명해보도록 하겠습니다.

    저는 write_buffer_bytes 를 1GB 로 설정하였습니다.

    options.setWritableFileMaxBufferSize(1024 * 1024 * 1024);

     

    write_buffer_bytes 는 1GB 로 설정한 이유는 MemTable 에서 SSTable 로 Flush 되지 않게 하기 위함인데요.

    1천만개의 Key-Value Pair 들을 MemTable 에만 추가한 이후에 프로그램을 종료시킵니다.

    그럼 메모리 상의 데이터를 휘발시키고, SSTable 이 생성되지 않습니다.

    오직 WAL Log 만이 생성되죠.

     

    package com.westlife;
    
    import org.rocksdb.*;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class RocksdbTest {
      public static void main(String[] args) throws RocksDBException {
    
        String dbPath = "src/main/resources/rocksdb";
    
        RocksDB.loadLibrary();
        final DBOptions options = new DBOptions();
        options.setCreateIfMissing(true);
        options.setInfoLogLevel(InfoLogLevel.NUM_INFO_LOG_LEVELS);
        options.setWritableFileMaxBufferSize(1024 * 1024 * 1024);
        ColumnFamilyOptions cfOpts = new ColumnFamilyOptions().optimizeUniversalStyleCompaction();
        List<ColumnFamilyDescriptor> cfDescriptors = Arrays.asList(new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY, cfOpts));
        List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
        RocksDB rocksDb = RocksDB.open(options, new File(dbPath).getAbsolutePath(), cfDescriptors, cfHandles);
        for (long i = 0; i < 1000001; i++) {
          rocksDb.put(rocksDb.getDefaultColumnFamily(), ("key" + i).getBytes(), ("" + i).getBytes());
        }
    
        rocksDb.close();
      }
    }

     

    위 코드의 실행의 결과로 아래와 같은 RocksDB 관련 파일들이 생성됩니다.

    .log 확장자를 가지는 파일이 Write-Ahead Log 파일입니다.

    그리고 Flush 가 되지 않아 SSTable 을 뜻하는 .sst 파일은 생성되지 않습니다.

     

     

    WAL Log Recovery 확인하기.

    SSTable 이 없는 상황에서 아래 프로그램을 다시 시작합니다.

    아래 프로그램은 다음과 같이 동작할 것입니다.

     

    1. 000005.log ( WAL Log ) 파일을 읽어들여 SSTable 을 생성

    2. SSTable 을 통해서 Memory 상의 Block Cache 를 구성

    3. 그 이후에 Read, Write 요청을 처리함.

     

     

    package com.westlife;
    
    import org.rocksdb.*;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class RocksdbTest {
      public static void main(String[] args) throws RocksDBException {
    
        String dbPath = "src/main/resources/rocksdb";
    
        RocksDB.loadLibrary();
        final DBOptions options = new DBOptions();
        options.setCreateIfMissing(true);
        options.setInfoLogLevel(InfoLogLevel.NUM_INFO_LOG_LEVELS);
        options.setWritableFileMaxBufferSize(1024 * 1024 * 1024);
        ColumnFamilyOptions cfOpts = new ColumnFamilyOptions().optimizeUniversalStyleCompaction();
        List<ColumnFamilyDescriptor> cfDescriptors = Arrays.asList(new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY, cfOpts));
        List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
        RocksDB rocksDb = RocksDB.open(options, new File(dbPath).getAbsolutePath(), cfDescriptors, cfHandles);
        byte[] result = rocksDb.get(rocksDb.getDefaultColumnFamily(), ("key1000000").getBytes());
        System.out.println("value : " + new String(result));
        rocksDb.close();
      }
    }
    value : 1000000

     

    위 프로그램을 실행시키면 원하는 출력이 나타납니다.

    그리고 RocksDB 의 파일 구조를 확인해보면 다음과 같이 .sst 파일이 확인됩니다.

    이는 기존의 WAL Log 로부터 생성된 SSTable 입니다.

     

     

    반응형

    'Database > RocksDB' 카테고리의 다른 글

    RocksDB Leveled Compaction 알아보기  (0) 2024.01.10
    RocksDB Column Family 알아보기  (0) 2024.01.10
    RocksDB Architecture 알아보기 (LSM-tree)  (0) 2024.01.10
Designed by Tistory.