Rsync uruchomił Linux OOM Killer na pojedynczym pliku 50 GB

66

Mam pojedynczy plik 50 GB na server_A i kopiuję go na server_B. biegnę

server_A$ rsync --partial --progress --inplace --append-verify 50GB_file root@server_B:50GB_file

Server_B ma 32 GB pamięci RAM z zamianą 2 GB. Jest w większości bezczynny i powinien mieć dużo wolnej pamięci RAM. Ma dużo miejsca na dysku. Przy około 32 GB transfer zostaje przerwany, ponieważ strona zdalna zamknęła połączenie.

Serwer_B spadł z sieci. Prosimy centrum danych o ponowne uruchomienie. Kiedy patrzę na dziennik jądra sprzed awarii, widzę, że używał 0 bajtów wymiany, a lista procesów używała bardzo mało pamięci (proces rsync został wymieniony jako wykorzystujący 600 KB pamięci RAM), ale oom_killer był szaleje, a ostatnią rzeczą w dzienniku jest miejsce, w którym zabija proces czytnika jądra metalogu.

To jest jądro 3.2.59, 32-bitowe (więc żaden proces nie może zmapować więcej niż 4 GB).

To prawie tak, jakby Linux dał większy priorytet buforowaniu niż długo działającym demonom. Co daje?? I jak mogę zapobiec powtórzeniu się?

Oto wynik działania oom_killer:

