Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

Məqalənin ideyası məqaləyə şərhlərdəki müzakirədən kortəbii olaraq yaranıb "İnode haqqında bir şey".

Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

Fakt budur ki, xidmətlərimizin daxili xüsusiyyəti çox sayda kiçik faylın saxlanmasıdır. Hazırda əlimizdə yüzlərlə terabaytlıq belə məlumat var. Və biz bəzi açıq-aydın və o qədər də aydın olmayan dırmıqlarla qarşılaşdıq və onları uğurla idarə etdik.

Ona görə də təcrübəmizi bölüşürəm, bəlkə kiməsə faydalı olar.

Problem XNUMX: "Cihazda yer qalmayıb"

Yuxarıda qeyd olunan məqalədə qeyd edildiyi kimi, problem fayl sistemində pulsuz blokların olmasıdır, lakin inode bitmişdir.

Komanda ilə istifadə olunan və pulsuz inodların sayını yoxlaya bilərsiniz df -ih:

Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

Məqaləni təkrar danışmayacağam; bir sözlə, diskdə həm verilənlərin özü üçün bloklar, həm də inode (index node) kimi tanınan metainformasiya blokları var. Onların sayı fayl sistemi işə salındıqda təyin olunur (söhbət ext2 və onun varislərindən gedir) və daha da dəyişmir. Məlumat bloklarının və inodların balansı orta statistik məlumatlardan hesablanır, lakin bizim vəziyyətimizdə, çox sayda kiçik fayl olduqda, balans inodların sayına doğru dəyişməlidir - onlardan daha çox olmalıdır.

Linux artıq müxtəlif balanslarla seçimlər təqdim etmişdir və bütün bu əvvəlcədən hesablanmış konfiqurasiyalar fayldadır /etc/mke2fs.conf.
Buna görə də, mke2fs vasitəsilə fayl sisteminin ilkin işə salınması zamanı istədiyiniz profili təyin edə bilərsiniz.

Fayldan bəzi nümunələr:

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

    big = {
        inode_ratio = 32768
    }

    largefile = {
        inode_ratio = 1048576
        blocksize = -1
    }

Mke2fs-ə zəng edərkən “-T” seçimindən istifadə edərək istədiyiniz istifadə halını seçə bilərsiniz. Hazır həll yoxdursa, tələb olunan parametrləri əl ilə də təyin edə bilərsiniz.

Daha ətraflı məlumat üçün təlimatlarda təsvir edilmişdir mke2fs.conf и mke2fs.

Yuxarıda qeyd olunan məqalədə toxunulmayan bir xüsusiyyət, məlumat blokunun ölçüsünü təyin edə biləcəyinizdir. Aydındır ki, böyük fayllar üçün daha böyük blok ölçüsünə sahib olmaq, kiçik fayllar üçün daha kiçik bir bloka sahib olmaq məna daşıyır.

Bununla belə, prosessor arxitekturası kimi maraqlı bir xüsusiyyəti nəzərə almağa dəyər.
Bir dəfə düşündüm ki, böyük foto faylları üçün daha böyük blok ölçüsünə ehtiyacım var. Bu, evdə, ARM arxitekturasında WD adlı bir ev fayl mağazasında baş verdi. Mən tərəddüd etmədən blok ölçüsünü əvvəllər qənaəti ölçərək standart 8k əvəzinə 16k və ya 4k təyin etdim. Saxlama özü uğursuz olana qədər hər şey yaxşı idi və disk hələ də canlı idi. Diski adi bir Intel prosessoru olan adi bir kompüterə quraşdırdıqdan sonra sürprizlə qarşılaşdım: dəstəklənməyən blok ölçüsü. Biz gəldik. Məlumat var, hər şey yaxşıdır, amma oxumaq mümkün deyil. i386 və oxşar prosessorlar tam olaraq 4k olan yaddaş səhifəsinin ölçüsünə uyğun gəlməyən blok ölçüləri ilə işləyə bilməz. Ümumiyyətlə, məsələ istifadəçi sahəsindən kommunalların istifadəsi ilə sona çatdı, hər şey yavaş və kədərli idi, lakin məlumatlar saxlanıldı. Kimsə maraqlanırsa, yardım proqramının adını google-da axtarın fuseext2. Əxlaq: ya bütün halları əvvəlcədən düşünün, ya da özünüzü super qəhrəman kimi göstərməyin və evdar qadınlar üçün standart parametrlərdən istifadə edin.

UPD. İstifadəçi şərhinə görə berez Aydınlaşdırmaq istərdim ki, i386 üçün blok ölçüsü 4k-dan çox olmamalıdır, lakin onun tam olaraq 4k olması lazım deyil, yəni. 1k və 2k məqbuldur.

Yaxşı, problemləri necə həll etdik?

Birincisi, çox terabaytlıq disk məlumatla dolu olduqda problemlə qarşılaşdıq və fayl sisteminin konfiqurasiyasını dəyişə bilmədik.

