2
« kdy: 01. 12. 2019, 10:24:08 »
Mam sluzbu "writer" ktora loguje spravy z roznych producentov. Kazdy producent ma sekvencne uint64 id pre svoje spravy. Ked sprava dorazi do tejto logovacej sluzby tak sa musi skontrolovat ze dana sekvencia pre daneho producenta uz nebola zapisana a je konsekutivna voci uz zapsianymi spravam, nasledne sa sprava zapise a prideli sa jej globalne sekvencne id.
Cize v praxi by to vyzeralo ako:
1:foo:1
2:foo:2
3:baz:1
4:bar:1
5:foo:3
6:bar:2
7:baz:2
8:bar:3
Aktualne to zapisujem do kdvdb, avsak do budnca sa obavam toho ze ta db, ako jeden subor, bude prilis velka. Je to b+tree a vyuziva mmap ale i tak nechcem skoncit s TB/PB suborom.
Preto by som chcel prejst na "manualne" logovanie do AOL suborov ktore by rotovali ked dosiahnu urcitu velkost. Tym znizim riziko poskodenia jedneho velkeho suboru a zalohovanie sa tak taktiez znacne ulahci.
Teraz ide o to ze tato sluzba je len na zapis sprav, avsak spravy sa budu aj citat(vo vysokom objeme) a na to su ine sluzby ktore sluzia prave na tento ucel(princip CQRS). Takze z tejto zapisovacej sluzby musim aj vediet citat spravy a synchronizovat ich do "readerov" aby ich mohli servirovat klientom.
"Reader" si len uchovava id globalnej sekvencie ktoru naposledy prijal takze z "masteru" si stiahne iba nove spravy. Cize ked budem pouzivat novy system zapisu do tychto mensich suborov tak musim aj vediet otvorit subor ktory obsahuje spravy ktore reader este nezosynchronizoval.
Cize "master" si musi sledovat lokalne sekvencie pre kazdeho producenta aby zapisoval iba nove spravy a ignoroval opakovane spravy a taktiez aby nepreskocil nejaku spravu(tzn. 1,2,3,6) a taktiez musi uchovavat globalnu sekvenciu.
Realne ide o malo dat, prakticky iba:
8 bytov pre uint64 globalnej sekvencie a mapa [string]uint64 pre sledovanie "lokalnych" sekvencii pre jednotlivych producentov.
Teraz ide o to, kde a ako uchovavat tieto indexy a ako sa dostat ku spravam ktore "reader" este nesynchronizoval.
Napada ze by som mohol pouzivat kvdb kde by som si uchovaval vyssie spomenute + byte index a nazov suboru pre kazdu spravu, podla coho viem potom pre readera otvorit konkretny subor a naseekovat na konkretny bajt so spravami ktore este nema a poslat mu ich. Problem tohto riesenia je ze mi takto vznikaju dve oddelene transakcie. Jedna je zapis samotnych sprav do suborov, druha je ukladanie tychto indexov. Ak by sa stalo ze jedna operacia neprejde, tak mi vznikne inkonzistentny stav.
Dalsia varianta je len zapisovat na koniec aktivneho suboru metadata(globalny index + lokalne sekvencie) a drzat ich v pameti pre rychle vyhodnotenie. Problem je ze nemozem uchovavat pointery pre jednotlive spravy nakolko by slo o privela dat pre taketo uchovanie v aktivnom subore a musel by som vediet ktory subor otvorit pre synchronizovanie readerov podla globalnej sekvencie, cize nazvy suborov by museli byt presne rozsahy sprav(napr 0-5000.dat, 5001-10000.dat, ..) a uz nie podla velkosti dat samotnych co by sposobilo inkonzistentne velkosti tychto suborov. Avsak ak viem podla sekvencie identifikovat subor tak potom ho len preskenovat a najst prvu spravu na sycnhrzonizovanie nie je az tak narocne.
Takze by ma zaujimalo ako by ste navrhli riesenie pre takuto situaciu?