Nápad na článek se zrodil spontánně z diskuze v komentářích k článku .

Faktem je, že interním specifikem našich služeb je ukládání obrovského množství malých souborů. V tuto chvíli máme asi stovky terabajtů takových dat. A narazili jsme na některé zjevné i ne tak zřejmé hrábě a úspěšně je navigovali.
Proto sdílím naše zkušenosti, třeba se budou někomu hodit.
Problém jedna: „Na zařízení nezbývá místo“
Jak bylo zmíněno ve výše zmíněném článku, problém je v tom, že na souborovém systému jsou volné bloky, ale inode došel.
Pomocí příkazu můžete zkontrolovat počet použitých a volných inodů df -ih:

Zkrátka článek nebudu převyprávět, disk obsahuje jak bloky pro samotná data, tak bloky pro metainformace, známé také jako inody (indexový uzel). Jejich počet se nastavuje při inicializaci souborového systému (mluvíme o ext2 a jeho nástupcích) a dále se nemění. Bilance datových bloků a inodů se počítá z průměrných statistických dat, ale v našem případě, kdy je mnoho malých souborů, by se bilance měla posunout směrem k počtu inodů – mělo by jich být více.
Linux již poskytuje možnosti s různými zůstatky a všechny tyto předem vypočítané konfigurace jsou v souboru /etc/mke2fs.conf.
Proto během počáteční inicializace souborového systému pomocí mke2fs můžete zadat požadovaný profil.
Zde je několik příkladů ze souboru:
small = {
blocksize = 1024
inode_size = 128
inode_ratio = 4096
}
big = {
inode_ratio = 32768
}
largefile = {
inode_ratio = 1048576
blocksize = -1
}
Požadovaný případ použití můžete vybrat pomocí možnosti „-T“ při volání mke2fs. Pokud neexistuje hotové řešení, můžete požadované parametry nastavit i ručně.
Více podrobností je popsáno v manuálech pro mke2fs.conf и mke2fs.
Funkce, kterou se výše uvedený článek nezmiňuje, je, že můžete nastavit velikost bloku dat. Je zřejmé, že pro velké soubory má smysl mít větší velikost bloku, pro malé soubory má smysl mít menší.
Za úvahu však stojí i tak zajímavá vlastnost, jakou je architektura procesoru.
Kdysi jsem si myslel, že pro velké soubory fotografií potřebuji větší velikost bloku. Stalo se to doma, v domácím úložišti souborů s názvem WD na architektuře ARM. Bez váhání jsem nastavil velikost bloku buď na 8k nebo 16k místo standardních 4k, když jsem předtím změřil úspory. A vše bylo v pořádku, dokud samotné úložiště selhalo a disk byl stále živý. Po instalaci disku do běžného počítače s běžným procesorem Intel jsem dostal překvapení: nepodporovaná velikost bloku. Přijeli jsme. Data tam jsou, vše je v pořádku, ale nelze je přečíst. i386 a podobné procesory neumí pracovat s velikostmi bloků, které neodpovídají velikosti paměťové stránky, která je přesně 4k. Obecně záležitost skončila použitím utilit z uživatelského prostoru, vše bylo pomalé a smutné, ale data byla zachráněna. Pokud má někdo zájem, vygooglujte si název utility fuseext2. Morálka: buď si předem promyslete všechny případy, nebo nepředstírejte, že jste superhrdina a použijte standardní nastavení pro ženy v domácnosti.
UPD. Podle komentáře uživatele Rád bych upřesnil, že u i386 by velikost bloku neměla přesáhnout 4k, ale nemusí to být přesně 4k, tzn. 1k a 2k jsou přijatelné.
Jak jsme tedy problémy vyřešili?
Za prvé jsme narazili na problém, když byl víceterabajtový disk plný dat a nemohli jsme změnit konfiguraci systému souborů.
Zadruhé bylo naléhavě zapotřebí řešení.
V důsledku toho jsme dospěli k závěru, že musíme změnit rovnováhu snížením počtu souborů.
Pro snížení počtu souborů bylo rozhodnuto umístit soubory do jednoho společného archivu. S ohledem na naše specifika jsme všechny soubory za určité časové období vložili do jednoho archivu a každou noc prováděli archivaci pomocí úlohy cron.
Vybraný archiv zip. V komentářích k předchozímu článku byl navržen tar, ale je s ním jeden problém: nemá obsah a soubory v něm jsou uloženy ve streamu (nejde jen o to, že „tar“ je zkratka pro „Tape Archive“, dědictví páskových jednotek), tj. pokud potřebujete přečíst soubor na konci archivu, musíte přečíst celý archiv, protože neobsahuje offsety pro každý soubor vzhledem k začátku archivu. A proto je to dlouhá operace. V zipu je vše mnohem lepší: v archivu má stejný obsah a offsety souborů a doba přístupu ke každému souboru nezávisí na jeho umístění. V našem případě bylo možné nastavit možnost komprese na „0“, protože všechny soubory byly již předem zkomprimovány v gzip.
Klienti načítají soubory přes nginx a podle starého API je určen pouze název souboru, například takto:
http://www.server.com/hydra/20170416/0453/3bd24ae7-1df4-4d76-9d28-5b7fcb7fd8e5
Pro rozbalení souborů za běhu jsme našli a připojili modul nginx-unzip-module () a zřídit dva proti proudu.
Výsledkem byla následující konfigurace:

Dva hostitelé v nastavení vypadali takto:
server {
listen *:8081;
location / {
root /home/filestorage;
}
}server {
listen *:8082;
location ~ ^/hydra/(d+)/(d+)/(.*)$ {
root /home/filestorage;
file_in_unzip_archivefile "/home/filestorage/hydra/$1/$2.zip";
file_in_unzip_extract "$2/$3";
file_in_unzip;
}
}
A upstream konfigurace na upstream nginx:
upstream storage {
server server.com:8081;
server server.com:8082;
}
Jak to funguje:
- Klient přejde na přední nginx
- Front nginx se snaží obsloužit soubor od prvního upstreamu, tzn. přímo ze souborového systému
- Pokud neexistuje žádný soubor, pokusí se odeslat z druhého upstreamu, který se pokusí najít soubor v archivu
Problém dva: opět „Na zařízení nezbývá místo“
Toto je druhý problém, na který jsme narazili, když je v adresáři mnoho souborů.
Snažíme se vytvořit soubor, systém si stěžuje, že není místo. Změníme název souboru a pokusíme se jej vytvořit znovu.
Ukazuje se.
Vypadá to takto:

Kontrola inodů nic nedala - existuje mnoho volných.
Kontrola umístění je stejná.
Mysleli jsme si, že v adresáři může být příliš mnoho souborů a na to existuje omezení, ale opět ne: Maximální počet souborů v adresáři: ~1.3 × 10^20
Ano, a pokud změníte název, můžete vytvořit soubor.
Závěr - problém je v názvu souboru.
Další prohledávání ukázalo, že problém je v algoritmu hash při konstrukci indexu adresáře s velkým počtem souborů jsou pozorovány kolize se všemi z toho vyplývajícími důsledky. Více podrobností si můžete přečíst zde:
Tuto možnost můžete zakázat, ale... hledání souboru podle názvu může být při prohledávání všech souborů nepředvídatelně dlouhé.
tune2fs -O "^dir_index" /dev/sdb3
Obecně se jedná o dočasné řešení, které může fungovat.
Morálka: hodně souborů v adresáři je obvykle špatná věc. Není třeba to dělat.
Obvykle jsou v takových případech vnořené adresáře vytvořeny podle prvních písmen názvu souboru nebo podle některých dalších parametrů, například podle data, ve většině případů se tím ušetří den.
Ale celkový počet malých souborů je stále špatný, i když jsou rozděleny do adresářů - pak viz první problém.
Problém tři: jak zobrazit seznam souborů, pokud jich je mnoho
V naší situaci, kdy máme hodně souborů, jsme tak či onak čelili problému, jak zobrazit obsah adresáře.
Standardní řešení - příkaz ls.
Dobře, podívejme se, co se stane s 4772098 soubory:
$ time ls /home/app/express.repository/offercache/ >/dev/null
real 0m30.203s
user 0m28.327s
sys 0m1.876s
30 sekund... bude moc. Navíc většinu času stráví zpracování souborů v uživatelském prostoru a už vůbec ne provoz jádra.
Ale existuje řešení:
$ time find /home/app/express.repository/offercache/ >/dev/null
real 0m3.714s
user 0m1.998s
sys 0m1.717s
3 sekundy. 10x rychleji.
Hurá!
UPD.
Ještě rychlejší řešení od uživatele - zakázat řazení ls
time ls -U /home/app/express.repository/offercache/ >/dev/null
real 0m2.985s
user 0m1.377s
sys 0m1.608s
Problém čtvrtý: velké LA při práci se soubory
Čas od času nastane situace, kdy potřebujete zkopírovat spoustu souborů z jednoho počítače na druhý. LA přitom často roste nereálně, jelikož vše závisí na výkonu samotných disků.
Nejchytřejší věc, kterou chcete udělat, je použít SSD. Opravdu super. Jedinou otázkou je cena multiterabajtových SSD.
Pokud jsou ale disky obyčejné, je potřeba soubory kopírovat, a to je také produkční systém, kdy přetížení vede k nespokojeným výkřikům klientů? Existují alespoň dva užitečné nástroje: nice и ionice.
nice — snižuje prioritu procesu, takže plánovač distribuuje více časových úseků jiným procesům s vyšší prioritou.
V naší praxi pomohlo nastavení nice na maximum (19 je minimální priorita, -20 (mínus 20) je maximum).
ionice — odpovídajícím způsobem upraví plánování I/O
Pokud používáte RAID a potřebujete jej náhle synchronizovat (po neúspěšném restartu nebo potřebujete obnovit pole RAID po výměně disku), pak má v některých situacích smysl snížit rychlost synchronizace, aby ostatní procesy mohly více fungovat nebo méně adekvátně. K tomu vám pomůže následující příkaz:
echo 1000 > /proc/sys/dev/raid/speed_limit_max
Problém 5: Jak synchronizovat soubory v reálném čase
Stále máme stejně velké množství souborů, které je třeba zálohovat na druhý server, abychom se vyhnuli... Soubory se neustále zapisují, takže abyste měli co nejmenší ztráty, musíte je co nejrychleji kopírovat.
Standardní řešení: Rsync přes SSH.
Toto je dobrá volba, pokud to nepotřebujete každých pár sekund. A existuje spousta souborů. I když je nezkopírujete, stále musíte nějak pochopit, co se změnilo, a porovnávání několika milionů souborů vyžaduje čas a zatížení disků.
Tito. musíme okamžitě vědět, co je třeba zkopírovat, aniž bychom pokaždé spouštěli srovnání.
Záchrana - lsyncd. Lsyncd - . Funguje také přes rsync, ale navíc sleduje změny v systému souborů pomocí inotify a fsevents a začíná kopírovat pouze ty soubory, které se objevily nebo změnily.
Problém šest: jak pochopit, kdo nahrává disky
Zná to asi každý, ale přesto pro dokreslení: existuje příkaz pro sledování diskového subsystému iotop - jako top, ale ukazuje procesy, které nejaktivněji využívají disky.

Mimochodem, starý dobrý top také umožňuje pochopit, zda je problém s disky nebo ne. K tomu jsou dvě nejvhodnější možnosti: Průměrná zátěž и IPočkejte.

První ukazuje, kolik procesů je ve frontě na službu, obvykle více než 2 - něco se již pokazilo. Při aktivním kopírování na záložní servery povolujeme až 6-8, poté je situace považována za abnormální.
Druhým je vytížení procesoru operacemi s diskem. IOwait >10 % je důvodem k obavám, i když na našich serverech se specifickým profilem zatížení je to trvale 40-50 %, a to je skutečně norma.
Zde skončím, i když je pravděpodobně mnoho bodů, které jsme nemuseli řešit, rád si počkám na komentáře a popisy zajímavých skutečných případů.
Zdroj: www.habr.com
