
BÀsta community, denna artikel kommer att handla om effektiv lagring och hantering av hundratals miljoner smÄ filer. För nÀrvarande presenteras en slutgiltig lösning för POSIX-kompatibla filsystem med fullstÀndig stöd för lÄsningar, inklusive klusterlÄsningar, och verkar till och med vara utan tillfÀlliga lösningar.
DÀrför har jag skrivit en egen specialiserad server för detta ÀndamÄl.
Under implementeringen av denna uppgift lyckades vi lösa det grundlÀggande problemet och samtidigt uppnÄ en betydande besparing i diskutrymme och RAM, som vÄr klusterfilsystem slukade. En sÄdan mÀngd filer Àr skadlig för vilket klusterfilsystem som helst.
Idén Àr enkel:
Med andra ord, smÄ filer laddas upp via servern, de sparas direkt i ett arkiv och lÀses ocksÄ dÀrifrÄn, medan stora filer placeras bredvid. Schema: 1 mapp = 1 arkiv, vilket ger oss flera miljoner arkiv med smÄ filer, istÀllet för flera hundra miljoner filer. Och allt Àr fullt genomfört utan skript och utan att sprida filer i tar/zip-arkiv.
Jag ska försöka sammanfatta det kort, jag ber om ursÀkt pÄ förhand om inlÀgget blir omfattande.
Allt började med att jag inte kunde hitta en lÀmplig server i vÀrlden som kunde spara data som mottagits via HTTP-protokollet direkt i arkiv, utan bristerna som kÀnnetecknar vanliga arkiv och objektlager. Anledningen till sökandet var den vÀxande Origin-klustret med 10 servrar, dÀr det redan hade samlats 250 000 000 smÄ filer, och vÀxttrenden sÄg inte ut att avta.
För dem som inte gillar att lÀsa artiklar och föredrar kortare dokumentation:
och .
Och docker samtidigt, just nu finns det bara ett alternativ med nginx inuti för sÀkerhets skull:
docker run -d --restart=always -e host=localhost -e root=\/var\/storage
-v \/var\/storage:\/var\/storage --name wzd -p 80:80 eltaline\/wzdNĂ€sta:
Om antalet filer Ă€r mycket stort krĂ€vs betydande resurser, och det mest frustrerande Ă€r att en del av dem gĂ„r till spillo. Till exempel, vid anvĂ€ndning av ett klusterfilssystem (i det hĂ€r fallet â MooseFS), upptar en fil, oavsett dess faktiska storlek, alltid minst 64 KB. Det innebĂ€r att för filer med storlekar pĂ„ 3, 10 eller 30 KB krĂ€vs 64 KB pĂ„ disken. Om det finns en kvarts miljard filer, förlorar vi mellan 2 och 10 terabyte. Det Ă€r inte möjligt att skapa nya filer i oĂ€ndlighet, eftersom MooseFS har en begrĂ€nsning: högst 1 miljard med en replik av varje fil.
Allt eftersom antalet filer ökar, behövs mycket RAM för metadata. Dessutom bidrar frekventa stora dumpningar av metadata till slitage pÄ SSD-lagringsenheter.
Server wZD. Vi ordnar upp pÄ diskarna.
Servern Àr skriven i Go. Först och frÀmst behövde jag minska antalet filer. Hur gör man detta? Genom att arkivera, men i detta fall utan kompression, eftersom mina filer Àr en serie av komprimerade bilder. Till min hjÀlp kom BoltDB, Àven om jag var tvungen att ÄtgÀrda vissa brister, vilket Àr dokumenterat.
IstÀllet för en kvarts miljard filer kvarstÄr det bara 10 miljoner Bolt-arkiv i mitt fall. Om jag haft möjlighet att Àndra den nuvarande filstrukturen för katalogerna, skulle det kanske ha kunnat minskas till ungefÀr 1 miljon filer.
Alla smĂ„filer packas i Bolt-arkiv, som automatiskt fĂ„r namn efter de kataloger dĂ€r de ligger, medan alla stora filer förblir i nĂ€rheten av arkiven; det Ă€r meningslöst att paketera dem, detta Ă€r konfigurerbart. SmĂ„ â arkivera, stora â lĂ€mna oförĂ€ndrade. Servern fungerar transparent för bĂ„de och.
Arkitekturen och egenskaperna hos servern wZD.

