Key-value Stores
heed
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:
- Caching: App data, web pages or images.
- Embedded databases for mobile apps, IoT devices, desktop applications.
- Indexing: Local search index or metadata storage.
- Game state persistence, configuration storage.
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
⮳ 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(())
}