Storh
Záznamy založené na souborech pro PHP: dokumenty JSONC, segmentované protokoly pouze pro přidávání a fronty založené na protokolech s id UUIDv7.
composer require storh/storhNejnovější vydání v0.5.2 MIT PHP 8.2+
$pages = $docs
->query()
->where('kind')->eq('page')
->orderBy('title')
->limit(20)
->get();V praxi
Rychlý začátek ve dvou částech: dokument v kořenovém adresáři úložiště a vedle něj položka protokolu a úloha fronty.
Jeden kořen, tři enginy
StorageRoot::resolve() normalizuje základní adresář a jmenný prostor na kořen a každý engine při prvním použití vytvoří vlastní adresář.
Každý engine vrací objekty StorageRecord s id() a data(). Fronta přidává každé převzetí i dokončení do svého protokolu událostí.
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());
}Úložiště dokumentů JSONC
Jeden soubor JSONC na záznam, id UUIDv7, dělení do shardů podle dvou znaků z poslední skupiny UUID, atomická náhrada a streamové filtry polí.
Segmentovaný protokol
Segmenty pouze pro přidávání s řádky JSON opatřenými délkou a kontrolním součtem, řídké indexy, čtení podle kurzoru a časového rozsahu, obnova po pádu a kompakce.
Fronta protokolu
Úlohy přecházejí mezi stavy čekající, zpracovávaná a dokončená pomocí kompaktních událostí fronty, které se pouze přidávají.
Záznamy UUIDv7
Tříděná id adresovatelná podle času pro stabilní kurzory, omezené průchody a cesty úložiště vhodné pro sharding.
Atomické zápisy
Zápisy do dočasných souborů a atomická přejmenování zachovávají úplnost záznamů. Po pádu zapisujícího procesu při dalším otevření dojde k odstranění osiřelých dočasných souborů.
Obnova po neúplném zápisu
Při čtení segmentů se ověřují pole délky a kontrolního součtu; obnova zkrátí neúplné koncové řádky.
Nejprve soubory
Bez databázového serveru, adaptéru frameworku a běhových balíčků Composer; volající předávají adresář.
Čte JSONC
Soubory záznamů mohou obsahovat komentáře a čárky na konci. Zápisy storh ukládají kompaktní jednorádkové JSON, takže komentáře zůstanou zachovány až do dalšího zápisu.
Tvůrce dotazů
Plynulé dotazy, například where('status')->in([...]), v DocStore a SegmentedLog; DocStore používá sekundární indexy, pokud jsou k dispozici.
Sekundární indexy
Indexy rovnosti, jedinečnosti a rozsahů uložené jako soubory vedle kolekce, odvozené ze záznamů a kdykoli znovu sestavitelné.
Schémata
Volitelná schémata kolekcí ověřují každý zápis a určují, která pole se indexují.
SQL Mirror
Odešlete kolekce do SQLite nebo MySQL kvůli spojování, vyhledávání a reportingu, zatímco soubory zůstávají kanonické. Rozšíření ext-pdo nebo ext-mysqli jsou potřeba pouze při použití.
Proč Storh
Adresář místo serveru
Předáte základní adresář a storh do něj zapisuje. Potřebuje PHP 8.2 a ext-json, bez běhových balíčků Composer a adaptéru frameworku.
Jeden tvar záznamu, tři rozložení
Dokumenty, protokoly i fronty ukládají id UUIDv7 a pole dat. Zvolte rozložení na disku podle úlohy a všechny tři uchovávejte pod jedním kořenem.
Kontroly, které můžete spustit
verify() porovnává indexy a stav protokolu s úplným průchodem souborů. repair() umisťuje poškozené záznamy do karantény a zkracuje neúplné konce protokolů; CLI vypisuje JSON pro úlohy cron a kontroly stavu.
Benchmarky včetně nastavení
README zveřejňuje mediány pro 50,000 záznamů na engine, naměřené na Apple M1 Pro s PHP 8.5; například čtení jednoho záznamu podle klíče trvá 5.6 µs. Každý zápis v těchto měřeních používá fsync, takže rychlost zápisu závisí na souborovém systému.
Srovnání
storh je úložiště založené na souborech, nikoli relační dotazovací engine, a proto tyto nástroje zvládají některé úlohy, které nepokrývá.
| Nástroj | Vhodné pro | Rozdíl oproti Storh |
|---|---|---|
| SQLite | Vhodné proSamostatný engine SQL v jediném souboru se serializovatelnými transakcemi ACID, které obstojí i při pádu programu nebo výpadku napájení. Dokumentace jej představuje jako náhradu za nahodilé datové soubory. | Rozdíl oproti Storhstorh uchovává jeden soubor JSON na záznam a jeho jádro nepotřebuje ovladač PDO. Nepodporuje transakce napříč více záznamy; dokumentace pro tyto úlohy doporučuje skutečnou databázi. Kolekce může odesílat do SQLite kvůli spojování a reportingu, přičemž soubory zůstávají kanonické. |
| MySQL | Vhodné proRelační databáze obsluhovaná vícevláknovým serverem SQL, s klientskými programy a knihovnami, nástroji pro správu a širokou škálou API. | Rozdíl oproti Storhstorh běží uvnitř procesu PHP nad adresářem, takže není třeba provozovat server. Pro spojování, vyhledávání a reporting zrcadlí kolekce do MySQL, a to i přes existující připojení mysqli; soubory zůstávají zdrojem pravdy. |
| SleekDB | Vhodné proDokumentová databáze s plochými soubory v PHP bez závislostí třetích stran, která ukládá data bez schématu jako prosté soubory JSON. Její dotazovací API zahrnuje spojování, textové vyhledávání, group by a having i filtry vnořených vlastností. | Rozdíl oproti Storhstorh spojuje úložiště dokumentů se segmentovaným protokolem pouze pro přidávání a frontou založenou na protokolu pod jedním kořenem a každý zápis synchronizuje pomocí fsync ještě před potvrzením uložení. Spojování není součástí storh; kolekce k tomu odesílá do SQLite nebo MySQL. |
Otázky a odpovědi
Stručné odpovědi z dokumentace Storh.
Ano. DocStore serializuje změny pomocí zámku na úrovni kolekce a při souběžných zápisech stejného id vítězí poslední přejmenování. Převzetí úlohy ve frontě drží zámek fronty, takže dva pracovní procesy nepřevezmou stejnou čekající úlohu.
Ano. Čtení přijímá komentáře a čárky na konci, ale další put() daného id přepíše soubor jako kompaktní JSON a odstraní je. V režimu mezipaměti TRUST se změny souborů provedené mimo storh nezjišťují.
Čtení podle id zůstává rychlé, dokud souborový systém zvládá daný počet souborů. Neindexované průchody polí v DocStore se zpomalují přibližně nad 10k záznamů, proto indexujte pole, podle kterých filtrujete. Průchody segmentovaného protokolu a čtení rozsahů zvládají zhruba až 1M záznamů.
Zápisy se synchronizují pomocí fsync a zveřejňují atomickým přejmenováním; při opětovném otevření protokolu nebo fronty se neúplné konce zkrátí na poslední potvrzenou událost. Odolnost proti výpadku napájení stále závisí na tom, zda souborový systém a volby připojení tyto synchronizace respektují.
Ne. Kvůli spojování, vyhledávání a reportingu odešlete kolekce do SQLite nebo MySQL pomocí SqlMirror. Atomické zápisy napříč více záznamy patří do skutečné databáze, která slouží jako systém evidence.
Ne. Fronta není univerzální úložiště záznamů a datová část úlohy se po dokončení zahodí.
Začněte rychlým začátkem a potom v části Výběr enginu přiřaďte DocStore, SegmentedLog nebo Queue ke své úloze.