1 个不稳定版本
0.1.0 | 2023年11月8日 |
---|
#137 在 数据库实现 中
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,可以在 glommio
或 tokio
上运行(使用 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