36 个版本
0.9.1 | 2024 年 7 月 8 日 |
---|---|
0.8.6 | 2024 年 2 月 11 日 |
0.8.5 | 2023 年 12 月 18 日 |
0.8.4 | 2023 年 5 月 10 日 |
0.4.0 | 2018 年 11 月 26 日 |
#11 在 数据库实现
200KB
5K SLoC
有关版本信息的详细信息,请参阅变更日志。
简介
Sonnerie 是一个时间序列数据库。将字符串映射到时间戳和值的列表。在一个数据库中存储多个此类系列。在几分钟内插入数千万个样本,在旋转媒体或固态存储上。
Sonnerie 优化了存储大量值进入多个系列的数据(插入数百万个条目需要几分钟,并且不会阻塞其他读取器或写入器),并且一次读取一个系列需要 10 毫秒。它也非常擅长转储字典序序列(这意味着:一切)。
Sonnerie 可以非常高效地进行随机插入和更新,并且适用于大型数据库。由于紧凑的磁盘格式,稀疏数据(例如只有少数时间戳的键)可以非常高效地存储。
Sonnerie 主要用于磁盘存档、实时更新和单个系列实时访问。对于分析目的,将必要的数据加载到内存中并通过其他方式进行处理。
功能
- 直接读取和写入协议
- 易于设置:在命令行中插入数据。
- 没有查询语言
- 事务性:事务完全提交或完全不提交。
- 隔离:事务不会看到其他事务的更新,直到它被提交。注意“最后一条记录获胜”的语义 - 如果两个事务使用相同的键和时间戳写入两个值,则最后一个完成的事务的记录将被保留。
- 持久性:提交的数据对意外关闭造成的损失具有抵抗力。
- 纳秒级时间戳(64 位),1970-2554
- 没有奇怪的依赖关系,没有虚拟机,一个用于命令行工具的单个原生二进制文件
- 浮点数、整数和字符串值,每个样本多个列
- 使用 Rayon 进行范围并发读取 - 在现代硬件上,每秒处理数十亿条记录,每个核心需要 30 秒。
Sonnerie 运行在类 Unix 系统上,并在 Linux 上开发。
快速入门
安装
Sonnerie是用Rust编写的,这是一种运行速度极快的系统编程语言。因此,从源代码安装需要您安装Rust编译器,安装过程非常简单:curl https://sh.rustup.rs -sSf | sh
.
然后可以从Cargo安装Sonnerie:cargo install sonnerie
.
Sonnerie包含一个可执行文件,sonnerie
(位于~/.cargo/bin/sonnerie
)
创建数据库
通过创建一个目录和一个名为"main
"的空文件来创建数据库
mkdir database
touch database/main
插入数据
echo -e "\
fibonacci 2020-01-01T00:00:00 1
fibonacci 2020-01-02T00:00:00 1
fibonacci 2020-01-03T00:00:00 2
fibonacci 2020-01-04T00:00:00 3
fibonacci 2020-01-05T00:00:00 5
fibonacci 2020-01-06T00:00:00 8" \
| sonnerie -d database/ add --format u --timestamp-format=%FT%T
如果"添加"命令成功,则事务将提交到磁盘。
使用sonnerie add
添加的项目必须按其键的字典顺序排序,然后按时间顺序排序。在sonnerie-serve
中不存在此要求。
读取数据
sonnerie -d database/ read %
%
是一个通配符,类似于SQL中的"LIKE
",它根据键进行过滤。基于前缀的搜索非常高效
sonnerie -d database/ read fib%
Sonnerie输出匹配的值
fibonacci 2020-01-01 00:00:00 1
fibonacci 2020-01-02 00:00:00 1
fibonacci 2020-01-03 00:00:00 2
fibonacci 2020-01-04 00:00:00 3
fibonacci 2020-01-05 00:00:00 5
fibonacci 2020-01-06 00:00:00 8
删除记录
sonnerie -d database/ delete --after-time=2020-01-04
立即删除指定时间及其之后的所有值,还提供了--before-time
和类似的按键范围过滤功能。
数据将从数据库中立即删除。稍后的压缩将清除它并恢复磁盘空间。
用法
行格式
每个系列都有一个format
。格式指定为一系列单字符代码,每个值一个。
字符代码是
f
- 32位浮点数(f32)F
- 64位浮点数(f64)u
- 32位无符号整数(u32)U
- 64位无符号整数(u64)i
- 32位有符号整数(i32)I
- 64位有符号整数(i64)s
- UTF-8编码的字符串类型。当输出字符串时,它们以"转义反斜杠"形式编码,因此所有空白和反斜杠之前都有一个反斜杠。
在上面的"fibonacci"示例中,我们使用的是"u"格式。
允许多列行;对于表示纬度和经度的两个浮点值
oceanic-airlines 2018-01-01T00:00:00 ff 37.686751 -122.602227
oceanic-airlines 2018-01-01T00:00:01 ff 37.686810 -122.603713
oceanic-airlines 2018-01-01T00:00:02 ff 37.686873 -122.605997
oceanic-airlines 2018-01-01T00:00:03 ff 37.687022 -122.609997
oceanic-airlines 2018-01-01T00:00:04 ff 37.687364 -122.610945
oceanic-airlines 2018-01-01T00:00:05 ff 37.687503 -122.615211
Sonnerie允许异构格式。
单个键可以更改其格式,例如
keyname 2020-01-01T00:00:00 u 42
keyname 2020-01-02T00:00:00 f 3.1415
keyname 2020-01-03T00:00:00 s Now\ a\ string
虽然键可以更改其格式,但它具有更大的存储开销,因此最好不允许键在类型之间摆动。
这是从版本0.6开始允许的,旧版本有一个"不安全"模式,允许绕过测试以提高性能。
不需要服务器
所有操作都可以通过运行sonnerie -d /path/to/data/
来完成。此外,一个文件(在移除其".tmp"后缀后)永远不会改变,尽管文件有时可能会被替换。这意味着您可以通过硬链接所有文件来复制数据库(ln
)。
必须压缩数据库
定期(可能是每天)必须压缩数据库。这将许多事务文件滚成一个大的交易文件。这对于性能很重要。当大约有100个事务文件时,性能会大大下降。因此,以防止这种情况发生所需的速率压缩数据库。
压缩分为两种类型,一种是主要压缩,另一种是次要压缩。主要压缩会替换整个数据库,需要读取和重写整个数据库。次要压缩则是用一个新的事务文件替换所有的事务文件。这要快得多,因为它只需要读取和重写事务文件的内容,而不是main
文件。
主要压缩可以通过以下方式完成:
sonnerie -d /path/to/data/ compact --major
而次要压缩
sonnerie -d /path/to/data/ compact
压缩不会阻止读取器或写入器,但任何时刻只能发生一次,所以放置了一个锁来防止多个并发压缩。
压缩是原子性的,因此您可以随时取消它(使用^C
)。
您可以对压缩和过滤进行操作
如果数据库中的一些数据需要修改,您可以使用带有--gegnum
选项的compact
。Gegnum在冰岛语中意味着“通过”。
此命令会删除以bad-objects
开头的记录
compact --major --gegnum 'grep -v ^bad-objects'
进行正常压缩,但也要计数记录
compact --major --gegnum 'pv -l'
--gegnum
在其命令内部运行/bin/sh,因此管道可以工作。过滤出坏对象并修改其他对象的名称
compact --major --gegnum 'grep -v ^bad-objects | sed "s/^old-name/new-name/"'
--gegnum
命令的输出必须是有序的。
您也可以通过将命令管道传输到| tee /dev/stderr
来预览其输出。
注意,行以“key\ttimestamp\tformat\tvalue”的形式出现
您还可以通过“读取 | 过滤 | 添加”到不同的数据库中,但gegnum
允许您修改现有数据库,这对于对进行并发更新的数据库进行在线维护非常有用。
sonnerie-serve
提供了一个服务器,您可以通过HTTP方便地读取和写入数据库。
运行sonnerie-serve -d /path/to/database/ -l 0.0.00:5555
,然后您可以发出PUT
和GET
请求
-
读取命名的系列
curlhttps://127.0.0.1:5555/fibonacci
(响应是整个系列,格式类似于sonnerie read
)
-
通过通配符读取系列
curlhttps://127.0.0.1:5555/fib%
(响应是每个系列,按字母顺序排列,格式类似于sonnerie read
)
-
输出可读的时间戳
curlhttps://127.0.0.1:5555/fib%?human
(时间戳以ISO-8601格式表示,而不是纳秒)
-
添加更多数据
curl -XPUT https://127.0.0.1:5555/ --data-binary 'fibonacci 1578384000000000000 u 13'
(200 OK
表示事务已提交)
与sonnerie add
不同,sonnerie-serve
允许无序输入。
请注意,由于sonnerie mmap
其文件,sonnerie-serve将显示其虚拟内存使用量非常大(在top中为VIRT
),但实际上际内存利用率将是合理的。
您可以通过命令行继续读取和修改您的sonnerie数据库,甚至可以通过另一个并发运行的sonnerie-serve
。
另一种方法是使用 "sshfs" 在远程挂载数据库。这种方法性能非常好,因为只有压缩后的数据通过网络传输,服务器无需进行任何解压缩。请避免使用 nfs,因为压缩操作会导致文件被删除,然后客户端将收到 IO 错误,因为 NFS 无法追踪服务器上已关闭的文件。
贡献
无论大小如何,我们始终欢迎错误报告和拉取请求。Sonnerie 的发展以人为中心,我们遵守 Rust 的行为准则。
如果您使用 Sonnerie,请提供反馈!
Sonnerie 已在生产中使用
Sonnerie 被Headline 使用,拥有一个大于 100GiB 的数据库和数十亿行。
性能
在大数据库中随机键的平均查找延迟约为 15ms(在 SSD 上)和旋转媒体设备上的速度要慢得多。顺序访问(即按字典顺序读取整个数据库)的速度约为 2k 键/秒和 3M 记录/秒,这很大程度上取决于数据本身。
版权
Sonnerie 由 Charles Samuels 在Headline 实现。
依赖项
约 10-24MB
约 346K SLoC