Ideen til artiklen opstod spontant fra en diskussion i kommentarerne til artiklen .

Det er sÄdan, at den interne specifikation af vores services er opbevaringen af enorme mÊngder smÄ filer. Lige nu har vi omkring flere hundrede terabyte af sÄdanne data. Og vi er stÞdt pÄ nogle Äbenlyse og ikke sÄ Äbenlyse problemer og har heldigvis klaret os forbi dem.
Derfor deler jeg vores erfaring, mÄske kan den vÊre til hjÊlp for nogen.
Problem nummer et: âIngen plads tilbage pĂ„ enhedenâ
Som nÊvnt i den ovenfor nÊvnte artikel, er problemet, at der er ledige blokke pÄ filsystemet, men at inodes er udtÞmt.
Antallet af brugte og ledige inodes kan tjekkes med kommandoen df -ih:

Jeg vil ikke gentage artiklen, men kort sagt er der pÄ disken bÄde blokke direkte til data og blokke til metadata, som er inodes (indeksnoder). Deres antal bestemmes ved initialisering af filsystemet (bÄde ext2 og dens efterkommere), og derefter Êndres det ikke. Balancen mellem datablokke og inodes beregnes udfra gennemsnitsdata, men i vores tilfÊlde, hvor der er mange smÄ filer, bÞr balancen skubbes i retning af antallet af inodes - der skal vÊre flere af dem.
I Linux er der allerede forudsete muligheder med forskellig balance, og alle disse forudberegnede konfigurationer findes i filen /etc/mke2fs.conf.
Derfor kan man angive den Ăžnskede profil ved den primĂŠre initialisering af filsystemet via mke2fs.
Her er nogle eksempler fra filen:
small = {
blocksize = 1024
inode_size = 128
inode_ratio = 4096
}
big = {
inode_ratio = 32768
}
largefile = {
inode_ratio = 1048576
blocksize = -1
}
Man kan vĂŠlge den Ăžnskede anvendelse ved hjĂŠlp af optionen â-Tâ ved kald af mke2fs. Man kan ogsĂ„ manuelt angive de Ăžnskede parametre, hvis der ikke er en klar lĂžsning.
Flere detaljer er beskrevet i manualerne for mke2fs.conf og mke2fs.
En funktion, der ikke er berÞrt i den ovennÊvnte artikel, er muligheden for at angive stÞrrelsen pÄ datablokken. Det er Äbenlyst, at for store filer giver det mening med en stÞrre blokstÞrrelse, for smÄ filer med en mindre.
Men man skal tage hĂžjde for en interessant egenskab, som er processorarkitekturen.
Engang tĂŠnkte jeg, at jeg havde brug for en stĂžrre blokstĂžrrelse til store fotofiler. Det var i hjemmemiljĂžet pĂ„ en WD-filopbevaring baseret pĂ„ ARM-arkitektur. Uden at tĂŠnke nĂŠrmere over det satte jeg blokstĂžrrelsen til enten 8k eller 16k i stedet for den standard 4k, efter at jeg havde mĂ„lt besparelsen. Og alt var vidunderligt, indtil lageret pludselig svigtede, selvom disken stadig virkede. Da jeg satte disken i en almindelig computer med en almindelig Intel-processor, fik jeg en overraskelse: understĂžttet blokstĂžrrelse. Datan er der, alt ser godt ud, men det er umuligt at lĂŠse det. i386-processorer og lignende kan ikke arbejde med blokstĂžrrelser, der ikke svarer til stĂžrrelsen pĂ„ hukommelsessiden, som netop er 4k. Alt i alt endte det med at bruge vĂŠrktĂžjer fra brugerrummet; alt var langsomt og trist, men vi reddede data. For dem, der er interesserede â goggle efter navnet pĂ„ vĂŠrktĂžjet. fuseext2. Moralen er: enten tĂŠnke pĂ„ alle scenarier pĂ„ forhĂ„nd, eller ikke opfĂžre sig som en superhelt og bruge standardindstillingerne til hjemmebrugere.
UPD. IfÞlge brugerens bemÊrkning prÊciserer jeg, at for i386 mÄ blokstÞrrelsen ikke overstige 4k, men behÞver ikke nÞdvendigvis at vÊre prÊcis 4k, det vil sige 1k og 2k er tilladt.
SÄdan lÞste vi problemerne.
For det fÞrste stÞdte vi pÄ problemet, da den mange terabyte store disk var fyldt med data, og vi kunne ikke Êndre konfigurationen af filsystemet.
For det andet var der brug for en hurtig lĂžsning.
Vi kom derfor frem til, at vi skulle ĂŠndre balancen ved at mindske antallet af filer.
For at reducere antallet af filer blev det besluttet at samle filerne i et fĂŠlles arkiv. I betragtning af vores specifik, samlede vi alle filer i et arkiv for en bestemt tidsperiode, og vi udfĂžrte arkiveringen med en cron-opgave hver nat.
Valgt zip-arkiv. I kommentarerne til den tidligere artikel blev tar foreslÄet, men der er en udfordring: det har ikke et indholdsfortegnelse, og filerne opbevares i en fortlÞbende strÞm (og det er ikke for ingenting, at "tar" er en forkortelse for "Tape Archive", et levn fra bÄndopbevaring), dvs. hvis man skal lÊse en fil i slutningen af arkivet, skal man lÊse hele arkivet, da der ikke er offsets for hver fil i forhold til arkivets begyndelse. Derfor er det en lang operation. I zip er alt meget bedre: det har det Þnskede indholdsfortegnelse og offsets for filerne inden i arkivet, og adgangstiden til hver fil er uafhÊngig af dens placering. I vores tilfÊlde kunne vi desuden angive kompressionsmuligheden til "0", da alle filer allerede var komprimeret i gzip.
Kunderne henter filer via nginx, og i henhold til det gamle API angives blot filnavnet, f.eks. sÄledes:
http://www.server.com/hydra/20170416/0453/3bd24ae7-1df4-4d76-9d28-5b7fcb7fd8e5
For at dekomprimere filer on-the-fly fandt vi og tilsluttede nginx-unzip-module () og indstillede to upstreams.
Resultatet blev en konfiguration som denne:

De to vÊrter i indstillingerne sÄ sÄledes ud:
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;
}
}
Og konfigurationen af upstreams pÄ den overordnede nginx:
upstream storage {
server server.com:8081;
server server.com:8082;
}
SÄdan fungerer det:
- Klienten gÄr til front nginx
- Front nginx forsĂžger at sende filen fra den fĂžrste upstream, dvs. direkte fra filsystemet
- Hvis filen ikke er tilgĂŠngelig â forsĂžger den at sende fra den anden upstream, som leder efter filen inden i arkivet
Det andet problem: igen "No space left on device"
Dette er det andet problem, vi stÞdte pÄ, nÄr der er mange filer i kataloget.
Vi forsĂžger at oprette en fil, men systemet klager over, at der ikke er plads. Vi ĂŠndrer filnavnet og prĂžver at oprette det igen.
Det virker.
Ser omtrent sÄdan her ud:

Kontrol af inodes gav ingen resultater â der er mange ledige.
Pladskontrol â det samme.
Vi tÊnkte, at der mÄske var for mange filer i kataloget, og at der er en begrÊnsning, men igen ikke: Maximum number of files per directory: ~1.3 à 10^20
Og filen kan oprettes, hvis man ĂŠndrer navnet.
Konklusion â problemet ligger i filnavnet.
Yderligere undersÞgelser viste, at problemet lÄ i hash-algoritmen, nÄr der bygges en indeksering af kataloget, da der er et stort antal filer, der observeres sammenfald med alle de konsekvenser, der fÞlger. Man kan lÊse mere her:
Du kan deaktivere denne mulighed, men... sÞgningen efter en fil efter navn kan blive uforudsigeligt lang, nÄr alle filer gennemgÄs.
tune2fs -O "^dir_index" /dev/sdb3
Generelt kan det virke som en midlertidig lĂžsning.
Moralen: mange filer i en mappe er som regel en dÄrlig idé. Det bÞr man undgÄ.
I sÄdanne tilfÊlde opretter man som regel underkataloger baseret pÄ de fÞrste bogstaver i filnavnet eller efter andre parametre, for eksempel efter datoer; i de fleste tilfÊlde hjÊlper det.
Men det samlede antal smĂ„ filer er stadig et problem, selvom de er opdelt i mapper â sĂ„ se pĂ„ det fĂžrste problem.
Problem tre: hvordan ser man en liste over filer, hvis der er mange?
I vores situation, nÄr vi har mange filer, stÞder vi pÄ problemet med at se indholdet af en mappe.
Den standardlĂžsning er kommandoen ls.
Okay, lad os se, hvad der sker med 4772098 filer:
$ time ls /home/app/express.repository/offercache/ >/dev/null
real 0m30.203s
user 0m28.327s
sys 0m1.876s
30 sekunder... det vil vÊre for meget. Og det meste af tiden gÄr med at behandle filer i brugeromrÄdet, ikke pÄ selve kernen.
Men der er en lĂžsning:
$ time find /home/app/express.repository/offercache/ >/dev/null
real 0m3.714s
user 0m1.998s
sys 0m1.717s
3 sekunder. 10 gange hurtigere.
Hurra!
UPD.
Endnu en hurtigere lĂžsning fra en bruger â deaktivering af sorteringen hos ls
time ls -U /home/app/express.repository/offercache/ >/dev/null
real 0m2.985s
user 0m1.377s
sys 0m1.608s
Problem fire: hÞj LA ved hÄndtering af filer
Der opstÄr jÊvnligt situationer, hvor man skal kopiere en masse filer fra én maskine til en anden. Ofte stiger LA markant, da det hele afhÊnger af diskens ydeevne.
Det mest fornuftige ville vÊre at bruge SSD. Virkelig fantastisk. SpÞrgsmÄlet er dog prisen pÄ manges terabytes SSD.
Men hvis diskene er almindelige, skal filer kopieres, og det er desuden en produktionssystem, hvor overbelastning fĂžrer til utilfredshed fra kunderne? Der er mindst to nyttige vĂŠrktĂžjer: nice og ionice.
nice â reducerer processens prioritet, hvilket gĂžr, at scheduler giver flere tidskvoter til andre, mere prioriterede processer.
I vores erfaring har det hjulpet at sĂŠtte nice til maksimum (19 â det mindste prioritet, -20 (minus 20) â maksimum).
ionice â justerer tilsvarende input/output prioriteten (I/O scheduling)
Hvis du bruger RAID, og det pludselig har brug for at synkronisere (efter en mislykket genstart eller hvis RAID-arrayet skal gendannes efter udskiftning af en disk), giver det i visse situationer mening at sÊnke synkroniseringshastigheden, sÄ andre processer kan fungere nogenlunde ordentligt. Dette kan opnÄs med fÞlgende kommando:
echo 1000 > /proc/sys/dev/raid/speed_limit_max
Problem nummer fem: Hvordan synkroniserer man filer i realtid
Vi har de samme store mÊngder filer, der skal sikkerhedskopieres til en anden server for at undgÄ⊠Filer skrives konstant, sÄ for at minimere tab skal de kopieres sÄ hurtigt som muligt.
StandardlĂžsning: Rsync over SSH.
Det er en god mulighed, medmindre det kun skal gĂžres hvert par sekunder. Og der er mange filer. Selv hvis de ikke skal kopieres â skal man stadig pĂ„ en eller anden mĂ„de forstĂ„, hvad der er ĂŠndret, og at sammenligne flere millioner filer tager tid og belaster disken.
Det vil sige, at vi skal vide med det samme, hvad der skal kopieres, uden at sammenligningen skal kĂžres hver gang.
Redningen er â lsyncd. Lsyncd â . Den fungerer ogsĂ„ via rsync, men den overvĂ„ger desuden filsystemet for ĂŠndringer ved hjĂŠlp af inotify og fsevents og starter kun kopieringen af de filer, der er blevet tilfĂžjet eller ĂŠndret.
Problem nummer seks: hvordan man forstÄr, hvem der belaster disken
Det ved sikkert alle, men alligevel for fuldstĂŠndighedens skyld: til overvĂ„gning af diskundersystemet findes kommandoen iotop â ligesom top, men viser de processer, der aktivt bruger disken mest.

Desuden gÞr den gamle gode top det ogsÄ muligt at forstÄ, om der er problemer med disken eller ej. Der er to parametre, der er mest relevante: Load Average og IOwait.

Den fÞrste viser, hvor mange processer der venter pÄ betjening; normalt, hvis der er mere end 2, er der allerede noget, der ikke fungerer korrekt. Ved aktiv kopiering til backup-servere tillader vi op til 6-8, hvorefter situationen betragtes som unormal.
Den anden viser, hvor meget CPU'en er brugt pĂ„ diskoperationer. IOwait >10% â er en grund til bekymring, selvom vi pĂ„ servere med specifik belastningsprofil stabilt kan have 40-50%, og det er reelt en norm.
Jeg vil afslutte her, selvom der helt sikkert er mange aspekter, som vi ikke har vĂŠret udsat for, og jeg ser frem til kommentarer og beskrivelser af interessante virkelige sager.
Kilde: habr.com
