#kv #arrow #parquet #schema #datafusion #component

tonbo

Rust中的嵌入式持久化KV数据库

3个不稳定版本

新版本 0.1.0 2024年8月14日
0.0.1 2024年8月12日
0.0.0 2024年8月1日

#238数据库接口

Download history 109/week @ 2024-07-29 253/week @ 2024-08-12

每月362次下载

Apache-2.0

270KB
7.5K SLoC

Tonbo (工作进行中)

CI github star github fork

简介

Tonbo是一个基于Apache Arrow & Parquet构建的嵌入式KV数据库,旨在使用LSM树存储、过滤和投影结构化数据。

它可以非常自然地与Datafusion等Arrow数据处理组件结合使用。参考这个示例

我们的目标是提供一个简洁的现代解决方案,用于在分层存储中存储数据,该存储由RAM、闪存、SSD、S3以及其他存储设备组成。

特性

  • 完全异步API。
  • 零拷贝Rust API,通过编译时类型和生命周期检查确保安全性。
  • 供应商无关
    • 各种使用方法、异步运行时和文件系统
    • 最轻量级的Arrow / Parquet LSM树实现
      • 使用Arrow架构定义模式,并在Parquet文件中存储数据。
      • (乐观)事务。
      • 分层压缩策略。
      • 下推过滤、限制和投影。
  • 运行时架构定义(下一版本)。
  • SQL(通过Apache DataFusion)。
  • 跨RAM、闪存、SSD和每个列族的远程对象存储服务(OSS)融合存储,平衡每个数据块的性能和成本效益
  • 块存储(如RocksDB中的BlobDB)。

示例

use std::ops::Bound;

use futures_util::stream::StreamExt;
use tonbo::{executor::tokio::TokioExecutor, tonbo_record, Projection, DB};

// use macro to define schema of column family just like ORM
// it provides type safety read & write API
#[tonbo_record]
pub struct User {
    #[primary_key]
    name: String,
    email: Option<String>,
    age: u8,
}

#[tokio::main]
async fn main() {
    // pluggable async runtime and I/O
    let db = DB::new("./db_path/users".into(), TokioExecutor::default())
        .await
        .unwrap();

    // insert with owned value
    db.insert(User {
        name: "Alice".into(),
        email: Some("[email protected]".into()),
        age: 22,
    })
    .await
    .unwrap();

    {
        // tonbo supports transaction
        let txn = db.transaction().await;

        // get from primary key
        let name = "Alice".into();

        // get the zero-copy reference of record without any allocations.
        let user = txn
            .get(
                &name,
                // tonbo supports pushing down projection
                Projection::All,
            )
            .await
            .unwrap();
        assert!(user.is_some());
        assert_eq!(user.unwrap().get().age, Some(22));

        {
            let upper = "Blob".into();
            // range scan of
            let mut scan = txn
                .scan((Bound::Included(&name), Bound::Excluded(&upper)))
                .await
                // tonbo supports pushing down projection
                .projection(vec![1])
                .take()
                .await
                .unwrap();
            while let Some(entry) = scan.next().await.transpose().unwrap() {
                assert_eq!(
                    entry.value(),
                    Some(UserRef {
                        name: "Alice",
                        email: Some("[email protected]"),
                        age: Some(22),
                    })
                );
            }
        }

        // commit transaction
        txn.commit().await.unwrap();
    }
}

为Tonbo做出贡献

请随时在Github Discussions中提问或联系我们。

依赖项

~30–48MB
~1M SLoC