3个版本
2.0.0-beta.4 | 2020年7月31日 |
---|---|
2.0.0-beta.3 | 2020年7月3日 |
2.0.0-beta.2 | 2020年6月30日 |
#2839 in 数据库接口
99KB
1K SLoC
Turing·DB
TuringDB是一个用Rust编写的数据库,旨在实现分布式和水平扩展。它旨在替代不需要关系数据库或模式的情况。
数据库由Sled键值存储支持
动机
构建这个数据库的动机是拥有一个具有ACID属性、速度、类型安全、无轮询的change feeds、多集群查询和复制的键值数据库。Rust在速度、类型安全和编译时检查方面最有资格。此外,sled.rs
已经被用作这个数据库的嵌入式键值存储,因为它是无锁的、有完全原子的操作、零拷贝读取、SSD优化的日志存储,并且是用Rust编写的,因此继承了语言的所有美好特性。
特性
数据库旨在成为
- 非常简单的文档数据库
- 具有查找和范围能力
- 分区容错和一致
- 提供无轮询的实时推送能力,灵感来自RethinkDB的change feeds
- 提供简单的连接
- 提供由Raft共识算法支持的可选分布式能力
- 提供可选的多集群查询
- 足够小,可以用作嵌入式数据库
- 足够小和快,可以用于嵌入式设备或大型服务器
- 非常有趣使用
正在开发中的特性包括
- 复制
- 多集群查询
- 无轮询的change feeds,灵感来自RethinkDB
- 支持JSON
服务器使用
-
从crates-io安装
$ cargo install turingdb-server
-
启动服务器
$ turingdb-server
-
创建一个新的cargo仓库
$ cargo new my-app
-
编辑
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
-
在编辑器中打开
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(()) }
数据库支持当前支持的查询方法
-
仓库查询
turingdb_helpers::RepoQuery::create()
在当前目录中创建一个新的仓库turingdb_helpers::RepoQuery::drop()
删除当前目录中的仓库
-
数据库查询
-
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;
-
-
文档查询
-
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;
-
-
字段查询
-
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_codes
包的 DbOps::EncounteredErrors([TuringDB::<GLOBAL>::(ERROR)-BUFFER_CAPACITY_EXCEEDED_16MB])
贡献
我们在做出贡献时遵循 Rust 行为准则
许可
对本项目的所有代码贡献都必须使用 Apache 许可证
致谢
本项目使用的所有库都受其自身许可的约束
依赖
~7MB
~116K SLoC