3 个不稳定版本
0.2.1 | 2023年2月25日 |
---|---|
0.2.0 | 2023年1月27日 |
0.1.0 | 2023年1月19日 |
#2301 in 数据库接口
174 每月下载次数
1MB
867 行
Cuttlestore
Cuttlestore是一个键值存储的通用API。它允许您无需额外努力即可支持多个键值存储,并能够在运行时在存储之间切换。
示例
use cuttlestore::{Cuttlestore, PutOptions};
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Serialize, Deserialize)]
struct SelfDestructingMessage {
message: String,
}
#[tokio::main]
async fn main() {
let store = Cuttlestore::new("filesystem://./example-store")
// or redis, sqlite, in-memory
.await
.unwrap();
let mission = SelfDestructingMessage {
message: "Your mission, should you choose to accept it, ...".to_string(),
};
store
.put_with("impossible", &mission, PutOptions::ttl_secs(60))
.await
.unwrap();
// Later
let value: Option<SelfDestructingMessage> = store.get("impossible").await.unwrap();
println!("Message says: {value:?}");
}
支持的后端
Cuttlestore目前支持以下后端
名称 | 功能 | 连接字符串 | 描述 | 默认启用 |
---|---|---|---|---|
Redis | backend-redis | redis://127.0.0.1 | 由Redis支持。这将为您提供最佳的扩展性。 | 是 |
Sqlite | backend-sqlite | sqlite://path | 一个用作键值存储的sqlite数据库。如果不需要扩展性,则性能最佳。 | 是 |
文件系统 | backend-filesystem | filesystem://path | 使用文件夹中的文件作为键值存储。性能取决于您的文件系统。 | 否 |
内存中 | backend-in-memory | in-memory | 不持久,但性能极高。如果存储是临时的,例如缓存,则非常有用。 | 是 |
安装
将Cuttlestore添加到您的 Cargo.toml
cuttlestore = "0.2"
如果您想禁用或启用某些后端,请禁用默认功能并选择您想要的
cuttlestore = { version = "0.2", default-features = false, features = [
# Only leave redis and sqlite enabled
"backend-redis",
"backend-sqlite",
# Remember to enable this or `logging-log`
"logging-tracing",
] }
现在您已经准备好使用Cuttlestore了!请参阅上面的示例,查看文档,并在仓库中找到更多示例。
概述
- 优点:Cuttlestore在以下情况下很有用
- 您想允许最终用户选择使用哪个存储,而无需重新编译
- 您正在寻找一个简单的键值存储API
- 缺点:避免使用Cuttlestore
- 您需要访问键值存储特定的功能
- 您只想使用一个键值存储,且不关心切换
例如,如果您正在创建一个自托管的Web应用程序,并希望允许用户根据需要选择使用Redis或sqlite,您可以使用Cuttlestore。Cuttlestore支持这两个后端,用户可以在应用程序设置中输入连接字符串以选择其中一个后端。大型部署的用户可以选择Redis,而小型用户可以选择sqlite,这样他们就不必部署Redis。
日志记录
该库可以使用tracing和log记录错误。tracing
默认启用,但您可以通过启用功能切换到log
。
cuttlestore = { version = "0.2", default-features = false, features = [
"logging-log",
# remember to enable the backends!
"backend-redis",
"backend-sqlite",
"backend-filesystem",
"backend-in-memory",
] }
后端详细信息
Redis
如果您不介意设置它,Redis通常是最佳选择。它提供良好的性能和可扩展性,因为您可以将多个应用程序服务器连接到同一Redis实例。
Cuttlestore支持TLS,您可以通过在连接字符串中添加一个s
来激活它,例如rediss://127.0.0.1
。您还可以通过添加:port
到末尾来更改您正在使用的端口号,例如redis://127.0.0.1:5678
。
Cuttlestore还支持ACL。您可以通过将其添加到连接字符串来启用它们。例如,如果您的用户名是agent
且密码是47
,您可以使用连接字符串redis://127.0.0.1?username=agent&password=47
。
Sqlite
Cuttlestore在用作此后端时可以使用sqlite数据库作为键值存储。数据库和任何表都会自动创建。
sqlite数据库被配置为使用预写日志,这意味着它可能在配置在连接字符串中的数据库文件旁边创建一些额外的文件。该配置还设置为有很小几率在发生崩溃时丢失最后几个put
或delete
操作,这是为了将性能提升到合理水平而不得不做出的遗憾。
Sqlite没有内置的ttl支持,因此ttl通过定期扫描数据库并在最佳努力的基础上删除已过期的条目来支持。这个扫描使用Tokio任务,这意味着它将在您的现有Tokio线程池中运行。
对于sqlite,您可以通过启用功能backend-sqlite-native-tls
或backend-sqlite-rustls
来选择本地TLS或Rustls。backend-sqlite
等同于backend-sqlite-native-tls
。
文件系统
Cuttlestore可以配置为使用文件夹作为键值存储。当使用此后端时,文件夹中的文件名是键,而值则使用二进制编码存储在文件中。
性能主要取决于您的文件系统。耐用性类似于sqlite:有很小风险会丢失最新的几个操作,但数据损坏是不预期的。
TTL功能通过定期扫描数据库并在最佳努力的基础上删除已过期的条目来支持。这个扫描使用Tokio任务,这意味着它将在您的现有Tokio线程池中运行。
内存中
内存后端是由dashmap支持的内存键值存储。
性能最好,但所有内容都保留在内存中,因此没有耐用性。
TTL
TTL(生存时间)功能允许您指定只应在存储中存在有限时间的值。超出TTL的值将被过期并从存储中删除以节省空间。
store.put_with("impossible", &mission, PutOptions::ttl_secs(60))
// or
store.put_with("impossible", &mission, PutOptions::ttl(Duration::from_secs(60)))
一些后端内置了对TTL(Redis)的支持。对于其他后端,通过定期运行一个Tokio任务来模拟TTL支持,该任务扫描存储并清理已过期的值。此任务在您的现有Tokio线程池中运行。您可以使用CuttlestoreBuilder
配置此清理任务运行的频率,请参阅构建器示例。
获取和扫描操作保证不会返回已过期的值,但已过期的值不一定立即被删除。
基准测试
有一些基准测试来比较不同后端性能。所有现有基准测试都使用小的键空间,因此性能不一定真实。
并发基准测试显示了后端的整体吞吐量,而顺序基准测试显示了每个请求可以预期的平均延迟。
简而言之,这些基准测试显示了以下几点
- Redis的延迟相对较高,每个操作约为67微秒。相比之下,第二慢的是sqlite,每个操作约为13到23微秒。
- 文件系统后端在吞吐量和延迟方面都提供了最佳性能,但最低和最高之间有很大的差异。在最坏的情况下,它比所有其他后端都要慢。
- 内存提供惊人的性能,但显然不可持久。
这些基准测试验证了readme中早些时候提到的建议。如果您需要可扩展性,Redis是一个不错的选择;如果可扩展性不是问题,sqlite也是一个好选择。如果性能不是关键问题,文件系统可以作为一个选择,但存在对于大型键空间性能不佳的风险。
依赖项
~6–25MB
~383K SLoC