Sep 23 02:04:16 [kernel] [1772321.850644] clamd invoked oom-killer: gfp_mask=0x84d0, order=0, oom_adj=0, oom_score_adj=0
Sep 23 02:04:16 [kernel] [1772321.850649] Pid: 21832, comm: clamd Tainted: G         C   3.2.59 #21
Sep 23 02:04:16 [kernel] [1772321.850651] Call Trace:
Sep 23 02:04:16 [kernel] [1772321.850659]  [<c01739ac>] ? dump_header+0x4d/0x160
Sep 23 02:04:16 [kernel] [1772321.850662]  [<c0173bf3>] ? oom_kill_process+0x2e/0x20e
Sep 23 02:04:16 [kernel] [1772321.850665]  [<c0173ff8>] ? out_of_memory+0x225/0x283
Sep 23 02:04:16 [kernel] [1772321.850668]  [<c0176438>] ? __alloc_pages_nodemask+0x446/0x4f4
Sep 23 02:04:16 [kernel] [1772321.850672]  [<c0126525>] ? pte_alloc_one+0x14/0x2f
Sep 23 02:04:16 [kernel] [1772321.850675]  [<c0185578>] ? __pte_alloc+0x16/0xc0
Sep 23 02:04:16 [kernel] [1772321.850678]  [<c0189e74>] ? vma_merge+0x18d/0x1cc
Sep 23 02:04:16 [kernel] [1772321.850681]  [<c01856fa>] ? handle_mm_fault+0xd8/0x15d
Sep 23 02:04:16 [kernel] [1772321.850685]  [<c012305a>] ? do_page_fault+0x20e/0x361
Sep 23 02:04:16 [kernel] [1772321.850688]  [<c018a9c4>] ? sys_mmap_pgoff+0xa2/0xc9
Sep 23 02:04:16 [kernel] [1772321.850690]  [<c0122e4c>] ? vmalloc_fault+0x237/0x237
Sep 23 02:04:16 [kernel] [1772321.850694]  [<c08ba7e6>] ? error_code+0x5a/0x60
Sep 23 02:04:16 [kernel] [1772321.850697]  [<c08b0000>] ? cpuid4_cache_lookup_regs+0x372/0x3b2
Sep 23 02:04:16 [kernel] [1772321.850700]  [<c0122e4c>] ? vmalloc_fault+0x237/0x237
Sep 23 02:04:16 [kernel] [1772321.850701] Mem-Info:
Sep 23 02:04:16 [kernel] [1772321.850703] DMA per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850704] CPU    0: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850706] CPU    1: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850707] CPU    2: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850709] CPU    3: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850711] CPU    4: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850713] CPU    5: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850714] CPU    6: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850716] CPU    7: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850718] Normal per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850719] CPU    0: hi:  186, btch:  31 usd:  70
Sep 23 02:04:16 [kernel] [1772321.850721] CPU    1: hi:  186, btch:  31 usd: 116
Sep 23 02:04:16 [kernel] [1772321.850723] CPU    2: hi:  186, btch:  31 usd: 131
Sep 23 02:04:16 [kernel] [1772321.850724] CPU    3: hi:  186, btch:  31 usd:  76
Sep 23 02:04:16 [kernel] [1772321.850726] CPU    4: hi:  186, btch:  31 usd:  29
Sep 23 02:04:16 [kernel] [1772321.850728] CPU    5: hi:  186, btch:  31 usd:  61
Sep 23 02:04:16 [kernel] [1772321.850731] CPU    7: hi:  186, btch:  31 usd:  17
Sep 23 02:04:16 [kernel] [1772321.850733] HighMem per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850734] CPU    0: hi:  186, btch:  31 usd:   2
Sep 23 02:04:16 [kernel] [1772321.850736] CPU    1: hi:  186, btch:  31 usd:  69
Sep 23 02:04:16 [kernel] [1772321.850738] CPU    2: hi:  186, btch:  31 usd:  25
Sep 23 02:04:16 [kernel] [1772321.850739] CPU    3: hi:  186, btch:  31 usd:  27
Sep 23 02:04:16 [kernel] [1772321.850741] CPU    4: hi:  186, btch:  31 usd:   7
Sep 23 02:04:16 [kernel] [1772321.850743] CPU    5: hi:  186, btch:  31 usd: 188
Sep 23 02:04:16 [kernel] [1772321.850744] CPU    6: hi:  186, btch:  31 usd:  25
Sep 23 02:04:16 [kernel] [1772321.850746] CPU    7: hi:  186, btch:  31 usd: 158
Sep 23 02:04:16 [kernel] [1772321.850750] active_anon:117913 inactive_anon:9942 isolated_anon:0
Sep 23 02:04:16 [kernel] [1772321.850751]  active_file:106466 inactive_file:7784521 isolated_file:0
Sep 23 02:04:16 [kernel] [1772321.850752]  unevictable:40 dirty:0 writeback:61 unstable:0
Sep 23 02:04:16 [kernel] [1772321.850753]  free:143494 slab_reclaimable:128312 slab_unreclaimable:4089
Sep 23 02:04:16 [kernel] [1772321.850754]  mapped:6706 shmem:308 pagetables:915 bounce:0
Sep 23 02:04:16 [kernel] [1772321.850759] DMA free:3624kB min:140kB low:172kB high:208kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolate
d(file):0kB present:15808kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:240kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tm
p:0kB pages_scanned:0 all_unreclaimable? yes
Sep 23 02:04:16 [kernel] [1772321.850763] lowmem_reserve[]: 0 869 32487 32487
Sep 23 02:04:16 [kernel] [1772321.850770] Normal free:8056kB min:8048kB low:10060kB high:12072kB active_anon:0kB inactive_anon:0kB active_file:248kB inactive_file:388kB unevictable:0kB isolated(anon)
:0kB isolated(file):0kB present:890008kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:513008kB slab_unreclaimable:16356kB kernel_stack:1888kB pagetables:3660kB unstable:0
kB bounce:0kB writeback_tmp:0kB pages_scanned:1015 all_unreclaimable? yes
Sep 23 02:04:16 [kernel] [1772321.850774] lowmem_reserve[]: 0 0 252949 252949
Sep 23 02:04:16 [kernel] [1772321.850785] lowmem_reserve[]: 0 0 0 0
Sep 23 02:04:16 [kernel] [1772321.850788] DMA: 0*4kB 7*8kB 3*16kB 6*32kB 4*64kB 6*128kB 5*256kB 2*512kB 0*1024kB 0*2048kB 0*4096kB = 3624kB
Sep 23 02:04:16 [kernel] [1772321.850795] Normal: 830*4kB 80*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB = 8056kB
Sep 23 02:04:16 [kernel] [1772321.850802] HighMem: 13*4kB 14*8kB 2*16kB 2*32kB 0*64kB 0*128kB 2*256kB 2*512kB 3*1024kB 0*2048kB 136*4096kB = 561924kB
Sep 23 02:04:16 [kernel] [1772321.850809] 7891360 total pagecache pages
Sep 23 02:04:16 [kernel] [1772321.850811] 0 pages in swap cache
Sep 23 02:04:16 [kernel] [1772321.850812] Swap cache stats: add 0, delete 0, find 0/0
Sep 23 02:04:16 [kernel] [1772321.850814] Free swap  = 1959892kB
Sep 23 02:04:16 [kernel] [1772321.850815] Total swap = 1959892kB
Sep 23 02:04:16 [kernel] [1772321.949081] 8650736 pages RAM
Sep 23 02:04:16 [kernel] [1772321.949084] 8422402 pages HighMem
Sep 23 02:04:16 [kernel] [1772321.949085] 349626 pages reserved
Sep 23 02:04:16 [kernel] [1772321.949086] 7885006 pages shared
Sep 23 02:04:16 [kernel] [1772321.949087] 316864 pages non-shared
Sep 23 02:04:16 [kernel] [1772321.949089] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
            (rest of process list omitted)
Sep 23 02:04:16 [kernel] [1772321.949656] [14579]     0 14579      579      171   5       0             0 rsync
Sep 23 02:04:16 [kernel] [1772321.949662] [14580]     0 14580      677      215   5       0             0 rsync
Sep 23 02:04:16 [kernel] [1772321.949669] [21832]   113 21832    42469    37403   0       0             0 clamd
Sep 23 02:04:16 [kernel] [1772321.949674] Out of memory: Kill process 21832 (clamd) score 4 or sacrifice child
Sep 23 02:04:16 [kernel] [1772321.949679] Killed process 21832 (clamd) total-vm:169876kB, anon-rss:146900kB, file-rss:2712kB

Oto wynik „górny” po powtórzeniu polecenia rsync jako użytkownik inny niż root:

top - 03:05:55 up  8:43,  2 users,  load average: 0.04, 0.08, 0.09
Tasks: 224 total,   1 running, 223 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0% us,  0.0% sy,  0.0% ni, 99.9% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:  33204440k total, 32688600k used,   515840k free,   108124k buffers
Swap:  1959892k total,        0k used,  1959892k free, 31648080k cached

Oto parametry sysctl vm:

# sysctl -a | grep '^vm'
vm.overcommit_memory = 0
vm.panic_on_oom = 0
vm.oom_kill_allocating_task = 0
vm.oom_dump_tasks = 1
vm.overcommit_ratio = 50
vm.page-cluster = 3
vm.dirty_background_ratio = 1
vm.dirty_background_bytes = 0
vm.dirty_ratio = 0
vm.dirty_bytes = 15728640
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
vm.nr_pdflush_threads = 0
vm.swappiness = 60
vm.lowmem_reserve_ratio = 256   32      32
vm.drop_caches = 0
vm.min_free_kbytes = 8192
vm.percpu_pagelist_fraction = 0
vm.max_map_count = 65530
vm.laptop_mode = 0
vm.block_dump = 0
vm.vfs_cache_pressure = 100
vm.legacy_va_layout = 0
vm.stat_interval = 1
vm.mmap_min_addr = 4096
vm.vdso_enabled = 2
vm.highmem_is_dirtyable = 0
vm.scan_unevictable_pages = 0
bez danych
źródło
2
Nie jestem ekspertem w czytaniu komunikatów o awariach jądra, ale nie widzę tam żadnych oznak, że B używa 32 GB rdzenia. Zanim przejdziemy do założenia, że ​​tak było, czy możesz potwierdzić, że tak jest obecnie? Ponieważ istnieje duża różnica między wyczerpującym pamięcią pudełkiem z 32 GB rdzenia, a tym z zaledwie 4 GB.
MadHatter
Zaktualizowano z wydajnością Top. Dzieje się tak po uruchomieniu tej samej komendy rsync, co użytkownik inny niż root. Prawie wszystkie oprócz 1 GB są teraz używane do buforowania.
24.09.2015
Dzięki. Jak powiedziałem, nie jestem ekspertem - ale warto to sprawdzić.
MadHatter
powinieneś również sprawdzić, czy twoje jądro pozwala na zamianę (tj. zamiana nie jest wyłączona) (i powinieneś poświęcić większą część miejsca na dysku, powiedzmy 16 Gb, a nawet 32 ​​Gb). Niektóre dziwne osoby w sieci zalecają wyłączenie zamiany, co jest bardzo złe.
Olivier Dulac
@OlivierDulac do jakiego ustawienia się odnosisz? obsługa zamiany jest wkompilowana, inaczej nie będziemy mogli zamontować swap, a „swapiness” jest ustawiony na 60. Jeśli chodzi o rozmiar swapów, czy to nie pogorszy problemu w 32-bitowym jądrze? Odpowiedź wydaje się, że struktury danych jądra były tym, co nas zabiło. Nie uruchamiamy 32 GB procesów użytkownika, chcemy tylko tyle pamięci RAM dla pamięci podręcznej dysku, dla wydajności.
danych

Odpowiedzi:

178

Przeczytajmy więc wynik działania zabójcy oom i zobaczmy, czego można się z niego nauczyć.

Analizując dzienniki zabójców OOM, ważne jest, aby spojrzeć na to, co je wywołało. Pierwszy wiersz dziennika zawiera wskazówki:

[jądro] [1772321.850644] clamd wywołał oom-killer: gfp_mask = 0x84d0, order = 0

order=0mówi nam, ile pamięci jest wymagane. Zarządzanie pamięcią jądra jest w stanie zarządzać numerami stron o sile 2, więc clamd zażądał 2 0 stron pamięci lub 4KB.

Najniższe dwa bity GFP_MASK (pobierz darmową maskę strony) stanowią tak zwaną maskę strefy, która informuje alokatora, z której strefy pobiera pamięć :

Flag            value      Description
                0x00u      0 implicitly means allocate from ZONE_NORMAL
__GFP_DMA       0x01u      Allocate from ZONE_DMA if possible
__GFP_HIGHMEM   0x02u      Allocate from ZONE_HIGHMEM if possible

