grocksdb

repository·master·Indexed 18 days ago

https://github.com/linxgnu/grocksdb

A Go wrapper for RocksDB and a patched fork of gorocksdb. It is designed to support a wider range of the RocksDB C API and is optimized for low overhead by avoiding `defer` in the codebase.

Tokens
56.2K
Snippets
201
Records
259
Agent score
64%

What's inside grocksdb

  1. Customize grocksdb build flags

    master

    You can customize how grocksdb links to libraries using Go build tags. This is useful if you want to override the default flags (-lrocksdb -pthread -lstdc++ -ldl -lm -lzstd -llz4 -lz -lsnappy) or use a cleaner set of links.

    Use -tags grocksdb_clean_link to reduce the base flags to -lrocksdb -pthread -lstdc++ -ldl. This allows you to manually specify only the additional libraries you need.

    Ignore library build flags

    Use -tags grocksdb_no_link to ignore the library's internal build flags entirely and build strictly based on the flags you provide in CGO_LDFLAGS.

    # Build with a cleaner set of flags
    CGO_LDFLAGS="-L/path/to/rocksdb -lzstd" go build -tags grocksdb_clean_link
    
    # Build ignoring library flags and using fully custom flags
    CGO_LDFLAGS="-L/path/to/rocksdb -lrocksdb -lstdc++ -lzstd -llz4" go build -tags grocksdb_no_link
  2. Build grocksdb with CGO flags

    master

    To build your Go application with grocksdb, you must provide the correct include and library paths via CGO_CFLAGS and CGO_LDFLAGS.

    If your prerequisites are already in your system's linker paths, you can simply run:

    go build

    Otherwise, use the following patterns depending on your RocksDB installation and compression libraries.

    # Standard build
    CGO_CFLAGS="-I/path/to/rocksdb/include" \
    CGO_LDFLAGS="-L/path/to/rocksdb -lrocksdb -lstdc++ -lm -lz -lsnappy -llz4 -lzstd" \
      go build
    
    # Build with bz2 support
    CGO_LDFLAGS="-L/path/to/rocksdb -lrocksdb -lstdc++ -lm -lz -lsnappy -llz4 -lzstd -lbz2" \
      go build
  3. Control data fetching levels with ReadTier

    master

    The ReadTier type allows you to specify which cache levels a read request should process. If the required data is not found at the specified tier, the operation returns Status::Incomplete.

    Available tiers:

    • ReadAllTier (0): Reads data from memtable, block cache, OS cache, or storage. (Default)
    • BlockCacheTier (1): Reads data from memtable or block cache only.
    • PersistedTier (2): Reads data from memtable or block cache persisted data. Note: If WAL is disabled, this skips memtable data. Currently supports Get and MultiGet only (not iterators).
    • MemtableTier (3): Reads data from memtable only. Used for memtable-only iterators.
    opts := grocksdb.NewDefaultReadOptions()
    opts.SetReadTier(grocksdb.BlockCacheTier)
  4. Understand EncodingType

    master

    The EncodingType defines how keys are written to the database.

    • EncodingTypePlain: Always writes full keys without any special encoding.
    • EncodingTypePrefix: Finds opportunities to write the same prefix once for multiple rows. Instead of the full key, it writes the size of the shared prefix and the remaining bytes.

    Note for EncodingTypePrefix: You must use the same prefix extractor when reopening the file. The name of the prefix extractor is stored in the file and is bitwise compared upon reopening; a mismatch will return an error.

    // Available types:
    // grocksdb.EncodingTypePlain
    // grocksdb.EncodingTypePrefix
  5. Use SliceTransform for prefix transformations

    master

    A SliceTransform is an interface used as a prefix extractor in RocksDB. It allows you to transform keys (e.g., for prefix seeking) and provides methods to validate if a key belongs to a specific domain or range.

    Key methods:

    • Transform(src []byte) []byte: Transforms the source key into a destination key.
    • InDomain(src []byte) bool: Returns true if the source key is valid for this transformation.
    • InRange(src []byte) bool: Returns true if the key is in the range of the transformation's output.
    • Name() string: Returns the identifier of the transformation.
    • Destroy(): Frees the underlying C memory associated with the transform. Note: You must call Destroy() to prevent memory leaks.
    var st grocksdb.SliceTransform
    // ... initialize st ...
    
    // Transform a key
    newKey := st.Transform(originalKey)
    
    // Check validity
    inDomain := st.InDomain(originalKey)
    inRange := st.InRange(newKey)
    
    // Cleanup
    st.Destroy()
  6. How to use GetUpdatesSince for WAL Tailing

    master

    The GetUpdatesSince method allows you to obtain an iterator positioned at a specific sequence number, effectively allowing you to read updates that occurred after a certain point.

    Important Requirements:

    • You must set WAL_ttl_seconds or WAL_size_limit_MB to large values. If the WAL files are cleared aggressively by RocksDB, the iterator may become invalid before you can read the updates.
    • This API is not yet consistent with WritePrepared transactions.

    Method:

    • GetUpdatesSince(seqNumber uint64) (*WalIterator, error): Returns a WalIterator positioned at the first available sequence number after the requested one.
  7. Configure Compaction Strategies and Priorities

    master

    RocksDB provides several ways to tune the compaction process to balance space amplification and performance.

    Level Compaction Tuning

    • Dynamic Level Bytes: When enabled via SetLevelCompactionDynamicLevelBytes(true), RocksDB picks the target size of each level dynamically. This gives max_bytes_for_level_multiplier priority over max_bytes_for_level_base, resulting in a more predictable LSM tree shape and limiting worst-case space amplification. Note: Turning this on/off for an existing DB is not recommended.
    • Compaction Priority: In level-based compaction, use SetCompactionPri(pri) to determine which file from a level is picked to merge into the next level.
    • Compaction Style: Set the overall compaction style using SetCompactionStyle(style).

    Compaction Options

    • Universal Compaction: Configure using SetUniversalCompactionOptions(options). This uses move semantics; do not use the options object after calling this.
    • FIFO Compaction: Configure using SetFIFOCompactionOptions(options). This also uses move semantics.
    • Automatic Compaction: Disable automatic compactions using SetDisableAutoCompactions(true).
    // Example: Setting compaction style and priority
    opts.SetCompactionStyle(LevelCompactionStyle)
    opts.SetCompactionPri(KMinOverlappingRatioCompactionPri)
  8. Use WriteBatchWI for read-your-own-write support

    master

    WriteBatchWI (Write Batch with Index) is a specialized batching type that allows for 'read-your-own-write' semantics. It maintains an index of Put, Merge, and Delete operations, enabling you to query the batch or use iterators to see pending changes before they are committed to the database.

    Key features include:

    • Index Support: Tracks updates to allow querying the batch directly.
    • Iterators: Supports creating iterators that view the batch as a delta over a base iterator.
    • Save Points: Allows rolling back the batch to a specific state using SetSavePoint and RollbackToSavePoint.
    // Example initialization
    wb := grocksdb.NewWriteBatchWI(1024, true)
    defer wb.Destroy()
    
    wb.Put([]byte("key"), []byte("value"))
    
    // Read the value from the batch before committing to DB
    val, err := wb.Get(opts, []byte("key"))
  9. How COWList handles concurrency

    master

    The COWList is designed for scenarios like CGO callback registries where reads are frequent and writes are occasional.

    Concurrency Model:

    • Reads: Non-blocking. Multiple goroutines can call Get simultaneously without contention.
    • Writes: Only one write can occur at a time (enforced by sync.Mutex).
    • Read/Write Interaction: Writes do not block reads, and reads do not block writes. A reader will always see a consistent, immutable snapshot of the list from the moment the read operation began.
  10. Experimental: SingleDelete for optimized workloads

    master
    The SingleDelete and SingleDeleteCF methods are experimental performance optimizations. They require that the key exists and has not been overwritten. Mixing SingleDelete with Delete or Merge operations can result in undefined behavior. It is recommended to set options.sync = true when using this feature.
  11. Manage database backups with BackupEngine

    master

    The BackupEngine is a reusable handle used to create, manage, and restore RocksDB backups. You can initialize it from an existing DB instance or by specifying a path and options manually.

    Core Lifecycle

    1. Initialize: Use CreateBackupEngine(db) to link an engine to an existing database, or OpenBackupEngine(opts, path) for manual configuration.
    2. Perform Operations: Create new backups, purge old ones, or verify existing ones.
    3. Restore: Restore the database state from a specific backup ID or the latest available backup.
    4. Cleanup: Call Close() to release the engine resources. Note that Close() does not delete existing backups on storage; it only cleans up the engine's state.
    // Example: Creating and using a backup engine
    engine, err := grocksdb.CreateBackupEngine(db)
    if err != nil {
        log.Fatal(err)
    }
    defer engine.Close()
    
    // Create a new backup
    err = engine.CreateNewBackup()
    
    // Get info about existing backups
    infos := engine.GetInfo()
    for _, info := range infos {
        fmt.Printf("Backup ID: %d, Size: %d\n", info.ID, info.Size)
    }