İkincisi, təcili həll lazım idi.

Nəticədə belə qənaətə gəldik ki, faylların sayını azaltmaqla balansı dəyişmək lazımdır.
Faylların sayını azaltmaq üçün faylları bir ümumi arxivə yerləşdirmək qərara alındı. Xüsusiyyətlərimizi nəzərə alaraq, müəyyən bir müddət ərzində bütün faylları bir arxivə yığdıq və hər gecə cron tapşırığından istifadə edərək arxivləşdirmə apardıq.

Seçilmiş zip arxivi. Əvvəlki məqaləyə şərhlərdə tar təklif edilmişdi, lakin bununla bağlı bir çətinlik var: onun məzmunu yoxdur və içindəki fayllar axın şəklində saxlanılır (təkcə “tar” qısaltması deyil) lent disklərinin mirası olan “Tap Arxivi” üçün), yəni. arxivin sonunda bir faylı oxumaq lazımdırsa, bütün arxivi oxumalısınız, çünki arxivin əvvəlinə nisbətən hər bir fayl üçün ofsetlər yoxdur. Və buna görə də uzun bir əməliyyatdır. Zip-də hər şey daha yaxşıdır: arxiv daxilində eyni məzmun cədvəli və fayl ofsetləri var və hər bir fayla giriş vaxtı onun yerindən asılı deyil. Yaxşı, bizim vəziyyətimizdə sıxılma seçimini "0" olaraq təyin etmək mümkün idi, çünki bütün fayllar əvvəlcədən gzip-də sıxılmışdı.

Müştərilər faylları nginx vasitəsilə əldə edirlər və köhnə API-ə əsasən, sadəcə fayl adı göstərilir, məsələn:

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

Faylları tez bir zamanda açmaq üçün nginx-unzip-modul modulunu tapdıq və birləşdirdik (https://github.com/youzee/nginx-unzip-module) və iki yuxarı axını qurun.

Nəticə aşağıdakı konfiqurasiya oldu:

Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

Parametrlərdəki iki host belə görünürdü:

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;
  }
}

Və yuxarı nginx-də yuxarı axın konfiqurasiyası:

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

Bu necə işləyir:

  • Müştəri ön nginx-ə keçir
  • Front nginx fayla ilk yuxarı axınından xidmət etməyə çalışır, yəni. birbaşa fayl sistemindən
  • Heç bir fayl yoxdursa, faylı arxivin içərisində tapmağa çalışan ikinci yuxarıdan göndərməyə çalışır.

İkinci problem: yenidən "Cihazda yer qalmayıb"

Bu, kataloqda çoxlu fayl olduqda qarşılaşdığımız ikinci problemdir.
Fayl yaratmağa çalışırıq, sistem boşluq olmadığından şikayətlənir. Faylın adını dəyişirik və onu yenidən yaratmağa çalışırıq.

Çıxır.

Bu kimi bir şey görünür:

Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

İnodları yoxlamaq heç bir şey vermədi - bir çox pulsuz olanlar var.
Yerin yoxlanılması eynidir.
Kataloqda həddən artıq çox fayl ola biləcəyini düşündük və bununla bağlı məhdudiyyət var, amma yenə də yox: Kataloqda maksimum fayl sayı: ~1.3 × 10^20

Bəli və adını dəyişdirsəniz, fayl yarada bilərsiniz.
Nəticə - problem fayl adındadır.

Sonrakı axtarışlar göstərdi ki, problem kataloq indeksini qurarkən hashing alqoritmindədir; çox sayda fayl ilə toqquşmalar bütün sonrakı nəticələrlə müşahidə olunur. Daha ətraflı burada oxuya bilərsiniz: https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Hash_Tree_Directories

Siz bu seçimi deaktiv edə bilərsiniz, lakin... bütün faylları axtararkən adı ilə fayl axtarışı gözlənilməz dərəcədə uzana bilər.

 tune2fs -O "^dir_index" /dev/sdb3

Ümumiyyətlə, bu işləyə biləcək müvəqqəti bir həlldir.

Əxlaq: kataloqda çoxlu fayl adətən pis bir şeydir. Bunu etməyə ehtiyac yoxdur.

Adətən belə hallarda, iç içə qovluqlar fayl adının ilk hərfləri və ya bəzi digər parametrlər, məsələn, tarixlər ilə yaradılır, əksər hallarda bu, günə qənaət edir.
Lakin kiçik faylların ümumi sayı hələ də pisdir, hətta kataloqlara bölünsələr də - onda ilk problemə baxın.

Problem üçüncü: faylların siyahısına baxmaq necədir, əgər onların sayı çoxdursa

Bizim vəziyyətimizdə, çoxlu fayllarımız olduqda, bu və ya digər şəkildə kataloqun məzmununa necə baxmaq problemi ilə qarşılaşdıq.

Standart həll - əmr ls.
Yaxşı, gəlin 4772098 faylında nə baş verdiyinə baxaq:


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

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