Servern körs under operativsystemen Linux, BSD, Solaris och OSX. Jag har testat endast för AMD64-arkitektur under Linux, men den bör ocksÄ fungera för ARM64, PPC64, MIPS64.
Huvudfunktioner:
- Multithreading;
- Multiserver, vilket sÀkerstÀller driftsÀkerhet och lastbalansering;
- Maximal transparens för anvÀndaren eller utvecklaren;
- Stödda HTTP-metoder: GET, HEAD, PUT och DELETE;
- Hantera beteende vid lÀsning och skrivning via klienthuvuden;
- Stöd för flexibelt konfigurerbara virtuella vÀrdar;
- Stöd för CRC-integritet för data nÀr de skrivs/lÀses;
- Halvdynamiska buffrar för minimal minnesanvÀndning och optimal nÀtverksprestanda;
- Fördröjd datakomprimering;
- Dessutom erbjuds den flerdelade arkivprogrammet wZA för migrering av filer utan att stÀnga av tjÀnsten.
Verklig erfarenhet:
Jag har utvecklat och testat en server och en arkiverare med verkliga data under en ganska lÄng tid, och nu fungerar den framgÄngsrikt pÄ ett kluster som inkluderar 250 000 000 smÄ filer (bilder), som Àr belÀgna i 15 000 000 kataloger pÄ separata SATA-diskar. Klustret av 10 servrar fungerar som en origin-server, installerad bakom ett CDN-nÀtverk. För dess drift anvÀnds 2 Nginx-servrar + 2 wZD-servrar.
För dem som bestÀmmer sig för att anvÀnda denna server Àr det klokt att planera katalogstrukturen innan anvÀndning, om det Àr tillÀmpligt. Jag vill genast pÄpeka att servern inte Àr avsedd för att stoppa allt i 1 Bolt-arkiv.
Prestandatestning:
Ju mindre storleken pÄ den arkiverade filen, desto snabbare utförs GET- och PUT-operationerna med den. Vi jÀmför den totala skrivtiden frÄn HTTP-klienten till vanliga filer och Bolt-arkiv, liksom lÀsningen. JÀmförelsen görs med filer av storlekarna 32 KB, 256 KB, 1024 KB, 4096 KB och 32768 KB.
Vid arbete med Bolt-arkiv kontrolleras dataintegriteten för varje fil (CRC anvĂ€nds), och bĂ„de före och efter skrivning sker en lĂ€sning och berĂ€kning i farten, vilket naturligtvis medför fördröjningar, men viktigast av allt â dataskydd.
Prestandatetterna utförde jag pÄ SSD-lagringsenheter, eftersom tester pÄ SATA-diskar inte visar nÄgon tydlig skillnad.
Diagram över testresultaten:


Som syns Àr skillnaden i lÀs- och skrivtid mellan arkiverade och icke-arkiverade filer liten för smÄ filer.
En helt annan bild fÄr vi vid test av lÀsning och skrivning av filer av storleken 32 MB:

Skillnaden i tid mellan lÀsning av filer ligger inom 5-25 ms. För skrivning Àr situationen sÀmre, med en skillnad pÄ cirka 150 ms. Men i detta fall krÀvs det inte att ladda upp stora filer, det finns helt enkelt ingen mening med det, de kan leva separat frÄn arkiven.
*Tekniskt sett kan denna server Àven anvÀndas för uppgifter som krÀver NoSQL.
Huvudmetoder för arbete med wZD-servern:
Uppladdning av en vanlig fil:
curl -X PUT --data-binary @test.jpg http://localhost/test/test.jpgUppladdning av en fil i Bolt-arkiv (om serverparametern fmaxsize, som bestÀmmer den maximala filstorleken som kan inkluderas i arkivet, inte överskrids; om den överskrids, laddas filen upp som vanligt bredvid arkivet):
curl -X PUT -H "Archive: 1" --data-binary @test.jpg http://localhost/test/test.jpgNedladdning av fil (om det finns filer med samma namn pÄ disken och i arkivet, ges prioritet till den oarkiverade filen som standard):
curl -o test.jpg http://localhost/test/test.jpgNedladdning av fil frÄn Bolt-arkivet (tvingad):
curl -o test.jpg -H "FromArchive: 1" http://localhost/test/test.jpgBeskrivning av andra metoder finns i dokumentationen.
Servern stöder för nÀrvarande endast HTTP-protokollet, HTTPS fungerar inte. POST-metoden stöds inte heller (detta har Ànnu inte beslutats om det behövs eller inte).
Den som grÀver i kÀllkoden kommer att upptÀcka en godisbit, som inte alla gillar, men jag har inte kopplat huvudkoden till webbframework-funktionerna, förutom avbrottshanteraren, sÄ jag kan snabbt skriva om den pÄ nÀstan vilken motor som helst.
ToDo:
- Utveckling av egen replikator och distributör + geo för möjligheter att anvÀnda i stora system utan klusterfilsystem (Allt pÄ vuxen nivÄ)
- Möjlighet till full reversibel ÄterstÀllning av metadata vid total förlust (vid anvÀndning av distributören)
- Nativt protokoll för möjligheten att anvÀnda permanenta nÀtverksanslutningar och drivrutiner för olika programmeringssprÄk
- Utökade möjligheter att anvÀnda NoSQL-komponenten
- Kompressering av olika typer (gzip, zstd, snappy) för filer eller vÀrden inuti Bolt-arkiven och för vanliga filer
- Kryptering av olika typer för filer eller vÀrden inuti Bolt-arkiven och för vanliga filer
- Fördröjd serverbaserad videokonvertering, inklusive pÄ GPU
Det var allt, jag hoppas att denna server kommer att vara till nytta för nÄgon, BSD-3 licens, dubbel upphovsrÀtt, eftersom utan företaget jag arbetar pÄ skulle jag inte ha skrivit servern. Jag Àr utvecklaren i ental. Jag skulle vara tacksam för upptÀckta buggar och funktionsförfrÄgningar.
KĂ€lla: habr.com
