Triky pri práci s veľkým počtom malých súborov

Nápad na tento článok sa zrodil spontánne z diskusie v komentároch k článku "Niečo o inode".

Triky pri práci s veľkým počtom malých súborov

Ide o to, že vnútornou špecifikou fungovania našich služieb je uchovávanie obrovského množstva drobných súborov. V súčasnosti máme zhruba stovky terabajtov týchto údajov. A narazili sme na niektoré zrejmé aj menej zrejmé prekážky, ktorými sme úspešne prešli.

Preto sa delím o našu skúsenosť, možno to niekomu pomôže.

Problém prvý: "Na zariadení nie je miesto"

Ako bolo spomenuté v predchádzajúcom článku, problém spočíva v tom, že vofilesysteme sú voľné bloky, ale inody sa minuli.

Skontrolovať počet použitých a voľných inode je možné príkazom df -ih:

Triky pri práci s veľkým počtom malých súborov

Nebudem rekapitulovať článok, ak to zhrniem, na disku sú bloky priamo pre dáta a bloky pre meta-informácie, ktoré sú inody (indexové uzly). Ich počet sa určuje pri inicializácii súborového systému (reč je o ext2 a jeho nástupcoch) a ďalej sa nemení. Vyváženie blokov dát a inode je vypočítané z priemerných údajov, v našom prípade, keď je veľa drobných súborov, by sa mala vyváženie posunúť na stranu inodes — malo by ich byť viac.

V Linuxe už sú predpísané možnosti s rôznymi vyvážením a všetky tieto predpočítané konfigurácie sa nachádzajú v súbore /etc/mke2fs.conf.
Preto pri počiatočnej inicializácii súborového systému cez mke2fs môžete zadať potrebný profil.

Tu je niekoľko príkladov zo súboru:

    small = {
        blocksize = 1024
        inode_size = 128
        inode_ratio = 4096
    }

    big = {
        inode_ratio = 32768
    }

    largefile = {
        inode_ratio = 1048576
        blocksize = -1
    }

Vybrať potrebnú variantu použitia je možné pomocou voľby "-T" pri volaní mke2fs. Môžete tiež ručne zadať požadované parametre, ak nie je k dispozícii hotové riešenie.

Viac podrobností je uvedených v manuáloch pre mke2fs.conf a mke2fs.

V článku vyššie sa nespomenula špeciálna vlastnosť — je možné nastaviť veľkosť bloku dát. Je jasné, že pre veľké súbory má zmysel väčšia veľkosť bloku, pre malé — menšia.

Avšak je potrebné brať do úvahy takú zaujímavú vlastnosť, ako je architektúra procesora.
Razmýšľal som, že pre veľké súbory s fotografiami potrebujem väčšiu veľkosť bloku. Bolo to v domácich podmienkach, na domácom WD súborovom systéme na architektúre ARM. Bez váhania som nastavil veľkosť bloku buď 8k, alebo 16k namiesto štandardných 4k, pričom som najprv zmeral úsporu. A všetko bolo skvelé až do okamihu, keď sa samotný systém prestal dať použiť, pričom disk bol funkčný. Keď som disk vložil do bežného počítača s obyčajným Intel procesorom, dostal som prekvapenie: nepodporovaná veľkosť bloku. Na to sme narazili. Dáta sú, všetko je v poriadku, ale nie je možné ich prečítať. Procesory i386 a podobné nevedia pracovať s veľkosťami bloku, ktoré nie sú v súlade s veľkosťou stránok pamäte, a tá je presne 4k. Takže sme skončili používaním utilít z užívateľského priestoru, všetko bolo pomalé a smutné, ale dáta sme zachránili. Kto má záujem, vyhľadajte názov utility. fuseext2. Morálka: buď premyslieť všetky možnosti vopred, alebo si nehrať na superhrdinu a používať štandardné nastavenia pre domácnosti.

UPD. Podľa pozorovania používateľa berez udržiavam, že pre i386 veľkosť bloku nesmie presiahnuť 4k, ale nemusí byť presne 4k, t.j. sú povolené aj 1k a 2k.

Takže, ako sme riešili problémy.

Po prvé, s problémom sme sa stretli, keď bola viac ako terabajtová disk naplnený dátami a nemohli sme zmeniť konfiguráciu súborového systému.

Po druhé, riešenie bolo potrebné okamžite.

Nakoniec sme dospeli k záveru, že musíme zmeniť rovnováhu, znížiť počet súborov.
Aby sme znížili počet súborov, rozhodli sme sa uložiť súbory do jedného spoločného archívu. Vzhľadom na našu špecifiku sme do jedného archívu ukládali všetky súbory za určitý časový úsek a archivačné úlohy sme vykonávali pomocou cron každej noci.