Strefy pamięci to koncepcja stworzona głównie ze względu na kompatybilność. W uproszczonym widoku istnieją trzy strefy dla jądra x86:

Memory range   Zone       Purpose 

0-16 MB        DMA        Hardware compatibility (devices)
16 - 896 MB    NORMAL     space directly addressable by the Kernel, userland 
> 896 MB       HIGHMEM    userland, space addressable by the Kernel via kmap() calls

W twoim przypadku, zonemask ma wartość 0, co oznacza, że ​​clamd żąda pamięci od ZONE_NORMAL.

Pozostałe flagi są rozpatrywane

/*
 * Action modifiers - doesn't change the zoning
 *
 * __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
 * _might_ fail.  This depends upon the particular VM implementation.
 *
 * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
 * cannot handle allocation failures.
 *
 * __GFP_NORETRY: The VM implementation must not retry indefinitely.
 */
#define __GFP_WAIT      0x10u   /* Can wait and reschedule? */
#define __GFP_HIGH      0x20u   /* Should access emergency pools? */
#define __GFP_IO        0x40u   /* Can start physical IO? */
#define __GFP_FS        0x80u   /* Can call down to low-level FS? */
#define __GFP_COLD      0x100u  /* Cache-cold page required */
#define __GFP_NOWARN    0x200u  /* Suppress page allocation failure warning */
#define __GFP_REPEAT    0x400u  /* Retry the allocation.  Might fail */
#define __GFP_NOFAIL    0x800u  /* Retry for ever.  Cannot fail */
#define __GFP_NORETRY   0x1000u /* Do not retry.  Might fail */
#define __GFP_NO_GROW   0x2000u /* Slab internal usage */
#define __GFP_COMP      0x4000u /* Add compound page metadata */
#define __GFP_ZERO      0x8000u /* Return zeroed page on success */
#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */

zgodnie z dokumentacją Linux MM , więc requst ma flagi na GFP_ZERO, GFP_REPEAT, GFP_FS, GFP_IOi GFP_WAIT, będąc w ten sposób nie jest szczególnie wybredny.

Więc o co chodzi ZONE_NORMAL? Niektóre ogólne statystyki można znaleźć dalej w danych wyjściowych OOM:

[jądro] [1772321.850770] Normalnie wolne: 8056kB min: 8048kB niski: 10060kB wysoki: 12072kB aktywny_anon: 0kB nieaktywny_anon: 0kB aktywny_plik: 248kB nieaktywny_plik: 388kB nieunikniony: 0kB izolowany (anon): 0kB izolowany (obecny): 89kB izolowany

Zauważalne jest tutaj to, że freejest tylko 8 KB od mini pod spodem low. Oznacza to, że menedżer pamięci twojego hosta jest nieco w trudnej sytuacji i kswapd powinien już zamieniać strony, tak jak jest w żółtej fazie poniższego wykresu: Wykres menedżera pamięci dla systemu Linux

Więcej informacji na temat fragmentacji pamięci strefy znajduje się tutaj:

[jądro] [1772321.850795] Normalny: 830 * 4kB 80 * 8kB 0 * 16kB 0 * 32kB 0 * 64kB 0 * 128kB 0 * 256kB 0 * 512kB 0 * 1024kB 0 * 2048kB 1 * 4096kB = 8056kB

w zasadzie stwierdzając, że masz jedną ciągłą stronę o wielkości 4 MB, a resztę mocno podzielono na strony głównie 4KB.

Podsumujmy więc:

  • masz proces użytkownika ( clamd), który pobiera pamięć, ZONE_NORMALpodczas gdy zwykle nie wykonuje się przydziału pamięciZONE_HIMEM
  • menedżer pamięci powinien na tym etapie być w stanie obsłużyć żądaną stronę 4K, chociaż wydaje się, że masz znaczną presję pamięci ZONE_NORMAL
  • system, zgodnie kswapdz regułami, powinien był wcześniej zobaczyć jakąś aktywność stronicowania, ale nic nie jest zamieniane, nawet pod presją pamięci ZONE_NORMAL, bez wyraźnej przyczyny
  • Żadne z powyższych nie podaje konkretnego powodu, dla którego oom-killerzostało przywołane

Wszystko to wydaje się dość dziwne, ale przynajmniej powinno być powiązane z tym, co opisano w sekcji 2.5 doskonałej książki Johna O'Gormana „Zrozumieć menedżera wirtualnej pamięci systemu Linux” :

Ponieważ przestrzeń adresów wykorzystywana przez jądro (ZONE_NORMAL) ma ograniczony rozmiar, jądro obsługuje koncepcję wysokiej pamięci. [...] Aby uzyskać dostęp do pamięci w zakresie od 1GiB do 4GiB, jądro tymczasowo mapuje strony z dużej pamięci do ZONE_NORMAL za pomocą kmap (). [...]

Oznacza to, że do opisania 1GiB pamięci potrzeba około 11 MB pamięci jądra. Zatem przy 16GiB zużywa się 176 MB pamięci, co powoduje znaczną presję na ZONE_NORMAL. Nie brzmi to źle, dopóki nie zostaną wzięte pod uwagę inne struktury, które używają ZONE_NORMAL. Nawet bardzo małe struktury, takie jak wpisy tabeli stron (PTE), w najgorszym przypadku wymagają około 16 MB. To sprawia, że ​​16GiB dotyczy praktycznego limitu dostępnej pamięci fizycznej Linux na x86 .

(nacisk jest mój)

Ponieważ 3.2 ma wiele ulepszeń w zarządzaniu pamięcią w stosunku do 2.6, nie jest to jednoznaczna odpowiedź, ale naprawdę silna wskazówka, którą chciałbym zastosować jako pierwszy. Zmniejsz użyteczną pamięć hosta do co najwyżej 16G, używając mem=parametru jądra lub zgrywając połowę modułów DIMM z serwera.

Ostatecznie użyj 64-bitowego jądra .

Koleś, to 2015.

the-wabbit
źródło
13
Kiedy powiedziałem powyżej „ Nie jestem ekspertem ”, to jest to, czego oczekiwałem czytać. +1000, gdybym mógł; +1 na pewno. Cóż za świetna odpowiedź!
MadHatter
18
To było piękne. Nadal jest nadzieja dla SF.
Rzym.
9
@dataless Tak. Podejrzewam, że wszystkie twoje ZONE_NORMAL są wypełnione metadanymi dotyczącymi górnych obszarów pamięci. Gdy proces użytkownika żąda stron pamięci, najprawdopodobniej poprosi o ZONE_HIGHMEM (który może zostać zaktualizowany przez MM do ZONE_NORMAL, jeśli HIGHMEM nie ma już wolnych stron do obsługi żądania, ale NORMAL ma), więc chyba, że ​​ZONE_HIGHMEM jest pod presją pamięci (twoje nie jest), ZONE_NORMAL nie będzie zawierał stron procesów w przestrzeni użytkownika.
the-wabbit
3
[uderza pięściami w klawiaturę] Daj temu Wabbitowi nagrodę
underscore_d
3
@ the-wabbit Gorące pytania sieciowe.
CodesInChaos
4

Kilka spraw ...

Moją ogólną zasadą dla przestrzeni wymiany jest przynajmniej dwukrotność fizycznego taranowania. Dzięki temu demon stronicowania / wymiany może efektywnie zmieniać pamięć.

Server_B ma 32 GB pamięci RAM, więc spróbuj skonfigurować go na 64 GB wymiany. IMO, 2GB swap serwer ma to droga zbyt niska, zwłaszcza na serwerze.

Jeśli nie masz dodatkowej partycji, którą można przekształcić w partycję wymiany, możesz to przetestować, tworząc plik i montując go jako partycję wymiany [będzie wolna]. Zobacz https://www.maketecheasier.com/swap-partitions-on-linux/

Ponieważ server_B ma dużo miejsca na dysku, --inplace nie jest potrzebne i może być niepożądane, ponieważ może to powodować, że rsync używa 32 GB. --inplace jest naprawdę przydatny tylko wtedy, gdy brakuje miejsca w systemie plików [czego nie masz] lub masz jakieś specjalne wymagania dotyczące wydajności.

Domyślam się, że rsync będzie chciał użyć 50 GB pamięci RAM [rozmiar pliku] z bieżącymi opcjami. Zwykle rsync nie potrzebuje tyle pamięci, aby wykonać swoje zadanie, więc problem może stanowić jedna lub więcej opcji. Rutynowo przesyłam pliki 200 GB bez problemu.

Wykonaj kilka testów bez żadnych opcji. Zrób to z mniejszymi plikami, powiedzmy 10 GB - to powinno zapobiec panice jądra, ale nadal pozwoli ci monitorować zachowanie, które powoduje problem. Monitoruj użycie pamięci rsync.

Stopniowo dodawaj opcje, pojedynczo, aby zobaczyć, która opcja [lub kombinacja opcji] powoduje, że rsync zaczyna wymazywać się w pamięci RAM (np. Podczas transferu trwa użycie pamięci RAM rsync rośnie proporcjonalnie do ilości przesyłanych danych pliku, itp.).

Jeśli naprawdę potrzebujesz opcji, które powodują, że rsync zachowuje obraz pliku w ramce, potrzebujesz dodatkowej przestrzeni wymiany, a maksymalny rozmiar pliku zostanie odpowiednio ograniczony.

Jeszcze kilka rzeczy [AKTUALIZACJA]:

(1) Śledzenie stosu jądra pokazuje, że rsync miał błąd strony w obszarze mmap. Prawdopodobnie kształtuje plik. mmap nie daje żadnej gwarancji, że opróżni się na dysk, dopóki plik nie zostanie zamknięty [w przeciwieństwie do odczytu / zapisu], który od razu trafia do pamięci podręcznej bloku FS [gdzie zostanie opróżniony]

(2) Awaria / panika jądra występuje, gdy rozmiar transferu osiąga rozmiar pamięci RAM. Najwyraźniej rsync pobiera tyle pamięci niefscache przez malloc lub mmap. Ponownie, z podanymi opcjami, rsync przydzieli 50 GB pamięci do przesłania pliku 50 GB.

(3) Prześlij plik 24 GB. To prawdopodobnie zadziała. Następnie uruchom jądro z mem = 16G i ponownie wykonaj test pliku 24GB. Wybuchnie przy 16 GB zamiast 32 GB. Potwierdzi to, że rsync naprawdę potrzebuje pamięci.

(4) Zanim powiesz, że dodanie swap jest śmieszne, spróbuj dodać [za pomocą metody swap-to-file]. Jest to o wiele łatwiejsze do zrobienia i przetestowania niż wszystkie akademickie argumenty dotyczące tego, że zamiana nie jest wymagana. Nawet jeśli nie jest to rozwiązanie, możesz się z tego czegoś nauczyć. Założę się, że test mem = 16G powiedzie się bez paniki / awarii.

(5) Jest szansa, że rsync jest uderzanie zamianę, ale zdarza się zbyt szybko, aby zobaczyć z góry przed kopnięciami OOM i zabija rsync. Zanim rsync osiągnie 32 GB, inne procesy zostały już zmuszone do zamiany, szczególnie jeśli są bezczynne. Być może połączenie „darmowego” i „górnego” da ci lepszy obraz.

(6) Po zabiciu rsync potrzeba czasu, aby spłukać mmap do FS. Nie jest wystarczająco szybki dla OOM i zaczyna zabijać inne rzeczy [niektóre są oczywiście krytyczne dla misji]. Oznacza to, że kolor mmapa i OOM ścigają się. Lub OOM ma błąd. W przeciwnym razie nie byłoby awarii.

(7) Z mojego doświadczenia wynika, że ​​kiedy system „uderza w ścianę pamięci”, Linux zajmuje dużo czasu, aby w pełni się zregenerować. I czasami tak naprawdę nigdy nie odzyskuje się prawidłowo, a jedynym sposobem na usunięcie jest ponowne uruchomienie. Na przykład mam 12 GB pamięci RAM. Kiedy uruchamiam zadanie, które wykorzystuje 40 GB pamięci [mam 120 GB wymiany, aby pomieścić duże zadania], a następnie go zabijam, powrót systemu do normalnego czasu reakcji zajmuje około 10 minut [z ciągłym świeceniem kontrolki dysku] .

(8) Uruchom rsync bez opcji. To zadziała. Uzyskaj podstawowy przykład do pracy. Następnie dodaj z powrotem - na miejscu i ponownie przetestuj. Następnie wykonaj --append-Verify. Następnie spróbuj obu. Dowiedz się, która opcja powoduje, że rsync robi ogromną mmapę. Następnie zdecyduj, czy możesz bez niego żyć. Jeśli - winowajcą jest --inplace, nie jest to żadnym problemem, ponieważ masz dużo miejsca na dysku. Jeśli musisz mieć tę opcję, musisz uzyskać przestrzeń wymiany, aby pomieścić malloc / mmap, które zrobi rsync.

DRUGA AKTUALIZACJA:

Wykonaj testy mem = i mniejsze pliki z powyższych.

Główne pytania: Dlaczego rsync zostaje zabity przez OOM? Kto / Co to jest pamięć do żucia?

Przeczytałem [ale zapomniałem] o systemie 32-bitowym. Tak więc, zgadzam się, rsync może nie być bezpośrednio odpowiedzialny (przez malloc / mmap - glibc implementuje duże malloc poprzez anonimowe / prywatne mmapy), a błąd strony mmap rsync po prostu wyzwala OOM przez przypadek. Następnie OOM oblicza całkowitą pamięć zajętą ​​przez rsync bezpośrednio i pośrednio [pamięć podręczną FS, bufory gniazd itp.] I decyduje, że jest to główny kandydat. Tak więc monitorowanie całkowitego zużycia pamięci może być pomocne. Podejrzewam, że skrada się z tą samą prędkością co transfer pliku. Oczywiście nie powinno.

Niektóre rzeczy, które możesz monitorować w / proc lub / proc / rsync_pid za pomocą skryptu perl lub python w szybkiej pętli [skrypt bash prawdopodobnie nie będzie wystarczająco szybki na zdarzenie końca świata], który może monitorować wszystkie następujące kilkaset razy / sek. Możesz uruchomić to z wyższym priorytetem niż rsync, aby utrzymywał się w pamięci RAM i działał, dzięki czemu możesz monitorować rzeczy tuż przed awarią i, mam nadzieję, podczas OOM, aby zobaczyć, dlaczego OOM wariuje:

/ proc / meminfo - aby uzyskać więcej drobnych ziaren na temat zamiany w „punkcie uderzenia”. W rzeczywistości bardziej przydatne może być uzyskanie ostatecznej liczby całkowitej ilości pamięci RAM. Chociaż zapewnia to góra, może nie być wystarczająco szybkie, aby pokazać stan wszechświata tuż przed „wielkim wybuchem” (np. Ostatnie 10 milisekund)

/ proc / rsync_pid / fd katalog. Czytanie dowiązań symbolicznych pozwoli ci określić, które fd jest otwarte w pliku docelowym (np. Readlink w / proc / rsync_pid / fd / 5 -> plik_docelowy). Prawdopodobnie należy to zrobić tylko raz, aby uzyskać numer fd [powinno pozostać naprawione]

Znając numer fd, spójrz na / proc / rsync_pid / fdinfo / fd. To plik tekstowy, który wygląda następująco:

pos: <pozycja_pliku>
flagi: blah_blah
mnt_id: blah_blah

Monitorowanie wartości „pos” może być pomocne, ponieważ przydatne może być „ostatnie położenie pliku”. Jeśli wykonasz kilka testów o różnych rozmiarach i opcjach mem =, czy ostatnia pozycja pliku śledzi którykolwiek z tych [i jak]? Zwykły podejrzany: pozycja pliku == dostępna pamięć RAM

Ale najprostszym sposobem jest rozpoczęcie od „rsync server_pliku lokalnego: plik_zdalny” i sprawdzenie, czy działa. Możesz być w stanie uzyskać podobne [ale szybsze] wyniki, robiąc "ssh server rsync plik_a plik_b" [musisz najpierw utworzyć 50 GB plik_a]. Prostym sposobem na utworzenie pliku_a jest system_lokalny scp: serwer_plików oryginalnych: plik_a i może to być interesujące samo w sobie (np. Czy działa to, gdy rsync ulega awarii? Jeśli scp działa, ale rsync nie działa, oznacza to rsync. Jeśli scp nie powiedzie się, wskazuje to do czegoś innego jak sterownik karty sieciowej). Wykonanie ssh rsync usuwa również NIC z równania, co może być pomocne. Jeśli to załączy system, coś jest naprawdę nie tak. Jeśli się powiedzie, [jak już wspomniałem] zacznij dodawać opcje jeden po drugim.

Nienawidzę omawiać tej kwestii, ale dodanie zamiany poprzez zamianę do pliku może zmienić / opóźnić awarię i może być przydatne jako narzędzie diagnostyczne. Jeśli dodanie, powiedzmy 16 GB, zamiany opóźnia awarię [mierzoną przez użycie pamięci lub docelową pozycję pliku] z 32 GB do 46 GB, to coś powie.

Może to nie być żaden konkretny proces, ale błędny sterownik jądra, który przeżuwa pamięć. Wewnętrzny vmalloc jądra przydziela rzeczy i można go wymienić. IIRC, nie jest związany adresowalnością we wszystkich okolicznościach.

Najwyraźniej OOM jest zdezorientowany / spanikowany. Oznacza to, że zabija rsync, ale nie widzi uwolnienia pamięci w odpowiednim czasie i szuka innych ofiar. Niektóre z nich są prawdopodobnie krytyczne dla działania systemu.

pomijając malloc / mmap, może to być spowodowane niewypełnioną pamięcią podręczną FS, która zajmuje dużo czasu (np. przy 30 GB nie zwolnionych danych, przy założeniu szybkości dysku 300 MB / s, opróżnienie może potrwać 100 sekund). Nawet przy takim tempie OOM może być zbyt niecierpliwy. Lub zabijanie rsync przez OOM nie uruchamia flusha FS wystarczająco szybko [lub wcale]. Lub flush FS następuje wystarczająco szybko, ale ma „leniwe” wydanie stron z powrotem do darmowej puli. Istnieje kilka opcji / proc, które można ustawić w celu kontrolowania zachowania pamięci podręcznej FS [nie pamiętam, jakie są].

Spróbuj uruchomić z mem = 4G lub inną małą liczbą. Może to skrócić pamięć podręczną FS i skrócić czas spłukiwania, aby OOM nie szukał innych rzeczy do zabicia (np. Czas spłukiwania został skrócony ze 100 do <1 sekundy). Może także zdemaskować błąd OOM, który nie obsługuje fizycznego RAMu> 4 GB w systemie 32-bitowym lub innym podobnym.

