Sunucu yanıt vermiyor, SSH birkaç saniyelik gecikmeyle açılıyor ve dmesg içinde Out of memory: Killed process 21834 (mysqld) gibi bir satır duruyor. Ya da tam tersi: free -h çalıştırıyorsunuz ve swap'ın tamamen dolu olduğunu ama CPU'nun boşta olduğunu ve her şeyin yavaşladığını görüyorsunuz. Bu iki durumun sorunu aynı ama çözümleri aynı değil. Doğru karar, önce hangisine sahip olduğunuzu anlamaktır.
Önce gerçekten bellek yetersizliği olup olmadığını görün
Herhangi bir değişiklikten önce sayı alın. Bu üç komut tam resmi verir:
free -m
vmstat 1 5
cat /proc/meminfo | grep -E 'MemAvailable|SwapTotal|SwapFree'
vmstat çıktısında iki sütun önemlidir: si ve so (saniyede kilobayt cinsinden swap in/out). Bu iki sayı sürekli sıfırın üzerinde kalıyorsa, sistem RAM ile disk arasında gidip geliyor demektir ve her disk işlemi birkaç kat daha yavaş tamamlanır. Eğer si ve so sıfırsa ve yalnızca SwapUsed yüksekse, o swap ölüdür; bir kez dışarı atılmış ve kimsenin aramadığı sayfalar. Bu durum sorun değildir.
Çoğu kişinin gözden kaçırdığı nokta: eski free çıktısı buff/cache sütununu ayrı gösterir ve insan RAM'in dolu olduğunu sanır. Doğru ölçüt MemAvailable'dır, MemFree değil. Çekirdek disk önbelleğini gerektiğinde serbest bırakır.
Swap dosyası eklemek; VPS'te işe yarayan yöntem
Önceden swap bölümü olmayan makinelerde (çoğu VPS), swap dosyası en hızlı yoldur. 2 gigabaytlık bir sunucu için 2 gigabaytlık bir dosya makul bir başlangıç noktasıdır:
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
fstab satırını unutmayın; yoksa yeniden başlatmadan sonra her şey eski haline döner ve siz ayarların çalışmadığını düşünürsünüz. Kontrol için: swapon --show ve free -h.
Pratik bir uyarı: bazı dosya sistemlerinde (eski XFS veya konteynerlerdeki overlayfs gibi) fallocate swap yapılamayan bir dosya oluşturur. Eğer swapon swapon failed: Invalid argument hatası verirse, dd ile oluşturun:
dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
Bulut altyapısında çalışıyorsanız ve sistem diski ağ tabanlıysa, aynı disk üzerinde swap neredeyse işe yaramaz çünkü IOPS paylaşımlı ve düşüktür. Bu durumda ya yerel NVMe diskli bir bulut sunucu kullanmalısınız ya da özel diski olan sunuculara yönelmelisiniz.
swappiness; herkesin yanlış ayarladığı sayı
Günümüz çekirdeklerinde vm.swappiness varsayılan değeri 60'tır. Bu sayı yüzde değildir; çekirdeğin kullanılmayan sayfaları dışarı atmaya karşı dosya önbelleğini serbest bırakmaya ne kadar istekli olduğunu söyleyen bir ağırlıktır. Sıfır değeri "mümkün olduğunca swap yapma" demektir, "asla swap yapma" değil.
sysctl vm.swappiness=10
echo 'vm.swappiness=10' >> /etc/sysctl.d/99-swap.conf
Veritabanı sunucusunda 10 mantıklıdır. Değişken trafikli web sunucusunda 20 ila 30 daha iyi sonuç verir çünkü dosya önbelleğinin canlı kalmasına izin verir. Sıfır değerini yalnızca gerçekten ne yaptığınızı biliyorsanız koyun; sonucu, RAM tükendiğinde çekirdeğin swap yapmak yerine doğrudan OOM Killer'a gitmesidir.
Bir de çok az kişinin başvurduğu başka bir parametre var: vm.vfs_cache_pressure. Eğer slabtop dentry ve inode_cache'in RAM'in büyük bir kısmını kapladığını gösteriyorsa, bu değeri 50'ye düşürmek çekirdeğin bu önbellekleri daha geç serbest bırakmasına yardımcı olur.
Burada hata yapıyorlar
Gördüğüm en yaygın hata şudur: sunucu yavaşlar, yönetici sekiz gigabaytlık bir swap dosyası oluşturur, free yeşile döner ve sorun "çözülür". İki hafta sonra aynı sunucu 40 yükle ve birkaç saniyelik yanıt gecikmesiyle geri döner, ama bu sefer logda hiçbir OOM hatası yoktur.
İşaret tam olarak şudur: iostat -x 1 diskin %util değerinin 100'e yakın olduğunu gösterir, vmstat içinde si ve so sürekli inip çıkar ve veritabanı yanıt süresi iki haneli olur. Swap burada hiçbir şeyi çözmedi; yalnızca uygulama ile bellek arasına yavaş bir disk katmanı koyarak sorunun daha geç patlamasını sağladı. Bellek kullanımınız sürekli artıyorsa, sorun RAM yetersizliği değil uygulamadaki bir bellek sızıntısıdır.
İkinci hata: swap'ı veritabanının bulunduğu diske koymak. Swap yapılan her sayfa, veritabanı sorgularıyla rekabet eden bir I/O oluşturur. Mecbursanız swap'ı ayrı bir diske koyun.
Swap ne kadar olmalı
| Durum | Önerilen boyut | Neden |
|---|---|---|
| Düşük RAM'li web sunucusu (1 ila 2 GB) | RAM'e eşit veya iki katı | Trafik zirvesinde OOM'u önlemek için |
| Özel veritabanı sunucusu | 1 ila 2 GB, sabit | Yalnızca soğuk sayfalar için; fazlası tehlikelidir |
| Yüksek RAM'li makine (32 GB ve üzeri) | 2 ila 4 GB | Bu makinelerde büyük swap yalnızca güvenlik yanılsaması verir |
| Konteyner veya paylaşımlı VPS | Sağlayıcı sınırına göre | Fazla swap disk kotasını doldurabilir |
Eski "RAM'in iki katı" kuralı 512 megabaytlık RAM'ler döneminden gelir ve bugün yanlıştır. 64 gigabaytlık bir makinede 128 gigabaytlık swap hiçbir işe yaramaz ve yalnızca disk alanını yer.
Swap işe yaramadığında
Tüm bu ayarlardan sonra hâlâ si/so yüksek kalıyorsa, sorun ayarlar değil kapasitedir. Üç yol var: RAM'i artırmak, tüketimi azaltmak (örneğin innodb_buffer_pool_size veya PHP-FPM'de pm.max_children değerini sınırlamak) ya da yükü başka bir makineye taşımak. Herhangi birinden önce, hangi sürecin gerçekten bellek yediğini bilmek için ps aux --sort=-rss | head -20 çıktısına bakın.
Yüksek yükünüz varsa ama kaynağının bellek mi, I/O mu yoksa CPU mu olduğundan emin değilseniz, sunucu yüksek yükünün nedenini teşhis etme kılavuzu doğru inceleme sırasını gösterir. Ağır ve istikrarlı yükü olan sunucular için, yeterli RAM'li bir özel sunucu genellikle herhangi bir swap hilesinden daha ucuza gelir.
Kararlılık hakkında son bir not: Sunucunuzda swap'ı etkinleştiriyorsanız, MySQL ve Redis gibi kritik servislerin bellek baskısı altında herkesten önce kurban edilmeyecek şekilde ayarlandığından emin olun. Servis biriminin systemd dosyasında OOMScoreAdjust veya /proc/<pid>/ içinde oom_score_adj ayarlamak bu kontrolü verir. Bu olmadan çekirdek veritabanınızı öldürüp web sunucusunu canlı tutabilir; tam da istediğinizin tersini.
Sık sorulan sorular
Swap'ın etkin olması sunucuyu yavaşlatır mı?
Swap'ın kendisi yavaş değildir; onun aktif kullanımı yavaştır. Eğer vmstat si ve so değerlerinin sıfıra yakın olduğunu gösteriyorsa, swap yalnızca kullanılmayan sayfaları tutuyor ve performans üzerinde hiçbir etkisi yoktur. Sorun, sistem sürekli RAM ile disk arasında gidip gelmeye başladığında ortaya çıkar.
Veritabanı sunucusu için uygun vm.swappiness değeri nedir?
MySQL veya PostgreSQL için genellikle 10 iyi bir değerdir. Sıfır koyarsanız, çekirdek swap yapmak yerine doğrudan OOM Killer'a gider ve veritabanı sürecini kaybedebilirsiniz. Varsayılan 60 değeri de veritabanı sunucusunda genellikle fazla agresiftir.
Swap'ım olup olmadığını nasıl anlarım?
swapon --show komutu etkin swap dosyalarını ve bölümlerini listeler. Çıktı boşsa swap'ınız yoktur. free -h komutu da Swap satırında toplam ve kullanılan miktarı verir.
Swap'ı yeniden başlatmadan kaldırabilir miyim?
Evet. Önce swapoff /swapfile çalıştırın, sonra ilgili satırı /etc/fstab dosyasından silin ve dosyayı silin. Yalnızca dikkat edin, bellek kullanımı RAM sınırına yakınsa swapoff anında OOM'a neden olabilir. Öncesinde free -m ile yeterli alanınız olduğundan emin olun.