Vybrali sme zip-archív. V komentároch k predchádzajúcemu článku bol navrhnutý tar, ale s tým je jedna komplikácia: nemá obsah a súbory v ňom sú usporiadané sekvenčne (nie nadarmo sa 'tar' skrátil z 'Tape Archive', dedičstvo páskových pamätí), t.j. ak potrebujete prečítať súbor na konci archívu, musíte prečítať celý archív, pretože neobsahuje posuny pre každý súbor vzhľadom na začiatok archívu. A preto je to pomalá operácia. V zip je to oveľa lepšie: má predpokladaný obsah a posuny súborov v archíve, a čas prístupu k každému súboru nezávisí od jeho umiestnenia. No a v našom prípade sme mohli stanoviť kompresnú možnosť '0', pretože všetky súbory boli už vopred skomprimované v gzip.

Klienti sťahujú súbory cez nginx, a podľa starého API, sa uvádza jednoducho názov súboru, napríklad takto:

http://www.server.com/hydra/20170416/0453/3bd24ae7-1df4-4d76-9d28-5b7fcb7fd8e5

Aby sme mohli na let priamo rozbaliť súbory, našli sme a pripojili modul nginx-unzip-module (https://github.com/youzee/nginx-unzip-module) a nastavili sme dva upstreamy.

Výsledkom bola takáto konfigurácia:

Triky pri práci s veľkým počtom malých súborov

Dva hostitelia mali nastavenia takto:

server {
  listen *:8081;

  location / {
    root      /home/filestorage;
  }
}

server {
  listen *:8082;

  location ~ ^/hydra/(d+)/(
    root      /home/filestorage;
    file_in_unzip_archivefile "/home/filestorage/hydra/$1/$2.zip";
    file_in_unzip_extract "$2/$3";
    file_in_unzip;
  }
}

A konfigurácia upstreamov na vyššom nginx:

upstream storage {
  server server.com:8081;
  server server.com:8082;
}

Ako to funguje:

  • Klient ide na front nginx
  • Front nginx sa snaží poskytnúť súbor z prvého upstreamu, t.j. priamo zo súborového systému
  • Ak súbor neexistuje — snaží sa ho poskytnúť z druhého upstreamu, ktorý sa pokúša nájsť súbor v archíve

Druhá problém: opäť "No space left on device"

To je druhý problém, s ktorým sme sa stretli, keď je v adresári veľa súborov.
Snažíme sa vytvoriť súbor, systém sa sťažuje, že nie je miesto. Zmeníme názov súboru a znovu sa pokúsime ho vytvoriť.

Podarí sa.

Vyzerá to približne takto:

Triky pri práci s veľkým počtom malých súborov

Kontrola inodes nič nedala — voľných je ich dosť.
Kontrola miesta — to isté.
Premýšľali sme, či nie je v adresári príliš veľa súborov, a na to je obmedzenie, ale opäť nie: Maximálny počet súborov na adresár: ~1,3 × 10^20

A predsa súbor možno vytvoriť, ak zmeníte názov.
Záver — problém je v názve súboru.

Ďalšie vyhľadávanie ukázalo, že problém je v hashovacom algoritme pri konštrukcii indexu adresára, pri veľkom počte súborov dochádza ku kolíziám so všetkými vyplývajúcimi následkami. Podrobnejšie si môžete prečítať tu: https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Hash_Tree_Directories

Túto možnosť môžete vypnúť, ale... vyhľadávanie súboru podľa názvu môže byť nepredvídateľne dlhé pri prechode všetkými súbormi.

 tune2fs -O "^dir_index" /dev/sdb3

Vo všeobecnosti to môže fungovať ako dočasné riešenie.

Morálka: veľa súborov v adresári je spravidla zlé. Takto to nerobte.

V takýchto prípadoch sa zvyčajne vytvárajú vnorené adresáre, podľa prvých písmen názvu súboru alebo iných parametrov, napríklad podľa dátumov, vo väčšine prípadov to pomáha.
Ale celkový počet malých súborov je stále zlý, aj keď sú rozdelené do adresárov — potom pozrite prvý problém.

Tretí problém: ako zobraziť zoznam súborov, ak ich je veľa

V našej situácii, keď máme veľa súborov, sa tak či onak stretávame s problémom, ako si pozrieť obsah adresára.

Štandardné riešenie je príkaz ls.
Dobre, pozrime sa, čo dostaneme na 4772098 súboroch:


$ time ls /home/app/express.repository/offercache/ >/dev/null

real	0m30.203s
user	0m28.327s
sys	0m1.876s

30 sekúnd... to je dosť. Hlavný čas ide na spracovanie súborov v užívateľskom priestore, nie na prácu jadra.

Ale existuje riešenie:


$ time find /home/app/express.repository/offercache/ >/dev/null

real	0m3.714s
user	0m1.998s
sys	0m1.717s

3 sekundy. Desakrát rýchlejšie.
Hurá!

UPD.

Ešte rýchlejšie riešenie od užívateľa berez — vypnutie triedenia pre ls


time ls -U /home/app/express.repository/offercache/ >/dev/null
real	0m2.985s
user	0m1.377s
sys	0m1.608s

Štvrtý problém: vysoký LA pri práci so súbormi

Pravidelne nastáva situácia, keď je potrebné skopírovať množstvo súborov z jedného stroja na druhý. Pri tom často rapídne stúpa LA, pretože všetko naráža na výkon samotných diskov.

Najrozumnejšie, čo chcete — je použiť SSD. Oveľa lepšie. Otázka je len v cene mnohaterabytových SSD.

Ale ak sú disky bežné, súbory treba skopírovať, a to je okrem toho aj produkčný systém, kde preťažovanie vedie k nespokojnosti zákazníkov? Existujú aspoň dva užitočné nástroje: nice a ionice.

nice — znižuje prioritu procesu, takže plánovač prideľuje viac časových kvant iným, prioritnejším procesom.
V našej praxi pomohlo nastaviť nice na maximum (19 — to je minimálna priorita, -20 (mínus 20) — maximálna).

ionice — teda koreguje prioritu vstupu/výstupu (I/O scheduling).

Ak máte RAID a je potrebné ho náhle synchronizovať (po zlyhaní reštartu alebo potrebné obnovenie RAID po výmene disku), v určitých situáciách má zmysel znížiť rýchlosť synchronizácie, aby ostatné procesy mohli fungovať aspoň akosi adekvátne. Na to pomôže nasledujúci príkaz:


echo 1000 > /proc/sys/dev/raid/speed_limit_max

Problém piaty: Ako synchronizovať súbory v reálnom čase

Máme všetky tie obrovské množstvá súborov, ktoré je potrebné zálohovať na druhý server, aby sa predišlo... Súbory sa neustále zapisujú, a preto, aby sme mali minimálne straty, musíme ich kopírovať maximálne rýchlo.

Štandardné riešenie: Rsync cez SSH.

Je to dobrá voľba, pokiaľ to nemusíte robiť každých niekoľko sekúnd. A súborov je mnoho. Aj keď ich nekopírujeme — aj tak je potrebné zistiť, čo sa zmenilo, a porovnanie niekoľkých miliónov súborov zaberie čas a zaťaženie diskov.

T.j. potrebujeme vedieť okamžite, čo je potrebné kopírovať, bez toho, aby sme každú chvíľu spúšťali porovnanie.

Riešenie — lsyncd. Lsyncd — Demon pre živé synchronizovanie (Mirror). Funguje tiež cez rsync, ale navyše monitoruje súborový systém na zmeny pomocou inotify a fsevents a spúšťa kopírovanie iba pre tie súbory, ktoré sa objavili alebo zmenili.

Problém šiesty: ako pochopiť, kto zaťažuje disky

To asi vie každý, ale predsa len pre celkový obraz: na sledovanie diskového subsystému existuje príkaz iotop — podobne ako top, ale zobrazuje procesy, ktoré najaktívnejšie používajú disky.

Triky pri práci s veľkým počtom malých súborov

Mimochodom, starý dobrý top tiež umožňuje zistiť, či sú nejaké problémy s diskami. Na to sú dva najvhodnejšie parametre: Load Average a IOwait.

Triky pri práci s veľkým počtom malých súborov

Prvý zobrazuje, koľko procesov čaká na obsluhu, zvyčajne viac ako 2 — už niečo nie je v poriadku. Pri aktívnom kopírovaní na záložné servery povolujeme až 6-8, po tom sa situácia považuje za mimoriadnu.

Druhý — ako veľmi je procesor zaťažený diskovými operáciami. IOwait >10% — je to dôvod na obavy, hoci na našich serveroch so špecifickým profilom zaťaženia býva stabilne 40-50%, a to je naozaj norma.

Týmto končím, hoci je určite mnoho momentov, s ktorými sme sa nestretli, s radosťou budem čakať na komentáre a opisy zaujímavých skutočných prípadov.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster