3个版本

2.0.0-beta.42020年7月31日
2.0.0-beta.32020年7月3日
2.0.0-beta.22020年6月30日

#2922 in 数据库接口

每月37次下载
用于 turingdb-server

Apache-2.0

27KB
253

Turing·DB

Turing·DB Logo

TuringDB 是一个用 Rust 编写的数据库,旨在实现分布式和水平扩展。它旨在作为不需要关系数据库或模式的替代品。

数据库由 Sled 键值存储支持

动机

创建这个数据库的动机是拥有一个具有 ACID 属性、速度、类型安全、非轮询的 changefeeds、多集群查询和复制的键值数据库。Rust 是速度、类型安全和编译时检查最适合的语言。此外,sled.rs 已被用作此数据库的嵌入式键值存储,因为它是无锁的、具有完全原子的操作、零拷贝读取、SSD 优化的日志存储,并且是用 Rust 编写的,因此继承了语言的所有美妙特性。

特性

数据库旨在是

  1. 非常简单易用的文档数据库
  2. 具有查找和范围功能
  3. 分区容错和一致性
  4. 提供实时推送能力,无需轮询,灵感来自 RethinkDB changefeeds
  5. 提供简单的连接操作
  6. 提供由 Raft 一致性算法支持的分布式能力
  7. 提供多集群查询能力
  8. 足够小,可以用作嵌入式数据库
  9. 足够小和快速,可以在嵌入式设备或大型服务器上使用
  10. 非常有趣易用

正在开发中的特性包括

  1. 复制
  2. 多集群查询
  3. 非轮询的 changefeeds,灵感来自 RethinkDB
  4. 支持 JSON

服务器使用

  1. 从 crates-io 安装

    $ cargo install turingdb-server
    
  2. 启动服务器

    $ turingdb-server
    
  3. 创建一个新的 cargo 仓库

    $ cargo new my-app
    
  4. 编辑 Cargo.toml 文件

    #[dependencies]
    turingdb-helpers = #add the latest version here
    bincode = #add the latest version
    async-std = #add latest version here
    anyhow = # add latest version
    custom_codes = #add latest vesion
    

    如果您已安装 cargo-edit,则可以使用它而不是手动添加依赖项

    $ cargo add turingdb-helpers bincode async-std anyhow custom_codes
    
  5. 在编辑器中打开 src/main.rs 文件

    use async_std::net::TcpStream;
    use async_std::io::prelude::*;
    use serde::{Serialize, Deserialize};
    use custom_codes::DbOps;
    
    const BUFFER_CAPACITY: usize = 64 * 1024; //16Kb
    const BUFFER_DATA_CAPACITY: usize = 1024 * 1024 * 16; // Db cannot hold data more than 16MB in size
    
    #[derive(Debug, Serialize, Deserialize)]
    struct DocumentQuery {
        db: String,
        document: Option<String>,
    }
    
    #[derive(Debug, Serialize, Deserialize)]
    pub (crate) struct FieldQuery {
        db: String,
        document: String,
        field: String,
        payload: Option<Vec<u8>>,
    }
    
    #[async_std::main]
    async fn main() -> anyhow::Result<()> {
    	let db_create = "db0".as_bytes();
    	let mut packet = vec![0x02];
    	packet.extend_from_slice(&db_create);
    
        let mut buffer = [0; BUFFER_CAPACITY];
        let mut container_buffer: Vec<u8> = Vec::new();
        let mut bytes_read: usize;
        let mut current_buffer_size = 0_usize;
        
        let mut stream = TcpStream::connect("127.0.0.1:4343").await?;
        stream.write(&packet).await?;
    
        loop {
            bytes_read = stream.read(&mut buffer).await?;
            
    
            // Add the new buffer length to the current buffer size
            current_buffer_size += buffer[..bytes_read].len();
    
            // Check if the current stream is less than the buffer capacity, if so all data has been received
            if  buffer[..bytes_read].len() < BUFFER_CAPACITY {
                // Ensure that the data is appended before being deserialized by bincode
                container_buffer.append(&mut buffer[..bytes_read].to_owned());
    			dbg!(&container_buffer);
    
    			dbg!(bincode::deserialize::<DbOps>(&container_buffer).unwrap());
    		
    			break;
                
            }
            // Append data to buffer
            container_buffer.append(&mut buffer[..bytes_read].to_owned());        
        }
    
        Ok(())
    }
    

数据库支持的当前查询方法

  1. 仓库查询

    • turingdb_helpers::RepoQuery::create() 在当前目录中创建一个新的仓库
    • turingdb_helpers::RepoQuery::drop() 在当前目录中删除一个仓库
  2. 数据库查询

    • DbQuery::create() 在仓库中创建一个新数据库

      use turingdb_helpers::DatabaseQuery;
      
      let mut foo = DatabaseQuery::new().await;
      foo
        .db("db_name").await
        .create().await;
      
    • DbQuery::drop() 在仓库中删除一个数据库

      use turingdb_helpers::DatabaseQuery;
      
      let mut foo = DatabaseQuery::new().await;
      foo
      	.db("db_name").await
      	.drop().await;
      
    • DbQuery::list() 列出仓库中的所有数据库

      use turingdb_helpers::DatabaseQuery;
      
      let mut foo = Database::new().await;
      foo.drop().await;
      
  3. 文档查询

    • DocumentQuery::create() 在数据库中创建一个文档

      use turingdb_helpers::DocumentQuery;
      
      let mut foo = DocumentQuery::new().await;
      foo
      	.db("db_name").await
      	.document("document_name").await
      	.create().await;
      
    • DocumentQuery::drop() 在数据库中删除一个文档

      use turingdb_helpers::DocumentQuery;
      
      let mut foo = DocumentQuery::new().await;
      foo
      	.db("db_name").await
      	.document("document_name").await
      	.drop().await;
      
    • DocumentQuery::list() 列出数据库中的所有文档

      use turingdb_helpers::DocumentQuery;
      
      let mut foo = DocumentQuery::new().await;
      foo
      	.db("db_name").await
      	.list().await;
      
  4. 字段查询

    • Field::set() 基于键在文档中创建一个字段

      use turingdb_helpers::FieldQuery;
      
      let mut foo = FieldQuery::new().await;
      let data = "my_data_converted_into_bytes".as_bytes();
      foo
        .db("db_name").await
        .document("document_name").await
        .field("field_name").await
        .payload(data).await
        .set().await
      
    • Field::get() 基于键获取文档中的字段

      use turingdb_helpers::FieldQuery;
      
      let mut foo = FieldQuery::new().await;
      foo
        .db("db_name").await
        .document("document_name").await
        .field("field_name").await
        .get().await
      
    • Field::modify() 基于键更新文档中的字段

      use turingdb_helpers::FieldQuery;
      
      let mut foo = FieldQuery::new().await;
      let data = "my_new_data_converted_into_bytes".as_bytes();
      foo
        .db("db_name").await
        .document("document_name").await
        .field("field_name").await
        .payload(data).await
        .modify().await
      
    • Field::remove() 基于键删除文档中的字段

      use turingdb_helpers::FieldQuery;
      
      let mut foo = FieldQuery::new().await;
      foo
        .db("db_name").await
        .document("document_name").await
        .field("field_name").await
        .remove().await
      
    • Field::list() 获取所有字段的键

      use turingdb_helpers::FieldQuery;
      
      let mut foo = FieldQuery::new().await;
      foo
        .db("db_name").await
        .document("document_name").await
        .list().await
      

警告

一个文档不能存储超过 16MiB 的数据,如果超过此阈值,将产生来自 custom_codescrate的 DbOps::EncounteredErrors([TuringDB::<GLOBAL>::(ERROR)-BUFFER_CAPACITY_EXCEEDED_16MB])

贡献

我们遵循 Rust行为准则 来进行贡献

许可证

对本项目的所有代码贡献都必须以Apache许可证授权

致谢

本项目中使用的所有库均受其自身许可证的约束

依赖关系

~0.8–1.4MB
~32K SLoC