Gå til indhold

Motorer

Valg af motor

Alle tre motorer gemmer det samme: et id af typen UUIDv7 plus et data-array, men de organiserer det forskelligt på disken. Denne organisering afgør, hvad hver motor egner sig til:

DocStore SegmentedLog Queue
På disk én JSONC-fil pr. post, opdelt i shards efter de sidste UUID tegn tilføjelsesbaserede segmenter med længde- og kontrolsumpræfikserede JSON-linjer samt et manifest én tilføjelsesbaseret hændelseslog
Skrivning atomisk filudskiftning pr. post tilføjelser med kontrolsum; overskrivninger og sletninger tilføjer nye poster, som frigøres ved compact() tilføjelse med kontrolsum for hver køhændelse
Læsning get() efter id, indekserede forespørgsler markør- og tidsområdescanninger, get() via tilstandsindekset claim() i enqueue-rækkefølge
Bedst til punktlæsninger og indekserede opslag ved alle samlingsstørrelser streams med mange tilføjelser, op til omkring 1M poster varig arbejdsfordeling mellem processer
Svaghed scanning af ikke-indekserede felter over cirka 10k poster hyppige omskrivninger af enkeltposter (ældre versioner optager plads indtil komprimering) ikke et generelt postlager; payloads fjernes, når et job er afsluttet

DocStore og SegmentedLog deler den samme flydende forespørgsels-API: den samme where()-kæde fungerer på begge motorer, og kun udførelsen er forskellig. DocStore kan hente svar fra sine sekundære indekser, mens SegmentedLog filtrerer under scanning af segmenter. Queue bruger claims, ikke forespørgsler: arbejdere claim() det næste job i stedet for at filtrere job.

Tommelfingerregler:

  • Poster, som du henter, opdaterer eller sletter enkeltvis og forespørger på efter felt: DocStore. Tilføj indekser for de felter, du filtrerer på.
  • Hændelser eller versioner, som du hovedsageligt tilføjer og læser tilbage i rækkefølge eller inden for et tidsinterval: SegmentedLog.
  • Job, der sendes fra producenter til arbejdsprocesser: Queue. Claims og afslutninger er sikre på tværs af processer, og claimMany()/completeMany() fordeler låse- og fsync-omkostningerne.
  • Sammenføjninger, søgning eller rapportering på tværs af en samling: tilføj et SQL-spejl. Filerne forbliver kanoniske; spejlet er en genopbyggelig projektion i SQLite eller MySQL.

Motorer kan kombineres: de deler kun rodmappen, så en applikation kan gemme indhold i en DocStore, et revisionsspor i en SegmentedLog og baggrundsarbejde i en Queue under samme lagerrod.

DocStore

DocStore er til punktlæsninger og enkle scanninger af varige poster. Den skriver én JSONC-fil pr. post:

PHP
$store = new Storh\DocStore($root, 'articles');
$record = $store->put(['slug' => 'hello', 'published' => true]);
$same = $store->get($record->id());

Postfiler opdeles i shards efter de sidste UUID tegn, så skriveudbrud fra UUIDv7 fordeles på tværs af mapper:

Text
articles/data/2d/018bcfe5-6800-7000-8000-2d5dba6274da.jsonc

SegmentedLog

SegmentedLog er til poster med mange tilføjelser, markørlæsninger og tidsområdelæsninger. Poster skrives til det aktive segment, én linje pr. post i formatet <byte-length>\t<xxh32>\t<json> (se Atomicitet). Segmentfilerne bruger filtypen .ndjson, men længde- og kontrolsumpræfikset betyder, at almindelige NDJSON-værktøjer ikke kan læse dem; læs posterne med stream() eller forespørgselsbyggeren. Fulde segmenter rulles over i forseglede segmenter med sparsomme indekser.

PHP
$events = new Storh\SegmentedLog($root, 'events');
$events->put(['type' => 'user.created']);
$events->compact();

Queue

Queue er til varige arbejdskøer med høj gennemstrømning. Enqueue, claim, complete, requeue og purge skriver tilføjelsesbaserede hændelser til queue.log; køtilstanden afspilles til hukommelsen, når køen åbnes. Batchmetoder fordeler låse- og flush-omkostningen på mange job. Loggen vokser med hver hændelse; stats() rapporterer dens aktuelle størrelse i bytes.

PHP
$queue = new Storh\Queue($root, 'mail');
$queue->enqueue(['to' => 'person@example.test']);
$job = $queue->claim();

Holdbarhed og samtidighed

storh offentliggør filskrivninger med atomisk omdøbning i målmappen. Ved genåbning og repair() fjernes forladte midlertidige filer, hvis ejerproces er afsluttet, mens midlertidige filer fra aktive skrivere bevares. Markører for skrivere gør kontrollen hurtig, så samlingen kun gennemgås, når et lager åbnes efter et nedbrud.

SegmentedLog og Queue skriver loglinjer med længde- og kontrolsumkontrol. Genåbning eller reparation afkorter afbrudte slutninger til den senest bekræftede hændelse og genopbygger tilstanden i hukommelsen ud fra loggens varige indhold. Log- og køskrivninger serialiseres med filsystemlåse.

DocStore-ændringer serialiseres med en skrivelås på samlingsniveau, så postfiler og sekundære indekser opdateres samlet som én konsistensgrænse på tværs af processer. Samtidige skrivninger til forskellige post-id'er er sikre under de samme antagelser om atomisk omdøbning i filsystemet. Ved samtidige skrivninger til samme id vinder den sidste omdøbning.

storh tømmer og fsync'er filhandles før omdøbning eller afslutning af tilføjelse og forsøger at fsync'e overordnede mapper efter atomiske omdøbninger. Holdbarhed ved strømsvigt afhænger stadig af, om det underliggende filsystem og monteringsindstillingerne overholder disse synkroniseringer.