30 saniyə... çox olacaq. Üstəlik, çox vaxt nüvənin işləməsinə deyil, istifadəçi məkanında faylların işlənməsinə sərf olunur.

Ancaq bir həll var:


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

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

3 saniyə. 10 dəfə sürətli.
Yaşasın!

UPD.

İstifadəçidən daha sürətli həll berez - çeşidləməni söndürün ls


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

Dördüncü problem: fayllarla işləyərkən böyük LA

Zaman zaman bir dəstə faylı bir maşından digərinə köçürmək lazım olan bir vəziyyət yaranır. Eyni zamanda, LA tez-tez qeyri-real şəkildə böyüyür, çünki hər şey disklərin öz performansından asılıdır.

Etmək istədiyiniz ən ağıllı şey SSD istifadə etməkdir. Həqiqətən sərin. Yeganə sual çox terabaytlıq SSD-lərin qiymətidir.

Ancaq disklər adidirsə, faylları kopyalamalısınız və bu da bir istehsal sistemidir, burada həddindən artıq yükləmə müştərilərdən narazı nidalara səbəb olur? Ən azı iki faydalı vasitə var: nice и ionice.

nice — prosesin prioritetini azaldır, müvafiq olaraq planlaşdırıcı daha çox vaxt dilimlərini digər, daha yüksək prioritetli proseslərə paylayır.
Təcrübəmizdə o, maksimuma gözəl təyin etməyə kömək etdi (19 minimum prioritet, -20 (mənfi 20) maksimum).

ionice — I/O cədvəlini müvafiq olaraq tənzimləyir

Əgər siz RAID-dən istifadə edirsinizsə və onu qəfil sinxronlaşdırmaq lazımdırsa (uğursuz yenidən yükləmədən sonra və ya diski dəyişdirdikdən sonra RAID massivini bərpa etməlisiniz), o zaman bəzi hallarda digər proseslərin daha çox işləməsi üçün sinxronizasiya sürətini azaltmaq mənasızdır. və ya daha az adekvat. Aşağıdakı əmr buna kömək edəcək:


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

Problem beş: Faylları real vaxtda necə sinxronlaşdırmaq olar

Bizdə hələ də qaçmaq üçün ikinci serverə ehtiyat nüsxəsini çıxarmaq lazım olan eyni sayda fayllarımız var... Fayllar daim yazılır, ona görə də minimum itkilərə sahib olmaq üçün onları mümkün qədər tez surətdə çıxarmaq lazımdır.

Standart həll: SSH üzərində Rsync.

Bunu bir neçə saniyədən bir etmək lazım deyilsə, bu yaxşı seçimdir. Və bir çox fayl var. Onları kopyalamasanız belə, nəyin dəyişdiyini hələ də birtəhər başa düşməlisiniz və bir neçə milyon faylı müqayisə etmək vaxt və disklərə yükləmə tələb edir.

Bunlar. hər dəfə müqayisə aparmadan, nəyin kopyalanması lazım olduğunu dərhal bilməliyik.

Xilasetmə - lsyncd. Lsyncd - Canlı Sinxronizasiya (Güzgü) Daemon. O, həmçinin rsync vasitəsilə işləyir, lakin əlavə olaraq inotify və fsevents istifadə edərək fayl sisteminə dəyişikliklərə nəzarət edir və yalnız görünən və ya dəyişdirilmiş faylları kopyalamağa başlayır.

Problem altıncı: diskləri kimin yüklədiyini necə başa düşmək olar

Yəqin ki, hər kəs bunu bilir, amma buna baxmayaraq, şəkli tamamlamaq üçün: disk alt sistemini izləmək üçün bir əmr var iotop - kimi top, lakin diskləri ən aktiv şəkildə istifadə edən prosesləri göstərir.

Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

Yeri gəlmişkən, köhnə yaxşı üst də disklərdə problem olub olmadığını anlamağa imkan verir. Bunun üçün ən uyğun iki variant var: Orta yükləmə и gözləyin.

Çoxlu sayda kiçik fayllarla işləmək üçün hacklər

Birincisi, xidmət növbəsində neçə prosesin olduğunu göstərir, adətən 2-dən çox - bir şey artıq səhv gedir. Yedək serverlərə aktiv surətdə köçürərkən, biz 6-8-ə qədər icazə veririk, bundan sonra vəziyyət anormal sayılır.

İkincisi, prosessorun disk əməliyyatları ilə nə qədər məşğul olmasıdır. IOwait >10% narahatlıq doğurur, baxmayaraq ki, xüsusi yük profili olan serverlərimizdə bu, ardıcıl olaraq 40-50% təşkil edir və bu, həqiqətən normadır.

Burada bitirəcəyəm, yəqin ki, həll etmədiyimiz bir çox məqamlar olsa da, şərhləri və maraqlı real hadisələrin təsvirlərini gözləməkdən məmnunam.

Mənbə: www.habr.com

Добавить комментарий