Ważny punkt: Uruchom jako użytkownik inny niż root. Użytkownicy root nie powinni żuć zasobów, więc otrzymują więcej wybaczających limitów (np. 99% pamięci w porównaniu do 95% dla użytkowników innych niż root). To może wyjaśniać, dlaczego OOM jest w takim stanie. Ponadto daje to OOM i in. glin. więcej miejsca na odzyskanie pamięci.

Craig Estey
źródło
Zobacz Ile miejsca SWAP w systemie o wysokiej pamięci? - i nie chcesz, aby Twój system używał 63 GB swapu. Nie będzie użyteczna.
Martin Schröder
1
zamiana> RAM jest naprawdę przydatna tylko wtedy, gdy uruchamiasz się bez komendy VM, więc jądro musi zarezerwować miejsce wymiany dla przydzielonych stron, dopóki nie zostaną zabrudzone i nie będą wymagały rzeczywistych fizycznych kopii zapasowych stron. Obecna praktyka polega na zezwoleniu na nadmierne zaangażowanie i uruchamianie z niewielką ilością przestrzeni wymiany, aby stronicować strony, które zostały dotknięte tylko podczas uruchamiania i nie są potrzebne w normalnym działaniu. overcommit = 0 przy małej zamianie jest w porządku, jeśli masz dużo pamięci RAM, w większości systemów.
Peter Cordes
Wydaje się, że rsync naprawdę próby użycia> 32GB, więc konwersja jest potrzebna do tego. Oznacza to, że rsync użyje 50 GB dla tego pliku. 2x jest sprawdzoną miarą od 30 lat. Ponieważ dysk o pojemności 6 TB kosztuje około 300 USD, nie ma powodu, aby tego nie robić. Co jeszcze może działać na tym serwerze, co zbiorowo przekroczy limit pamięci RAM?
Craig Estey
1
@CraigEstey 64 GB wymiany jest całkowicie niedorzeczne, ponieważ, jak wcześniej powiedziałem, nie mamy dużych procesów użytkownika, chcemy tylko pamięci podręcznej dysku, a jak pokazał mój dziennik, korzystaliśmy z wymiany ZERO w momencie awarii. ZERO. Również rsync używa 600 KB pamięci RAM, nawet w przypadku pliku 50 GB. Moje początkowe zamieszanie polegało na tym, że może linux agresywnie trzymał pamięć podręczną dysku. Na koniec chcę zobaczyć liczby lub dokumentację na temat ilości pamięci używanej przez jądro do śledzenia przestrzeni wymiany, zanim dodam więcej do tego pola.
dataless
@dataless Dodałem dodatkowe informacje, które w pełni wyjaśniają, co się dzieje i dlaczego. rsync jest chwytając pamięć za pomocą malloc / mmap i przejdzie do 50GB zanim to się robi. Zobacz zaktualizowaną sekcję. Ma testy, które mogą udowodnić / obalić to, co mówię, i możesz początkowo pominąć dodaną zamianę, aby przetestować. BTW, ja już zostały programowania jąder / sterowniki dla ponad 40 lat - może po prostu coś wiedzieć, że nie, więc proszę umiarkowany ton - ja jestem stara się pomóc.
Craig Estey
2

milczek? Wygląda na to, że używasz ClamAV i masz włączone skanowanie podczas uzyskiwania dostępu, w którym silnik antywirusowy próbuje skanować otwarte pliki w poszukiwaniu wirusów, ładując do pamięci całą zawartość każdego pliku otwartego przez inny proces .

W zależności od stanu bezpieczeństwa i konieczności tego transferu, należy rozważyć wyłączenie skanowania podczas uzyskiwania dostępu ClamAV podczas wykonywania transferu.

oo.
źródło
Nie wiedziałem, że jest to nawet coś, co Clamav może zrobić ... ale nie, skanujemy tylko określone pliki przesyłane do niego z clamc. Również 32-bitowy, więc nie ma niebezpieczeństwa zablokowania całej pamięci systemowej przez clamav. (rozumiesz, dlaczego uważaliśmy, że
wersja
1
Jądro Linux zgłasza, że ​​clamd jest procesem, którego żądania alokacji pamięci wywołują zabójcę OOM - ClamAV jest prawie na pewno wtórną przyczyną (główną przyczyną jest niewystarczająca ilość pamięci). Niezależnie od tego, czy jest to skanowanie podczas uzyskiwania dostępu, czy inna konfiguracja, wszystkie znaki wskazują na ClamAV.
oo.
Następnym razem, gdy uruchomisz rsync, uruchom top i monitoruj rozmiar rezydentny procesu clamd.
oo.
clamd był pierwszym procesem wywołującym Oom Killera, ale także pierwszym, który zginął, ponieważ waży prawie 42 MB (jeden z większych procesów na serwerze). Oom_killer działa wielokrotnie, aż zabije nawet metalog.
danych