Storh
Vispirms failos glabāti ieraksti ar PHP: JSONC dokumenti, tikai pievienojami segmentēti žurnāli un žurnālā balstītas rindas ar UUIDv7 ID.
composer require storh/storhJaunākais laidiens v0.5.2 MIT PHP 8.2+
$pages = $docs
->query()
->where('kind')->eq('page')
->orderBy('title')
->limit(20)
->get();Praksē
Ātrais sākums divās daļās: dokuments krātuves saknes mapē, pēc tam žurnāla ieraksts un rindas darbs līdzās.
Viena saknes mape, trīs dzinēji
StorageRoot::resolve() normalizē pamata mapi un nosaukumvietu, izveidojot saknes mapi, un katrs dzinējs pirmajā lietošanas reizē tajā izveido savu mapi.
Katrs dzinējs atgriež StorageRecord objektus ar id() un data(). Rinda pievieno katru darba paņemšanu un pabeigšanu savam notikumu žurnālam.
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 dokumentu krātuve
Viens JSONC fails katram ierakstam, UUIDv7 ID, sadalīšana segmentos pēc divām rakstzīmēm no UUID pēdējās daļas, atomiska aizstāšana un straumējoši lauku filtri.
Segmentēts žurnāls
Tikai pievienojami segmenti ar prefiksā norādītu JSON rindu garumu un kontrolsummu, retināti indeksi, nolasīšana ar kursoru un laika diapazonā, atkopšana pēc avārijas un blīvēšana.
Žurnāla rinda
Darbi pāriet no gaidīšanas stāvokļa uz apstrādi un pēc tam uz pabeigtu stāvokli, izmantojot kompaktus, tikai pievienojamus rindas notikumus.
UUIDv7 ieraksti
Kārtojami ID ar laika informāciju nodrošina stabilus kursorus, ierobežotu apjomu skenēšanu un segmentēšanai piemērotus glabāšanas ceļus.
Atomiska ierakstīšana
Pagaidu failu ierakstīšana un atomiska pārdēvēšana saglabā ierakstu veselumu. Ja rakstītājs avarē, nākamajā atvēršanas reizē tiek iztīrīti tā bāreņu pagaidu faili.
Nepilna ieraksta atkopšana
Segmentu nolasīšanas laikā tiek pārbaudīti garuma un kontrolsummas lauki; atkopšanas laikā tiek saīsinātas nepilnas rindu beigas.
Vispirms faili
Nav vajadzīgs datubāzes serveris, ietvara adapteris vai Composer izpildlaika pakotnes; izsaucēji norāda mapi.
Nolasīšana ar JSONC
Ierakstu failos var būt komentāri un noslēdzošie komati. storh ieraksta kompaktu vienas rindas JSON, tāpēc komentāri saglabājas līdz nākamajai ierakstīšanas reizei.
Vaicājumu veidotājs
Plūstoši vaicājumi, piemēram, where('status')->in([...]) DocStore un SegmentedLog; DocStore izmanto sekundāros indeksus, ja tie ir pieejami.
Sekundārie indeksi
Vienādības, unikālie un diapazona indeksi tiek glabāti failos līdzās kolekcijai, atvasināti no ierakstiem un jebkurā brīdī atjaunojami.
Shēmas
Neobligātas kolekciju shēmas validē katru ierakstīšanas darbību un deklarē laukus, kam izveido indeksus.
SQL spogulis
Pārsūtiet kolekcijas uz SQLite vai MySQL savienošanai, meklēšanai un pārskatiem, kamēr faili paliek kanoniski. Nepieciešams ext-pdo vai ext-mysqli tikai lietošanas laikā.
Kāpēc Storh
Mape, nevis serveris
Norādiet pamata mapi, un storh tajā ierakstīs datus. Nepieciešams PHP 8.2 un ext-json; nav vajadzīgas Composer izpildlaika pakotnes vai ietvara adapteris.
Viena ieraksta struktūra, trīs izkārtojumi
Dokumenti, žurnāli un rindas glabā UUIDv7 ID un datu masīvu. Izvēlieties diska izkārtojumu atbilstoši slodzei un glabājiet visus trīs vienā saknes mapē.
Pārbaudes, ko varat palaist
verify() pārbauda indeksus un žurnāla stāvokli, pilnībā skenējot failus. repair() ievieto karantīnā bojātos ierakstus un saīsina nepilnīgos žurnāla ierakstus, bet CLI izvada JSON cron darbiem un darbspējas pārbaudēm.
Veiktspējas mērījumi ar norādītu konfigurāciju
README publicē mediānas, kas noteiktas katram dzinējam ar 50,000 ierakstiem, izmantojot Apple M1 Pro un PHP 8.5; piemēram, tieša nolasīšana aizņem 5.6 µs. Katrā pārbaudē visas rakstīšanas darbības tiek sinhronizētas ar disku, tāpēc rakstīšanas ātrums ir atkarīgs no failu sistēmas.
Salīdzinājums ar
storh ir vispirms failos balstīta krātuve, nevis relāciju vaicājumu dzinējs, tāpēc šie rīki veic dažus uzdevumus, ko tā neatbalsta.
| Rīks | Piemērots | Atšķirība no Storh |
|---|---|---|
| SQLite | PiemērotsPašpietiekams SQL dzinis vienā failā ar serializējamām ACID transakcijām, kas saglabājas arī pēc programmas avārijas vai strāvas padeves pārtraukuma. Dokumentācijā tas piedāvāts kā aizstājējs ad hoc datu failiem. | Atšķirība no Storhstorh katram ierakstam izmanto atsevišķu JSON failu, un tā kodolam nav vajadzīgs PDO draiveris. Tas neatbalsta vairāku ierakstu transakcijas, un dokumentācija šādu darbu iesaka uzticēt pilnvērtīgai datubāzei. Kolekcijas var nosūtīt uz SQLite savienojumiem un pārskatiem, kamēr faili paliek kanoniskais datu avots. |
| MySQL | PiemērotsRelāciju datubāze, ko apkalpo daudzpavedienu SQL serveris, ar klientprogrammām un bibliotēkām, administrēšanas rīkiem un plašu API klāstu. | Atšķirība no Storhstorh darbojas PHP procesā, izmantojot direktoriju, tāpēc nav jāuztur serveris. Savienojumiem, meklēšanai un pārskatiem kolekcijas tiek atspoguļotas MySQL, arī izmantojot esošu mysqli savienojumu, un faili paliek patiesības avots. |
| SleekDB | PiemērotsPlakano failu dokumentu datubāze, kas rakstīta PHP, bez trešo pušu atkarībām un glabā datus bez shēmas kā vienkāršus JSON failus. Tās vaicājumu API ietver savienojumus, teksta meklēšanu, group by un having, kā arī filtrus ligzdotām īpašībām. | Atšķirība no Storhstorh apvieno dokumentu krātuvi ar tikai papildināmu segmentētu žurnālu un uz žurnālu balstītu rindu vienā saknes direktorijā, kā arī izpilda fsync katram ierakstam, pirms paziņo, ka tas saglabāts. Savienojumi nav iekļauti storh; to vajadzībām kolekcijas tiek nosūtītas uz SQLite vai MySQL. |
Jautājumi un atbildes
Īsas atbildes no Storh dokumentācijas.
Jā. DocStore serializē izmaiņas ar kolekcijas līmeņa rakstīšanas slēdzeni, un vienlaicīgiem ierakstiem ar vienu un to pašu ID uzvar pēdējā pārdēvēšana. Rindas uzdevumu paņemšanas laikā tiek turēta rindas slēdzene, tāpēc divi darbinieki nepaņems vienu un to pašu gaidošo uzdevumu.
Jā. Lasīšana pieļauj komentārus un beigu komatus, taču nākamā put() darbība ar šo ID pārraksta failu kompaktā JSON formātā un tos izmet. TRUST kešatmiņas režīmā izmaiņas failos ārpus storh netiek konstatētas.
Pēc ID veiktā punktlasīšana paliek ātra, kamēr failu sistēma spēj apstrādāt failu skaitu. Neindeksētu DocStore lauku skenēšana kļūst lēnāka, kad ierakstu skaits pārsniedz aptuveni 10k, tāpēc deklarējiet indeksus laukiem, pēc kuriem filtrējat. Segmentētā žurnāla skenēšana un diapazonu lasīšana labi darbojas līdz aptuveni 1M ierakstu.
Ieraksti tiek sinhronizēti ar fsync un publicēti, izmantojot atomāru pārdēvēšanu; atkārtoti atverot žurnālu vai rindu, nepilnīgie beigu dati tiek apgriezti līdz pēdējam apstiprinātajam notikumam. Datu saglabāšana strāvas padeves zuduma gadījumā joprojām ir atkarīga no tā, vai failu sistēma un montēšanas opcijas ievēro šīs sinhronizācijas.
Nē. Nosūtiet kolekcijas uz SQLite vai MySQL ar SqlMirror, lai izmantotu savienojumus, meklēšanu un pārskatus. Vairāku ierakstu atomāra rakstīšana paliek pilnvērtīgas datubāzes ziņā, kas kalpo par sistēmas ierakstu avotu.
Nē. Queue nav vispārīga ierakstu krātuve, un uzdevuma dati tiek atmesti, kad uzdevums ir izpildīts.
Sāciet ar ātro sākšanas pamācību, pēc tam sadaļā “Dziņa izvēle” piemeklējiet DocStore, SegmentedLog vai Queue savai slodzei.