Storh
Registros con prioridad en archivos para PHP: documentos JSONC, registros segmentados de solo anexado y colas respaldadas por registros con ids UUIDv7.
composer require storh/storhÚltima versión v0.5.2 MIT PHP 8.2+
$pages = $docs
->query()
->where('kind')->eq('page')
->orderBy('title')
->limit(20)
->get();En la práctica
Inicio rápido en dos partes: un documento en una raíz de almacenamiento y, junto a él, una entrada de registro y un trabajo en cola.
Una raíz, tres motores
StorageRoot::resolve() normaliza un directorio base y un espacio de nombres en una raíz, y cada motor crea su propio directorio dentro de ella la primera vez que se usa.
Todos los motores devuelven objetos StorageRecord con id() y data(). La cola añade cada reclamación y finalización a su registro de eventos.
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());$log = new SegmentedLog($root, 'events');
$log->put([
'type' => 'page.saved',
'pageId' => $home->id(),
]);
foreach ($log->stream(RecordQuery::all()->after($home->id())->limit(50)) as $record) {
// Process records lazily.
}
$queue = new Queue($root, 'jobs');
$jobId = $queue->enqueue(['task' => 'render', 'pageId' => $home->id()]);
$job = $queue->claim();
if (null !== $job) {
$queue->complete($job->id());
}Almacén de documentos JSONC
Un archivo JSONC por registro, ids UUIDv7, fragmentación con dos caracteres del último grupo de UUID, reemplazo atómico y filtros de campos en streaming.
Registro segmentado
Segmentos de solo anexado con líneas JSON precedidas por longitud y suma de verificación, índices dispersos, lecturas por cursor y rango de tiempo, recuperación tras fallos y compactación.
Cola de registros
Los trabajos pasan por los estados pendiente, en proceso y completado mediante eventos compactos de cola de solo anexado.
Registros UUIDv7
Ids ordenables y localizables por fecha para cursores estables, recorridos acotados y rutas de almacenamiento adaptadas a la fragmentación.
Escrituras atómicas
Las escrituras en archivos temporales y los renombrados atómicos mantienen íntegros los registros. Tras el bloqueo de un escritor, la siguiente apertura elimina sus archivos temporales huérfanos.
Recuperación de escrituras incompletas
Las lecturas de segmentos validan los campos de longitud y suma de verificación; la recuperación trunca las líneas finales parciales.
Prioridad en archivos
Sin servidor de base de datos, sin adaptador de framework y sin paquetes de ejecución Composer; quien llama pasa un directorio.
Lecturas JSONC
Los archivos de registro pueden incluir comentarios y comas finales. storh escribe JSON compactos de una sola línea, por lo que los comentarios se conservan hasta la siguiente escritura.
Constructor de consultas
Consultas encadenables como where('status')->in([...]) en DocStore y SegmentedLog; DocStore utiliza índices secundarios cuando están disponibles.
Índices secundarios
Índices de igualdad, unicidad y rango almacenados en archivos junto a la colección, derivados de los registros y reconstruibles en cualquier momento.
Esquemas
Los esquemas de colección opcionales validan cada escritura y declaran qué campos se indexan.
Espejo de SQL
Envíe colecciones a SQLite o MySQL para hacer uniones, búsquedas e informes mientras los archivos siguen siendo la fuente canónica. Solo necesita ext-pdo o ext-mysqli cuando se usa.
Por qué Storh
Un directorio, no un servidor
Indique un directorio base y storh escribirá allí. Necesita PHP 8.2 y ext-json, sin paquetes de ejecución Composer ni adaptador de framework.
Una forma de registro, tres diseños
Documentos, registros y colas almacenan un id UUIDv7 y un arreglo de datos. Elija el diseño en disco según la carga de trabajo y mantenga los tres bajo una misma raíz.
Comprobaciones que puede ejecutar
verify() compara los índices y el estado del registro con un recorrido completo de los archivos. repair() pone en cuarentena los registros dañados y trunca los finales incompletos del registro; CLI muestra JSON para los trabajos y las comprobaciones de estado de cron.
Pruebas de rendimiento con su configuración
README publica medianas para 50,000 registros por motor en un Apple M1 Pro con PHP 8.5, como 5.6 µs por lectura puntual. En esas pruebas, cada escritura se sincroniza con fsync, por lo que las tasas de escritura dependen del sistema de archivos.
Comparación con
storh prioriza el almacenamiento en archivos en lugar de las consultas relacionales, así que estas herramientas realizan algunas tareas que no ofrece.
| Herramienta | Ideal para | Diferencia con Storh |
|---|---|---|
| SQLite | Ideal paraUn motor SQL autónomo en un solo archivo, con transacciones ACID serializables que resisten un fallo del programa o un corte de energía. Su documentación lo presenta como una alternativa a los archivos de datos improvisados. | Diferencia con Storhstorh mantiene un archivo JSON por registro y su núcleo no necesita un controlador PDO. No admite transacciones entre varios registros; su documentación recomienda usar una base de datos real para esa tarea. Puede enviar colecciones a SQLite para hacer uniones e informes, mientras los archivos siguen siendo la fuente canónica. |
| MySQL | Ideal paraUna base de datos relacional servida por un servidor SQL multihilo, con programas cliente y bibliotecas, herramientas de administración y una amplia variedad de APIs. | Diferencia con Storhstorh se ejecuta dentro del proceso PHP y opera sobre un directorio, por lo que no hay ningún servidor que administrar. Para hacer uniones, búsquedas e informes, refleja colecciones en MySQL, también mediante un controlador mysqli existente; los archivos siguen siendo la fuente de verdad. |
| SleekDB | Ideal paraUna base de datos documental de archivos planos en PHP, sin dependencias de terceros, que almacena datos sin esquema en archivos JSON simples. Su API de consultas incluye uniones, búsqueda de texto, agrupación y filtros sobre propiedades anidadas. | Diferencia con Storhstorh combina su almacén de documentos con un registro segmentado de solo anexado y una cola respaldada por registros bajo una misma raíz, y sincroniza cada escritura con fsync antes de confirmar que se ha guardado. Las uniones no forman parte de storh; para hacerlas, envía colecciones a SQLite o MySQL. |
Preguntas y respuestas
Respuestas breves de la documentación de Storh.
Sí. DocStore serializa las modificaciones mediante un bloqueo de escritura por colección, y en escrituras simultáneas al mismo id prevalece el último renombrado. Las reclamaciones de trabajos de la cola mantienen el bloqueo de la cola, por lo que dos trabajadores no reclaman el mismo trabajo pendiente.
Sí. La lectura admite comentarios y comas finales, pero la siguiente put() de ese id reescribe el archivo como JSON compacto y los elimina. Con el modo de caché TRUST, no se detectan los cambios en archivos hechos fuera de storh.
Las lecturas puntuales por id siguen siendo rápidas mientras el sistema de archivos pueda manejar la cantidad de archivos. Las búsquedas de campos sin índice en DocStore se ralentizan al superar aproximadamente los 10k registros, así que declare índices para los campos por los que filtre. Los recorridos y las lecturas por rango del registro segmentado funcionan bien con hasta aproximadamente 1M de registros.
Las escrituras se sincronizan con fsync y se publican mediante un renombrado atómico; al volver a abrir un registro o una cola, se truncan los finales incompletos hasta el último evento confirmado. La durabilidad ante cortes de energía sigue dependiendo de que el sistema de archivos y las opciones de montaje respeten esas sincronizaciones.
No. Envíe colecciones a SQLite o MySQL mediante SqlMirror para hacer uniones, búsquedas e informes. Las escrituras atómicas de varios registros siguen siendo tarea de una base de datos real como sistema de registro.
No. Queue no es un almacén de registros de uso general, y la carga útil de un trabajo se descarta al completarlo.
Empiece con el inicio rápido y luego consulte Elegir un motor para adaptar DocStore, SegmentedLog o Queue a su carga de trabajo.