Ugrás a tartalomhoz

Motorok

Motorválasztás

Mindhárom motor ugyanazt tárolja: egy UUIDv7 azonosítót és egy adattömböt, de másképp rendezi el őket a lemezen. Ez az elrendezés határozza meg, mire alkalmasak az egyes motorok:

DocStore SegmentedLog Queue
Lemezen rekordonként egy JSONC fájl, UUID-farok szerinti particionálással csak hozzáfűzhető szegmensek, hossz- és ellenőrzőösszeg-előtaggal ellátott JSON sorokkal, valamint jegyzékkel egy csak hozzáfűzhető eseménynapló
Írás atomi fájlcserével rekordként ellenőrzőösszeggel védett hozzáfűzések; a felülírások és törlések új bejegyzést fűznek hozzá, a helyet a(z) compact() szabadítja fel ellenőrzőösszeggel védett hozzáfűzés minden sorsoreseménynél
Olvasás get() azonosító alapján, indexelt lekérdezések kurzor- és időtartomány-pásztázás, get() az állapotindex alapján claim() sorba állítási sorrendben
Ideális pontszerű olvasásokhoz és indexelt keresésekhez bármilyen gyűjteményméretnél sok hozzáfűzésű adatfolyamokhoz, körülbelül 1M rekordig tartós munkafeladatok folyamatok közötti kiosztásához
Hátrány nem indexelt mezők pásztázása körülbelül 10k rekord felett gyakori, egyrekordos átírások (a régi verziók a tömörítésig helyet foglalnak) nem általános rekordtár; a hasznos adatok a feladat befejezése után törlődnek

A(z) DocStore és a(z) SegmentedLog ugyanazt a gördülékeny lekérdezési API kezelőfelületet használja: ugyanaz a where() lánc mindkét motoron fut, és csak a végrehajtás tér el. A(z) DocStore a másodlagos indexeiből is tud választ adni, míg a(z) SegmentedLog szegmensek pásztázása közben szűr. A(z) Queue igénylésalapú, nem kérdezhető le: a feldolgozók az következő feladatot claim(), nem pedig szűrik a feladatokat.

Ökölszabályok:

  • Egyenként lekért, frissített vagy törölt, illetve mező alapján lekérdezhető rekordok: DocStore. Adjon hozzá indexeket a szűréshez használt mezőkhöz.
  • Többnyire hozzáfűzött, majd sorrendben vagy időablak szerint visszaolvasott események vagy verziók: SegmentedLog.
  • A létrehozóktól a feldolgozó folyamatokhoz továbbított feladatok: Queue. A lefoglalás és a befejezés több folyamat között is biztonságos, a claimMany()/completeMany() pedig megosztja a zárolás és az fsync költségét.
  • Összekapcsolások, keresés vagy jelentéskészítés bármely gyűjteményen: adjon hozzá egy SQL tükröt. A fájlok maradnak a hiteles források; a tükör újraépíthető vetület SQLite vagy MySQL formátumban.

A motorok kombinálhatók: csak a gyökérkönyvtárat osztják meg, így egy alkalmazás ugyanazon tárolási gyökér alatt tarthatja a tartalmat egy DocStore-ban, az auditnaplót egy SegmentedLog-ban, a háttérfeladatokat pedig egy Queue-ban.

DocStore

A DocStore tartós rekordok közvetlen lekérésére és egyszerű bejárására szolgál. Rekordonként egy JSONC fájlt ír:

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

A rekordfájlok elosztása a UUID utolsó karakterei alapján történik, így a UUIDv7 írási terhelési csúcsok több könyvtár között oszlanak meg:

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

SegmentedLog

A SegmentedLog hozzáfűzés-intenzív rekordokhoz, kurzoros olvasáshoz és időtartomány szerinti olvasáshoz készült. A rekordok az aktív szegmensbe kerülnek, rekordonként egy sorban, <byte-length>\t<xxh32>\t<json> formátumban (lásd: Atomi működés). A szegmensfájlok kiterjesztése .ndjson, de a hossz- és ellenőrzőösszeg-előtag miatt a hagyományos NDJSON-eszközök nem tudják olvasni őket; a rekordokat a stream() vagy a lekérdezésépítő segítségével olvassa vissza. A megtelt szegmensek lezárt szegmensekké válnak, ritka indexekkel.

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

Sor

A Queue nagy áteresztőképességű, tartós feladatsorokhoz készült. A sorba állítás, lefoglalás, befejezés, újrasorba állítás és törlés csak hozzáfűzött eseményeket ír a queue.log fájlba; a sor állapota a sor megnyitásakor kerül visszajátszásra a memóriába. A kötegelt metódusok sok feladat között osztják el a zárolás és a kiürítés költségét. A napló minden eseménnyel növekszik; a stats() jelenti az aktuális méretét bájtban.

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

Tartósság és párhuzamosság

A storh atomi átnevezéssel teszi közzé a fájlírásokat a célkönyvtáron belül. Újranyitáskor és a repair() eltávolítja azokat az elhagyott ideiglenes fájlokat, amelyek tulajdonos folyamata már leállt, az aktív írók ideiglenes fájljait viszont érintetlenül hagyja. Az írójelölők révén az ellenőrzés állandó idejű, így a tároló megnyitásakor csak összeomlás után vizsgálja át a gyűjteményt.

A SegmentedLog és a Queue hosszal és ellenőrzőösszeggel védett naplósorokat ír. Újranyitáskor vagy javításkor a rendszer a részlegesen írt napló végét az utolsó véglegesített eseménynél csonkolja, majd a tartós naplótartalomból újraépíti a memóriabeli állapotot. A napló- és sorírásokat fájlrendszer-zárolások sorosítják.

A DocStore módosításait gyűjteményszintű írási zárolás sorosítja, így a rekordfájlok és a másodlagos indexek egyetlen konzisztenciahatár mentén frissülnek a folyamatok között. A különböző rekordazonosítókra irányuló párhuzamos írások biztonságosak, ha a fájlrendszer biztosítja az atomi átnevezés feltételeit. Ugyanazon azonosító egyidejű írásai közül az utoljára átnevezett érvényesül.

A storh kiüríti és fsync-kel szinkronizálja a fájlleírókat az átnevezés vagy a hozzáfűzés befejezése előtt, és az atomi átnevezések után megkísérli az fsync-et a szülőkönyvtárakon. Az áramkimaradással szembeni tartósság továbbra is attól függ, hogy az alapul szolgáló fájlrendszer és a csatolási beállítások betartják-e ezeket a szinkronizálásokat.