#rocksdb #embeddable #facebook #write #merge #iterator

sys librocksdbsys

Facebook的RocksDB嵌入式数据库librocksdb_sys包装器的分支

1 个不稳定版本

使用旧的Rust 2015

0.1.2 2019年4月16日

#2128数据库接口


用于 rexrocksdb

Apache-2.0

9MB
203K SLoC

C++ 176K SLoC // 0.1% comments Java 19K SLoC // 0.3% comments Shell 2.5K SLoC // 0.2% comments Rust 1.5K SLoC // 0.0% comments Python 1.5K SLoC // 0.2% comments C 1.5K SLoC // 0.1% comments PowerShell 286 SLoC // 0.2% comments PHP 255 SLoC // 0.2% comments Bitbake 159 SLoC // 0.2% comments INI 108 SLoC // 0.2% comments JavaScript 95 SLoC // 0.1% comments

包含 (WOFF字体, 75KB) LatoLatin-Italic.woff, (WOFF字体, 71KB) LatoLatin-Black.woff, (WOFF字体, 73KB) LatoLatin-BlackItalic.woff, (WOFF字体, 73KB) LatoLatin-Light.woff, (WOFF字体, 73KB) LatoLatin-Regular.woff, (WOFF字体, 44KB) LatoLatin-Black.woff2 等4个文件.

rust-rocksdb

此库已在Linux和macOS上与RocksDB 5.6.1进行了测试。

状态

  • 基本的打开/插入/获取/删除/关闭
  • rustic合并运算符
  • 写批处理(感谢 @dgrnbrg!)
  • 保存点
  • 压缩过滤器,风格
  • LRU缓存
  • 销毁/修复
  • 迭代器
  • 比较器
  • 快照
  • 列族操作
  • 前缀搜索
  • 切片转换
  • 速率限制器
  • 统计信息
  • 恢复
  • 备份
  • 暂停/继续后台工作
  • 删除范围
  • 导入外部sst文件
  • Windows支持

欢迎反馈和pull请求!如果您认为RocksDB的某个特性很重要,请通过打开问题让我们知道,我们将优先考虑它。

先决条件:RocksDB

首先,使用您系统的包管理器安装snappy。这是可选的,但可以让rocksdb利用更好的压缩,并且某些代码可能需要它。

有关安装rocksdb的信息,请参阅其安装指南。对于Windows用户,请确保您已启用rocksdb的CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS

或启用功能static-link,crate将自动下载和编译RocksDB及其依赖项。

cargo build --features static-link

运行

Cargo.toml
[dependencies.rocksdb]
git = "https://github.com/pingcap/rust-rocksdb.git"
代码
extern crate rocksdb;
use rocksdb::{DB, Writable};

fn main() {
    let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap();
    db.put(b"my key", b"my value");
    match db.get(b"my key") {
        Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
        Ok(None) => println!("value not found"),
        Err(e) => println!("operational problem encountered: {}", e),
    }

    db.delete(b"my key");
}
执行多个写入的原子提交
extern crate rocksdb;
use rocksdb::{DB, WriteBatch, Writable};

fn main() {
    // NB: db is automatically freed at end of lifetime
    let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap();
    {
        let mut batch = WriteBatch::new(); // WriteBatch and db both have trait Writable
        batch.put(b"my key", b"my value");
        batch.put(b"key2", b"value2");
        batch.put(b"key3", b"value3");
        db.write(batch); // Atomically commits the batch
    }
}
获取迭代器
extern crate rocksdb;
use rocksdb::{DB, Direction, IteratorMode};

fn main() {
    // NB: db is automatically freed at end of lifetime
    let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap();
    let mut iter = db.iterator(IteratorMode::Start); // Always iterates forward
    for (key, value) in iter {
        println!("Saw {} {}", key, value); //actually, need to convert [u8] keys into Strings
    }
    iter = db.iterator(IteratorMode::End);  // Always iterates backward
    for (key, value) in iter {
        println!("Saw {} {}", key, value);
    }
    iter = db.iterator(IteratorMode::From(b"my key", Direction::forward)); // From a key in Direction::{forward,reverse}
    for (key, value) in iter {
        println!("Saw {} {}", key, value);
    }

    // You can seek with an existing Iterator instance, too
    iter.set_mode(IteratorMode::From(b"another key", Direction::reverse));
    for (key, value) in iter {
        println!("Saw {} {}", key, value);
    }
}
从快照获取迭代器
extern crate rocksdb;
use rocksdb::{DB, Direction};

fn main() {
    // NB: db is automatically freed at end of lifetime
    let mut db = DB::open_default("/path/for/rocksdb/storage").unwrap();
    let snapshot = db.snapshot(); // Creates a longer-term snapshot of the DB, but freed when goes out of scope
    let mut iter = snapshot.iterator(IteratorMode::Start); // Make as many iterators as you'd like from one snapshot
}
Rustic合并运算符
extern crate rocksdb;
use rocksdb::{Options, DB, MergeOperands, Writable};

fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>,
    operands: &mut MergeOperands) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::with_capacity(operands.size_hint().0);
    existing_val.map(|v| {
        for e in v {
            result.push(*e)
        }
    });
    for op in operands {
        for e in op {
            result.push(*e)
        }
    }
    result
}

fn main() {
    let path = "/path/to/rocksdb";
    let mut opts = Options::new();
    opts.create_if_missing(true);
    opts.add_merge_operator("test operator", concat_merge);
    let mut db = DB::open(&opts, path).unwrap();
    let p = db.put(b"k1", b"a");
    db.merge(b"k1", b"b");
    db.merge(b"k1", b"c");
    db.merge(b"k1", b"d");
    db.merge(b"k1", b"efg");
    let r = db.get(b"k1");
    assert!(r.unwrap().unwrap().to_utf8().unwrap() == "abcdefg");
}
应用一些调整

请阅读官方调整指南,最重要的是,在现实工作负载和现实硬件下测量性能。

use rocksdb::{Options, DB};
use rocksdb::DBCompactionStyle::DBUniversalCompaction;

fn badly_tuned_for_somebody_elses_disk() -> DB {
    let path = "_rust_rocksdb_optimizetest";
    let mut opts = Options::new();
    opts.create_if_missing(true);
    opts.set_max_open_files(10000);
    opts.set_use_fsync(false);
    opts.set_bytes_per_sync(8388608);
    opts.set_disable_data_sync(false);
    opts.set_block_cache_size_mb(1024);
    opts.set_table_cache_num_shard_bits(6);
    opts.set_max_write_buffer_number(32);
    opts.set_write_buffer_size(536870912);
    opts.set_target_file_size_base(1073741824);
    opts.set_min_write_buffer_number_to_merge(4);
    opts.set_level_zero_stop_writes_trigger(2000);
    opts.set_level_zero_slowdown_writes_trigger(0);
    opts.set_compaction_style(DBUniversalCompaction);
    opts.set_max_background_compactions(4);
    opts.set_max_background_flushes(4);
    opts.set_disable_auto_compactions(true);

    DB::open(&opts, path).unwrap()
}

依赖项

~6MB
~100K SLoC