10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

sledというRust製のNoSQLなライブラリ(?)触ってみた

Last updated at Posted at 2019-03-09

はじめに

状態を保っていてcrudな操作をするようなcliをRustで作ろうとした時に、
sqliteなど外部ツールに依存するのもアレだなと思って、
パス1個渡すだけで、ファイルなりにcrudな操作ができる、DBみたいなライブラリがあれば良いなと思って調べていました。

すると、sledという組み込み向けのそれっぽいライブラリがあり、
スターが1800くらい付いていて、
サンプルを見た感じ、path1個通すだけで済んでcrudな操作も出来そうなので、少し触ってみました。

*載せてる公式のサンプルコードやライブラリのAPIは2019/03/10現在のものです

公式のgithubに書いてあるサンプルコード
// https://github.com/spacejam/sled#sled
use sled::Db;

let tree = Db::start_default(path)?;

// set and get
tree.set(k, v1);
assert_eq!(tree.get(&k), Ok(Some(v1)));

// compare and swap
tree.cas(k, Some(v1), Some(v2));

// scan forward
let mut iter = tree.scan(k);
assert_eq!(iter.next(), Some(Ok((k, v2))));
assert_eq!(iter.next(), None);

// deletion
tree.del(&k);

// block until all operations are on-disk
tree.flush();

触ってみる

↓dependenciesにsledを追加する

cargo.toml
# ...省略
[dependencies]
sled = "0.19.0"

↓ストレージ用のディレクトリを作成する

// projectのルートに作る
$ mkdir test_storage
$ tree -L 1
  .
  ├── Cargo.lock
  ├── Cargo.toml
  ├── src
  ├── target
+ └── test_storage

↓こんな感じにmain.rsを書いて

main.rs
extern crate sled;

use sled::Db;

fn main() {
    let path = "test_storage";
    let tree = Db::start_default(path).unwrap();
}

cargo runする
(test_storage以下にそれっぽいファイルとかが増えていればひとまず動いていそう)

$ cargo run
$ tree -L 2
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
├── target
│   └── debug
└── test_storage
+    ├── blobs
+    ├── conf
+    ├── db
+    └── snap.0000000000000000

setしてgetするだけの単純なコードを書いてみる

main.rs
extern crate sled;

use sled::Db;

fn main() {
    let dir_path = "test_storage";
    let tree = Db::start_default(dir_path).unwrap();

    let key = "hoge";
    let value = "abcdefg";

    // `API similar to a threadsafe BTreeMap<Vec<u8>, Vec<u8>>` とのこと。
    // tree.setのvalueのtypeも `type Value = Vec<u8>;`
    // を要求しているので、`as_bytes().to_vec()`を噛ませる
    tree.set(&key, value.as_bytes().to_vec())
        .expect("set fail");

    match tree.get(&key) {
        Ok(Some(res)) => {
            let converted: String = String::from_utf8(res.to_vec()).unwrap();
            assert_eq!(value,converted);
            println!("{}", converted); // abcdefg
        }
        _ => {}
    }
}

公式のサンプルにも書いてあるが、set,get以外にもupdate(swap)したり、scanしたり、deleteしたり、簡単な操作は一通りできるよう。


// compare and swap
    tree.cas(k, Some(v1), Some(v2));

// scan forward
    let mut iter = tree.scan(k);
    assert_eq!(iter.next(), Some(Ok((k, v2))));
    assert_eq!(iter.next(), None);

// deletion
    tree.del(&k);

// block until all operations are on-disk
    tree.flush();
}

良いところ、イマイチなところ

sledの良いところ

  • ディレクトリのパス1個渡すだけで、使える
  • sqliteなど使わずにrust単体でちょっとしたツールが作れそう

sledのイマイチなところ

  • 2019/03/10時点でまだアルファ版
  • 32bit環境はnightly版で動かさないといけなさそう
  • test_storageの中にdbというファイルが生成され、雰囲気的にこのファイルにガリガリ書き込んでいく様子
    • append onlyなのかtree.flush()を走らせても中身は削除されず、tree.set()のたびにファイルがどんどん大きくなるようだった。
    • (もしかしたら、そういうものなのかもしれない。)

まとめ

まだアルファ版なのと、setするとひたすらでかくなるファイルが気になりますが、
ディレクトリのパス1個だけ渡すだけですぐに使えるのと、
rust単体で完結しそうなのでポータビリティ高めなツールが作れそうな気がしました。

10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?