Key-value Stores

RecipeCratesCategories
heedheedcat-database
rocksdbrocksdbcat-database

heed

heed heed-crates.io heed-github heed-lib.rs cat-data-structures cat-database

heed is a fully-typed LMDB wrapper. LMDB (Lightning Memory-Mapped Database) is a fast and efficient embedded database library that provides key/value storage. Use heed for:

Advantages include speed, minimal memory footprint, embedded use, memory mapping, and ACID (Atomicity, Consistency, Isolation, Durability) properties. It is not ideal for huge datasets, complex queries, or network access.

use heed::Database;
use heed::EnvOpenOptions;
use heed::types::*;

// `heed` (and `heed3`) are high-level wrappers of LMDB.
// Lightning Memory-Mapped Database (LMDB) is an embedded, transactional
// database in the form of a key-value store.

/// This function demonstrates basic usage of the `heed` crate for interacting
/// with an LMDB database. It covers opening a database, creating a write
/// transaction, writing data, committing the transaction, opening a read
/// transaction, and reading data.
fn main() -> anyhow::Result<()> {
    // Open a database:
    let dir = tempfile::tempdir().unwrap();
    let env = unsafe {
        EnvOpenOptions::new()
            .map_size(1024 * 1024 * 10) // 10 MiB
            .max_dbs(10)
            .open(dir.path())?
    };

    // Create a transaction with read and write access for use with the
    // environment.
    let mut wtxn = env.write_txn()?;

    // Open the default unnamed database. We specify the key type as a
    // 32-bit unsigned integer in native endianness and the value type as a
    // string.
    let db: Database<U32<byteorder::NativeEndian>, Str> =
        env.create_database(&mut wtxn, None)?;

    // Write data to the database. We insert a key-value pair where the key is
    // 1 and the value is "Hello, world!".
    db.put(&mut wtxn, &1, "Hello, world!")?;
    // Commit the write transaction to persist the changes.
    wtxn.commit()?;

    // Open a read transaction.
    let rtxn = env.read_txn()?;
    // Read data from the database
    let value = db.get(&rtxn, &1)?.unwrap();
    println!("Value: {}", value);
    assert_eq!(value, "Hello, world!");

    Ok(())
}

rocksdb

rocksdb rocksdb-crates.io rocksdb-github rocksdb-lib.rs cat-database

rocksdb is a Rust wrapper for Facebook's RocksDB embeddable database. RocksDB is a high performance database for key-value data. Use rocksdb:

  • As the storage engine for other databases (MySQL, MongoDB, TiKV...).
  • For caching.
  • To handle time-series data, indexes for search engines, persistent message queues.

RocksDB is employed in stream processing frameworks like Apache Flink and Kafka Streams to maintain the state of streaming applications.

RocksDB is great for performance, scalability, flexibility, embeddability. Avoid when dealing with complex SQL or distributed transactions.

//! Example using Facebook's RocksDB embeddable database.
//!
//! Ensure you have the RocksDB C++ library installed on your system, because
//! the Rust `rocksdb` crate is just a wrapper around the native C++ RocksDB
//! library. If you're on `Ubuntu`, you can install it with:
//! ```sh
//! sudo apt-get install librocksdb-dev
//! ```
//! On `macOS`, you can install it with:
//! ```sh
//! brew install rocksdb
//! ```
//! You will also need Clang and LLVM.

use rocksdb::DB;
use rocksdb::Options;

fn main() -> anyhow::Result<()> {
    // Create a new temporary directory to store the database,
    // which will be deleted when `tempdir` goes out of scope
    let tempdir = tempfile::Builder::new()
        .prefix("rocksdb_storage")
        .tempdir()
        .expect(
            "Failed to create the temporary directory for `rocksdb` storage",
        );
    let path = tempdir.path();
    // In real life, use e.g.: let path = "my_rocksdb_path";
    {
        // Open a RocksDB database.
        // This will create a new database if it doesn't exist.
        let db = DB::open_default(path)?;

        // Insert some key-value pairs:
        db.put(b"key1", b"value1")?;
        db.put(b"key2", b"value2")?;

        // Retrieve a value by its key:
        match db.get(b"key1")? {
            Some(value) => println!(
                "Found key1 with value: {}",
                String::from_utf8_lossy(&value)
            ),
            None => println!("key1 not found"),
        }

        // Delete a key-value pair:
        db.delete(b"key1")?;

        // Try to get the deleted key:
        match db.get(b"key1")? {
            Some(value) => println!(
                "Found key1 with value: {}",
                String::from_utf8_lossy(&value)
            ),
            None => println!("key1 not found after deletion"),
        }
    }
    let _ = DB::destroy(&Options::default(), path);

    Ok(())
}