跳转到正文

Storh

面向 PHP 的文件优先记录:JSONC 文档、只追加的分段日志,以及由日志支持、使用 UUIDv7 id 的队列。

终端
composer require storh/storh

最新版本 v0.5.2 MIT PHP 8.2+

实践应用

两部分快速入门:先在存储根目录中创建文档,再在旁边添加日志条目和队列作业。

一个根目录,三种引擎

StorageRoot::resolve() 会将基础目录和命名空间规范化为一个根目录,每种引擎首次使用时都会在其中创建自己的目录。

每种引擎都会返回带有 id() 和 data() 的 StorageRecord 对象。队列会将每次领取和完成操作追加到其事件日志中。

文件
use Storh\DocStore;
use Storh\Queue;
use Storh\RecordQuery;
use Storh\SegmentedLog;
use Storh\StorageRoot;

$root = StorageRoot::resolve(__DIR__ . '/var/storh', 'demo');

$docs = new DocStore($root, 'pages');
$home = $docs->put([
    'kind' => 'page',
    'title' => 'Home',
]);

$loaded = $docs->get($home->id());

JSONC 文档存储

每条记录对应一个 JSONC 文件、使用 UUIDv7 id、按 UUID 最后一组中的两个字符进行分片、原子替换,并支持流式字段筛选。

分段日志

只追加的分段包含带长度和校验和前缀的 JSON 行,并支持稀疏索引、游标和时间范围读取、崩溃恢复及压缩。

日志队列

作业通过紧凑的只追加队列事件,在待处理、处理中和已完成状态之间流转。

UUIDv7 记录

可排序、可按时间定位的 id,适用于稳定游标、有界扫描和便于分片的存储路径。

原子写入

临时文件写入和原子重命名可确保记录完整。写入进程崩溃后,下次打开时会清理其孤立的临时文件。

写入截断恢复

分段读取会验证长度和校验和字段;恢复时会截断末尾不完整的行。

文件优先

无需数据库服务器、框架适配器或 Composer 运行时软件包;调用方只需传入一个目录。

读取 JSONC

记录文件可以包含注释和尾随逗号。storh 会写入紧凑的单行 JSON,因此注释会一直保留到下次写入。

查询构建器

DocStore 和 SegmentedLog 支持流畅查询,例如 where('status')->in([...]);DocStore 会使用现有的二级索引。

二级索引

相等、唯一和范围索引以文件形式存储在集合旁边,由记录派生生成,并可随时重建。

架构

可选的集合架构会验证每次写入,并声明哪些字段需要建立索引。

SQL 镜像

将集合推送到 SQLite 或 MySQL,即可进行联接、搜索和报告,同时文件仍是权威数据源。只有在使用时才需要 ext-pdo 或 ext-mysqli。

为什么选择 Storh

一个目录,无需服务器

你只需传入一个基础目录,storh 就会在那里写入。它需要 PHP 8.2 和 ext-json,无需 Composer 运行时软件包或框架适配器。

一种记录格式,三种存储布局

文档、日志和队列都会存储一个 UUIDv7 id 和一个数据数组。你可以根据工作负载选择磁盘布局,并将三者都放在同一个根目录下。

可运行的检查

verify() 会将索引和日志状态与文件的完整扫描结果进行核对。repair() 会隔离损坏的记录并截断日志末尾的不完整部分;CLI 会为 cron 作业和健康检查打印 JSON。

附有配置说明的基准测试

README 会公布在配备 PHP 8.5 的 Apple M1 Pro 上,各引擎处理 50,000 条记录时的中位数,例如每次点读取耗时 5.6 µs。这些测试中的每次写入都会执行 fsync,因此写入速率取决于文件系统。

对比

storh 是文件优先的存储,而非关系型查询引擎,因此这些工具可以完成它未涵盖的一些工作。

Storh 与其他工具的对比
SQLite 擅长领域一个自包含的 SQL 引擎,全部封装在单个文件中,并支持可序列化的 ACID 事务,即使程序崩溃或断电也能保持事务完整。其文档将其描述为零散数据文件的替代方案。 与 Storh 的区别storh 为每条记录保留一个 JSON 文件,其核心无需 PDO 驱动。它不支持跨多条记录的事务,相关工作应交由真正的数据库处理。它可以将集合推送到 SQLite 以进行联接和报告,同时文件仍是权威数据源。
MySQL 擅长领域由多线程 SQL 服务器提供服务的关系型数据库,配有客户端程序和库、管理工具以及丰富的 API。 与 Storh 的区别storh 在 PHP 进程内针对一个目录运行,因此无需运维服务器。若要进行联接、搜索和报告,它可以将集合镜像到 MySQL,也可以使用现有的 mysqli 句柄;文件仍是事实来源。
SleekDB 擅长领域一个基于 PHP 的平面文件文档数据库,无第三方依赖,以纯 JSON 文件存储无架构数据。其查询 API 支持联接、文本搜索、group by 和 having,以及对嵌套属性进行筛选。 与 Storh 的区别storh 将文档存储与只追加的分段日志和日志队列配对,统一置于一个根目录下,并在报告每次写入已存储之前执行 fsync。联接并非 storh 的功能;它会将集合推送到 SQLite 或 MySQL 来实现联接。

问答

来自 Storh 文档的简明解答。

从快速入门开始,然后使用“选择引擎”,根据工作负载选择 DocStore、SegmentedLog 或 Queue。