#document-database #distributed-database #thread-per-core #io-uring #database #rust

bin+lib dbeel

dbeel 是一个快速且极简的按核心分布的文档数据库

1 个不稳定版本

0.1.0 2023年11月8日

#137数据库实现

Apache-2.0 OR MIT

205KB
5.5K SLoC

简介

dbeel 是学习现代数据库架构的一次尝试。

描述数据库的最佳一句话是: 使用 Rust 编写的分布式按核心文档数据库。

基本上,它具有类似 MongoDB 的文档 API,类似 Cassandra 的无首领复制,以及类似 ScyllaDB 的按核心架构。

它根本不适合生产环境,但这并不意味着项目没有价值。如果您曾想阅读数据库代码而又不想被大量的代码所淹没,那么 dbeel 就是您要找的。

特性

  • 文档 + API 使用 msgpack 格式
  • LSM 树
    • Memtable 是一棵红黑树
  • 按核心线程(感谢 glommio
  • io_uring(再次感谢 glommio
  • 直接 I/O
    • 使用 WTiny-LFU 弃置算法实现的页面缓存
  • 通过 一致性哈希 进行负载均衡
    • 每个分片(核心)都放置在环上
  • 使用 Gossip 传播 发送元数据事件
  • 无首领复制,具有可调一致性
    • replication_factor(在 create_collection 命令中的参数) - 将存储数据副本的节点数量
    • 写入 consistency(在 set 命令中的参数) - 为成功,确认写入的节点数量
    • 读取 consistency(在 get 命令中的参数) - 为成功,响应读取操作的节点数量
      • 最大时间戳冲突解决

性能

在我的机器上运行基准测试(System76 lemp11)且没有 fdatasync 的结果如下

Set:
total: 54.424290449s, min: 80.219µs, p50: 446.851µs, p90: 905.422µs, p99: 1.806261ms, p999: 7.463916ms, max: 35.385961ms

Get:
total: 29.281556369s, min: 36.577µs, p50: 231.464µs, p90: 479.929µs, p99: 1.222589ms, p999: 3.269881ms, max: 6.242454ms

使用 --wal-sync 运行(每次写入WAL文件后调用 fdatasync)将导致以下输出(请注意,在我的机器上 fdatasync 需要 6-10ms)

Set:
total: 1253.611595658s, min: 6.625024ms, p50: 12.57609ms, p90: 12.858347ms, p99: 13.4931ms, p999: 19.062725ms, max: 31.880792ms

您始终可以通过设置 --wal-sync-delay 来配置 --wal-sync 以获得更好的吞吐量,但尾部延迟更差(尝试将时间设置为平均 fdatasync 文件所需时间的一半)。

使用方法

唯一实现的客户端是异步Rust,可以在 glommiotokio 上运行(使用 cargo features 选择其中一个)。

文档格式为 msgpack,我找到的最佳crate是 rmpv,因此客户端大量使用了它。

示例(大部分来自 tokio_example/

// When connecting to a cluster, you provide nodes to request cluster metadata from.
let seed_nodes = [("127.0.0.1", 10000)];
let client = DbeelClient::from_seed_nodes(&seed_nodes).await?;

// Create a collection with replication of 3 (meaning 3 copies for each document).
let collection = client.create_collection_with_replication(COLLECTION_NAME, 3).await?;

// Create key and document using rmpv.
let key = Value::String("key".into());
let document = Value::Map(vec![
    (Value::String("is_best_db".into()), Value::Boolean(true)),
    (Value::String("owner".into()), Value::String("tontinton".into())),
]);

// Write document using quorum consistency.
collection.set_consistent(key.clone(), value.clone(), Consistency::Quorum).await?;

// Read document using quorum consistency.
let response = collection.get_consistent(key, Consistency::Quorum).await?;
assert_eq!(response, value);

// Drop collection.
collection.drop().await?;

试试看

编译数据库

cargo build --release
./target/release/dbeel --help

编译黑盒基准测试

cd blackbox_bench
cargo build --release

运行基准测试

./target/release/dbeel               # On first terminal
./target/release/blackbox-bench      # On second terminal

依赖项

~17–28MB
~442K SLoC