Storh
Filbaserede poster til PHP: JSONC-dokumenter, append-only segmenterede logs og logbaserede køer med UUIDv7-id'er.
composer require storh/storhSeneste udgivelse v0.5.2 MIT PHP 8.2+
$pages = $docs
->query()
->where('kind')->eq('page')
->orderBy('title')
->limit(20)
->get();I praksis
Hurtigstarten i to dele: et dokument i en lagermappe, derefter en logpost og et køjob ved siden af.
Én rod, tre motorer
StorageRoot::resolve() normaliserer en basismappe og et navnerum til en rod, og hver motor opretter sin egen mappe under den ved første brug.
Hver motor returnerer StorageRecord-objekter med id() og data(). Køen føjer hver reservation og fuldførelse til sin hændelseslog.
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());
}JSONC-dokumentlager
Én JSONC-fil pr. post, UUIDv7-id'er, sharding efter to tegn fra den sidste gruppe i UUID, atomisk udskiftning og streamingfiltre på felter.
Segmenteret log
Append-only-segmenter med JSON-linjer, der har længde og checksum som præfikser, sparsomme indekser, læsning med cursor og tidsinterval, gendannelse efter nedbrud og komprimering.
Logkø
Jobs bevæger sig gennem statuserne afventer, behandles og færdig via kompakte append-only-køhændelser.
UUIDv7-poster
Sorterbare, tidsadresserbare id'er til stabile cursors, afgrænsede scanninger og shardvenlige lagerstier.
Atomiske skrivninger
Skrivning til midlertidige filer og atomiske omdøbninger holder posterne intakte. Efter et nedbrud under skrivning rydder den næste åbning op i forældreløse midlertidige filer.
Gendannelse af delvise skrivninger
Segmentlæsninger validerer længde- og checksumfelter; gendannelse afkorter delvise afsluttende linjer.
Filbaseret
Ingen databaseserver, ingen frameworkadapter, ingen Composer-runtimepakker; kalderen angiver en mappe.
Læsning JSONC
Postfiler kan indeholde kommentarer og afsluttende kommaer. storh-skrivninger gemmer kompakt JSON på én linje, så kommentarer bevares indtil næste skrivning.
Forespørgselsbygger
Kædede forespørgsler som where('status')->in([...]) på DocStore og SegmentedLog; DocStore bruger sekundære indekser, hvor de findes.
Sekundære indekser
Ligheds-, entydigheds- og intervalindekser gemt som filer ved siden af samlingen, afledt af posterne og genopbyggelige når som helst.
Skemaer
Valgfrie samlingsskemaer validerer hver skrivning og angiver, hvilke felter der indekseres.
SQL-spejl
Send samlinger til SQLite eller MySQL til joins, søgning og rapportering, mens filerne forbliver kanoniske. Kræver kun ext-pdo eller ext-mysqli, når funktionen bruges.
Hvorfor Storh
En mappe, ikke en server
Du angiver en basismappe, og storh skriver dertil. Den kræver PHP 8.2 og ext-json, ingen Composer-runtimepakker og ingen frameworkadapter.
Én postform, tre layouts
Dokumenter, logs og køer gemmer alle et UUIDv7-id plus et dataarray. Vælg disklayout efter arbejdsbelastning, og hold alle tre under én rod.
Kontroller, du kan køre
verify() kontrollerer indekser og logtilstand mod en fuld scanning af filerne. repair() sætter korrupte poster i karantæne og afkorter ødelagte logafslutninger, og CLI udskriver JSON for cron-jobs og sundhedskontroller.
Benchmarks med opsætningen beskrevet
README offentliggør medianer for 50,000 poster pr. motor på en Apple M1 Pro med PHP 8.5, f.eks. 5.6 µs pr. punktlæsning. Alle skrivninger i disse kørsler udføres med fsync, så skrivehastigheder afhænger af filsystemet.
Sammenlignet med
storh er filbaseret lagring snarere end en relationel forespørgselsmotor, så disse værktøjer klarer nogle af de opgaver, den udelader.
| Værktøj | God til | Forskel fra Storh |
|---|---|---|
| SQLite | God tilEn selvstændig SQL-motor i én fil med serialiserbare ACID-transaktioner, der holder ved programnedbrud eller strømsvigt. Dokumentationen beskriver den som en erstatning for ad hoc-datafiler. | Forskel fra Storhstorh gemmer én JSON-fil pr. post, og kernen kræver ingen PDO-driver. Den har ikke transaktioner på tværs af flere poster, og dokumentationen henviser dette arbejde til en egentlig database. Den kan sende samlinger til SQLite til joins og rapportering, mens filerne forbliver kanoniske. |
| MySQL | God tilEn relationel database, der leveres af en multitrådet SQL-server med klientprogrammer og biblioteker, administrationsværktøjer og et bredt udvalg af API'er. | Forskel fra Storhstorh kører i PHP-processen mod en mappe, så der er ingen server, der skal driftes. Til joins, søgning og rapportering spejler den samlinger til MySQL, også via et eksisterende mysqli-handle, og filerne forbliver sandhedskilden. |
| SleekDB | God tilEn flat-file-dokumentdatabase i PHP uden tredjepartsafhængigheder, der gemmer skemafrie data som almindelige JSON-filer. Dens forespørgsels-API omfatter joins, tekstsøgning, group by og having samt filtre på indlejrede egenskaber. | Forskel fra Storhstorh kombinerer sit dokumentlager med en append-only-segmenteret log og en logbaseret kø under én rod og udfører fsync på hver skrivning, før den melder, at den er gemt. Joins er ikke en del af storh; til dem sender den samlinger til SQLite eller MySQL. |
Spørgsmål og svar
Korte svar fra Storh-dokumentationen.
Ja. DocStore serialiserer ændringer med en skrivelås på samlingsniveau, og samtidige skrivninger til samme id afgøres af den seneste omdøbning. Køreservationer holder kølåsen, så to workers ikke reserverer det samme afventende job.
Ja. Læsninger accepterer kommentarer og afsluttende kommaer, men den næste put() til det id omskriver filen som kompakt JSON og fjerner dem. Med TRUST-cachetilstand registreres ændringer i filer uden for storh ikke.
Punktlæsninger efter id forbliver hurtige, så længe filsystemet kan håndtere antallet af filer. Uindekserede DocStore-feltscanninger bliver langsommere ved mere end cirka 10k poster, så deklarér indekser for de felter, du filtrerer på. Scanninger og intervalaflæsninger i segmenterede logs fungerer godt op til cirka 1M poster.
Skrivninger udføres med fsync og publiceres med atomisk omdøbning, og når en log eller kø åbnes igen, afkortes ødelagte afslutninger til den sidste bekræftede hændelse. Holdbarhed ved strømsvigt afhænger stadig af, om filsystemet og monteringsindstillingerne overholder disse synkroniseringer.
Nej. Send samlinger til SQLite eller MySQL med SqlMirror til joins, søgning og rapportering. Atomiske skrivninger på tværs af flere poster hører stadig til i en egentlig database, der fungerer som system of record.
Nej. Queue er ikke et generelt postlager, og et jobs payload slettes, når jobbet er fuldført.
Begynd med hurtigstarten, og brug derefter Choosing an engine til at tilpasse DocStore, SegmentedLog eller Queue til din arbejdsbelastning.