4个版本
0.1.3 | 2022年1月17日 |
---|---|
0.1.2 | 2021年10月29日 |
0.1.1 | 2021年10月29日 |
0.1.0 | 2021年10月29日 |
#1440在数据库接口
105KB
2.5K SLoC
Timesource
使用TimescaleDb作为存储引擎的事件源,适用于Rust应用程序。
注意:公共API非常不稳定。当API进一步稳定时,将发布文档。
特性
- 具有TimescaleDb提供所有优势的事件源
- 分区表,实现横向扩展
- 查询速度比PostgreSQL快10-100倍
- 压缩数据,降低存储需求
- 可以追踪到事件发生的确切时刻。将来,此crate旨在提供时间旅行和时间感知仓库的API。所有事件都有纳秒级的时间戳。
- Timesource采用灵活的事件序列化方法。它支持以下任一种格式:JSON、CBOR或Protocol Buffers
- 具有强大保护措施的消费者
- 如果数据库出现问题时,将应用背压
- 消费者处理速度慢时,会自我修复并赶上事件,当新消息的速率大于处理它们所需的时间时
- 偏移量存储在数据库中,以便消费者可以从上次离开的地方继续
- 灵活的排序约束
- 事件可以有序或无序地发布。但是,消费者始终会以有序的方式收到事件。
- 同一聚合类型的事件按单调递增的整数排序。聚合根按时间戳单独排序。
- 存储引擎可以处理总共9,223,372,036,854,775,807个事件,直到
11 April 2262 23:47:16.854
。
事件序列化/反序列化
Timesource支持
- JSON(使用serde json)
- CBOR(使用minicbor)
- Protocol Buffers(使用prost)
如果没有提供配置,timesource默认使用JSON。编码可以通过派生属性进行配置。例如
#[derive(serde::Serialize, serde::Deserialize, TimesourceEvent, PartialEq, Debug)]
#[timesource(encoding = "json")] // this is optional, as JSON is already the default
enum TdbEventJson {
Created,
Abandoned(String),
#[allow(dead_code)]
AddedItem {
id: usize,
},
}
#[derive(minicbor::Encode, minicbor::Decode, TimesourceEvent, PartialEq, Debug)]
#[timesource(encoding = "cbor", version = "1.1")] // it's also possible to set the version along with the encoding
enum TdbEventCbor {
#[b(0)]
Created,
#[b(1)]
Abandoned(#[b(0)] String),
#[b(2)]
AddedItem {
#[b(0)]
id: usize,
},
}
mod proto {
use prost::Message;
#[derive(Clone, PartialEq, Message)]
pub struct Created {}
#[derive(Clone, PartialEq, Message)]
pub struct Abandoned {
#[prost(string, tag = "1")]
pub reason: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Message)]
pub struct AddedItem {
#[prost(uint32, tag = "1")]
pub id: u32,
}
#[derive(Clone, PartialEq, Message, TimesourceEvent)]
#[timesource(encoding = "proto")]
pub struct TdbEvent {
#[prost(oneof = "tdb_event_proto::Data", tags = "1, 2, 3")]
pub data: ::core::option::Option<tdb_event_proto::Data>,
}
pub mod tdb_event_proto {
#[derive(Clone, PartialEq, ::prost::Oneof)]
pub enum Data {
#[prost(message, tag = "1")]
Created(super::Created),
#[prost(message, tag = "2")]
Abandoned(super::Abandoned),
#[prost(message, tag = "3")]
AddedItem(super::AddedItem),
}
}
}
每种支持的协议都有其优点和缺点,可能没有一种可以覆盖所有用例。
以下表格总结了为什么选择每种协议
编码 | 人类友好(即易于阅读) | 性能 | 存储大小 | 模式演化支持 |
---|---|---|---|---|
JSON | x | (通过 derive 属性手动) | ||
CBOR | x | x | x | |
Protobuf | x | x | x |
尽管目前还没有关于 timesource 的基准测试,但检查 serdebench 的序列化基准测试可能会有所帮助。
与 Eventually 的区别
Timesource 是作为 eventually-rs 的分支而诞生的。Eventually-rs 不支持时间戳,因此无法将 timescaledb 作为存储引擎有意义地使用。
而 Eventually 的理念是成为一个具有可插拔存储引擎的事件源库,Timesource 只会支持 Timescaledb。这使得 Timesource 的范围更加狭窄。这也允许进行一些优化,更有效地处理事件,并消除 内存溢出 的风险。
如何使用
请参阅 订单聚合示例
依赖项
~20–31MB
~572K SLoC