Çoklu Çekirdek Kullanarak Sıkıştırmayı Hızlandırma: pigz ve pbzip2

Geçen ay bir müşterimizin sunucusunda 200GB’lık bir veritabanı yedeğini sıkıştırmam gerekti. Klasik gzip ile başlattım işlemi, kahvemi aldım, döndüm, hâlâ devam ediyordu. Yarım saat sonra bakıyorum, 8 çekirdekli sunucunun sadece bir çekirdeği %100’de koşuyor, diğerleri uyuyor. İşte tam bu noktada pigz ve pbzip2 hayatıma girdi ve o günden sonra tek çekirdekli sıkıştırma araçlarına geri dönmek zor geldi.

Sorun: Geleneksel Sıkıştırma Araçları Tek Çekirdekte Çalışır

gzip, bzip2 ve xz gibi araçlar, onlarca yıl önce tasarlandı. O dönemde çok çekirdekli işlemciler yaygın değildi, dolayısıyla bu araçlar paralel işlem için yazılmadı. Bugün elimizde 16, 32, hatta 64 çekirdekli sunucular var ama klasik gzip bunların sadece birini kullanıyor.

Büyük dosyalarla çalışan bir sistem yöneticisi için bu ciddi bir darboğaz. Sabah 03:00’teki yedekleme penceresi dolmadan işin bitmesi gerekiyor, production veritabanı dump’ı bir an önce aktarılmalı, CI/CD pipeline’ındaki artifact sıkıştırması dakikalar değil saniyeler almalı. Bunların hepsi için paralel sıkıştırma şart.

pigz Nedir, Nasıl Çalışır?

pigz (Parallel Implementation of GZip), gzip‘in çok çekirdekli versiyonu olarak düşünülebilir. Zlib ve gzip formatlarıyla tam uyumlu çıktı üretir. Yani pigz ile sıkıştırdığınız dosyayı sıradan gzip veya gunzip ile açabilirsiniz. Bu geriye dönük uyumluluk, production ortamlarında çok kritik.

Çalışma mantığı şöyle: Girdi dosyasını bloklara böler, her bloğu ayrı bir thread’e verir, sıkıştırılmış blokları sıraya koyarak birleştirir. Varsayılan blok boyutu 128KB’dır. CPU’ların tamamını kullanarak teorik olarak N çekirdekte N kat hızlanma sağlayabilirsiniz; tabii I/O darboğazı olmadığı sürece.

Kurulum

Çoğu dağıtımda paket deposundan direkt kurulur:

# Debian/Ubuntu
apt install pigz

# RHEL/CentOS/AlmaLinux
dnf install pigz

# Arch Linux
pacman -S pigz

Temel Kullanım

Kullanım sözdizimi gzip ile neredeyse birebir aynı:

# Tek dosya sıkıştırma
pigz buyuk_dosya.tar

# Birden fazla CPU kullanma sayısını belirtme (-p ile)
pigz -p 8 buyuk_dosya.tar

# Sıkıştırma seviyesi belirleme (1-9, varsayılan 6)
pigz -9 -p 16 veritabani_yedek.sql

# Dosyayı açma
pigz -d arsiv.gz
# veya
unpigz arsiv.gz

# İçeriği listele (gzip uyumlu)
pigz -l arsiv.gz

tar ile entegrasyon son derece temiz:

# Klasik tar.gz oluşturma ama pigz ile
tar -I pigz -cvf yedek.tar.gz /var/www/html/

# Alternatif yöntem: pipe kullanarak
tar -cv /opt/uygulama | pigz -p 8 > uygulama_yedek.tar.gz

# Açma işlemi
tar -I pigz -xvf yedek.tar.gz

Önemli pigz Parametreleri

-p [sayı]: Kullanılacak işlemci thread sayısını belirler. Belirtilmezse sistemdeki tüm çekirdekler kullanılır.

-1 ile -9: Sıkıştırma seviyesi. -1 en hızlı ama en az sıkıştırma, -9 en yavaş ama en iyi sıkıştırma oranı.

-k: Orijinal dosyayı sildirmez, korur.

-c: Çıktıyı stdout’a yazar, dosyayı yerinde sıkıştırmaz.

-d: Açma (decompress) modu.

-r: Dizin içinde özyinelemeli sıkıştırma.

–best: -9 ile eşdeğer, maksimum sıkıştırma.

–fast: -1 ile eşdeğer, maksimum hız.

-b [blok boyutu]: KB cinsinden blok boyutu. Varsayılan 128, büyük dosyalar için 256 veya 512 deneyin.

pbzip2 ile Paralel bzip2

pbzip2, bzip2‘nin paralel versiyonu. pigz‘e benzer mantıkla çalışır ama bzip2 algoritmasını kullanır. bzip2, gzip’e kıyasla genellikle daha iyi sıkıştırma oranı sunar ama daha yavaştır; paralel versiyonu bu denklemi değiştirir.

Kurulum

# Debian/Ubuntu
apt install pbzip2

# RHEL/CentOS/AlmaLinux
dnf install pbzip2

Temel Kullanım

# Dosya sıkıştırma
pbzip2 buyuk_dosya.tar

# CPU sayısı belirterek
pbzip2 -p8 buyuk_dosya.tar

# Açma
pbzip2 -d arsiv.bz2
# veya
pbunzip2 arsiv.bz2

# tar ile kullanım
tar -I pbzip2 -cvf yedek.tar.bz2 /home/kullanici/

# Pipe yöntemi
tar -cv /var/lib/mysql | pbzip2 -p8 > mysql_yedek.tar.bz2

Önemli pbzip2 Parametreleri

-p[sayı]: Kullanılacak işlemci sayısı (boşluk olmadan yazılır, pbzip2 -p8 gibi).

-b[boyut]: Blok boyutu, 100KB biriminde. -b9 demek 900KB blok boyutu demek.

-1 ile -9: Sıkıştırma seviyesi.

-k: Orijinal dosyayı koru.

-c: Stdout’a yaz.

-d: Açma modu.

-t: Test modu, dosyanın bütünlüğünü kontrol eder.

-v: Verbose mod, ilerlemeyi gösterir.

Gerçek Dünya: PostgreSQL Yedekleme Senaryosu

Benim asıl kullanım alanım veritabanı yedekleri. Tipik bir production PostgreSQL sunucusunda şöyle bir şey çalışıyordu:

#!/bin/bash
# Eski yöntem - tek çekirdek, yavaş
pg_dump -U postgres mydb | gzip > /backup/mydb_$(date +%Y%m%d).sql.gz

# Yeni yöntem - tüm çekirdekler, hızlı
pg_dump -U postgres mydb | pigz -p $(nproc) -6 > /backup/mydb_$(date +%Y%m%d).sql.gz

nproc komutu mevcut CPU çekirdeği sayısını döndürür, böylece script farklı sunucularda da doğru şekilde çalışır. Ama dikkat: Bir production sunucusunda tüm çekirdekleri sıkıştırmaya vermek istemeyebilirsiniz. Ben genellikle $(( $(nproc) / 2 )) kullanarak mevcut çekirdeklerin yarısını kullanırım, geri kalanını production trafiğine bırakırım.

# Çekirdeklerin yarısını kullan
CORES=$(( $(nproc) / 2 ))
pg_dump -U postgres buyuk_db | pigz -p $CORES > /backup/buyuk_db_yedek.sql.gz

Gerçek Dünya: Log Arşivleme

Log sıkıştırma başka bir klasik senaryo. /var/log altındaki eski logları arşivlemek:

# Tüm eski nginx loglarını paralel sıkıştır
find /var/log/nginx -name "*.log" -mtime +7 | xargs -P 4 pigz -9

# Büyük tek bir log dosyasını sıkıştır
pigz -p 8 -9 /var/log/uygulama/access_2024.log

# Dizini tar.gz olarak arşivle
tar -cv /var/log/eski_loglar/ | pigz -p 4 > /archive/loglar_$(date +%Y%m).tar.gz

xargs -P 4 ile birden fazla dosyayı aynı anda sıkıştırabilirsiniz, bu da küçük dosyalar için pigz‘in tek başına vereceğinden daha iyi performans sağlar çünkü küçük dosyalarda thread overhead’i baskın çıkabilir.

Performans Karşılaştırması: Rakamlar Konuşsun

Teorik konuşmak yerine somut bir test yapalım. 8 çekirdekli bir sunucuda 10GB’lık bir SQL dump dosyasıyla yapılan test:

# gzip ile süreyi ölç
time gzip -6 -k test_dosya_10gb.sql

# pigz ile süreyi ölç (8 thread)
time pigz -6 -p 8 -k test_dosya_10gb.sql

# bzip2 ile
time bzip2 -6 -k test_dosya_10gb.sql

# pbzip2 ile (8 thread)
time pbzip2 -6 -p8 -k test_dosya_10gb.sql

Tipik sonuçlar: gzip 8-10 dakika alırken pigz -p 8 aynı işi 1.5-2 dakikada bitirir. bzip2 15-20 dakika sürüyorken pbzip2 -p8 ile 3-4 dakikaya iner. Sıkıştırma oranları ise tamamen aynı kalır, paralel işlem sıkıştırma kalitesini etkilemez.

pxz ile xz Formatında Paralel Sıkıştırma

xz formatını kullananlar için pxz veya xz‘nin kendi paralel seçeneği de var:

# xz zaten -T parametresiyle paralel çalışabiliyor
xz -T 8 -6 buyuk_dosya.tar

# Tüm çekirdekleri kullan (0 = otomatik)
xz -T 0 buyuk_dosya.tar

# tar ile
tar -cv /opt/data | xz -T 8 > arsiv.tar.xz

xz formatı en iyi sıkıştırma oranını sunar ama en yavaş algoritmadır. -T 0 ile tüm çekirdekleri verseniz bile gzip kadar hızlı olmayabilir. Depolama alanı kritikse xz, hız kritikse pigz seçin.

Dikkat Edilmesi Gereken Noktalar

I/O Darboğazı

Paralel sıkıştırmanın en büyük düşmanı disk I/O’dur. 16 çekirdek kullanıyorsunuz ama hard disk saniyede 100MB okuyabiliyorsa, 16 thread sadece birbirini bekler. Bu durumda çekirdek sayısını artırmak pek bir şey kazandırmaz. NVMe SSD veya RAID array’lerde fark çok daha belirgindir.

# Önce disk hızını ölçün
dd if=/dev/zero of=/tmp/test bs=1G count=5 oflag=direct
dd if=/tmp/test of=/dev/null bs=1G

Bellek Kullanımı

pbzip2 özellikle bellek konusunda dikkatli olunmasını gerektirir. Her thread kendi blok tamponu için bellek ayırır. -p16 -b9 gibi agresif ayarlarla belirgin miktarda RAM kullanabilirsiniz. Belleği kısıtlı sistemlerde bu dengeyi gözetin.

Decompress Hızı

pigz açma işleminde de paralel çalışabilir ama gzip formatının yapısı gereği açma işlemi sıkıştırma kadar paralel verimli değildir. Yine de tek çekirdekli gunzip‘ten daha hızlıdır.

pbzip2 açma işleminde ise tam paralel çalışır çünkü bzip2 blok yapısı buna uygundur. Büyük .bz2 dosyalarını açarken pbzip2 -d kullanmak ciddi zaman kazandırır.

Mevcut Script’lerde Drop-in Replacement

pigz‘i doğrudan gzip yerine symlink ile de kullanabilirsiniz:

# Dikkatli yapın, sistem araçlarını bozmayın
# Bunun yerine alias kullanmak daha güvenli
echo "alias gzip='pigz'" >> ~/.bashrc
echo "alias gunzip='unpigz'" >> ~/.bashrc
source ~/.bashrc

Ya da script’lerinizde şu pattern’i kullanın:

# gzip varsa pigz, yoksa gzip kullan
GZIP_CMD=$(which pigz 2>/dev/null || which gzip)
$GZIP_CMD -6 -p 4 buyuk_dosya.tar

Gelişmiş Senaryo: Uzak Sunucuya Paralel Aktarım

Sıkıştırıp ağ üzerinden aktarırken pipeline kullanmak hem zaman hem disk alanı kazandırır:

# Yerel olarak sıkıştırıp uzak sunucuya gönder
tar -cv /opt/uygulama | pigz -p 8 | ssh kullanici@uzak-sunucu "cat > /backup/uygulama.tar.gz"

# Uzak sunucudan alıp yerel'e aç
ssh kullanici@uzak-sunucu "cat /backup/buyuk_arsiv.tar.gz" | pigz -d | tar -xv -C /opt/restore/

# rsync ile birlikte (sıkıştırma rsync'e bırakılırsa)
# Ama büyük dosyalarda önceden sıkıştırıp rsync etmek daha verimli
pigz -p 4 -c /var/lib/mysql/dump.sql > /tmp/dump.sql.gz
rsync -avz /tmp/dump.sql.gz kullanici@uzak:/backup/

Cron ile Otomatik Yedekleme Entegrasyonu

Production’da kullandığım basit bir yedekleme script’i:

#!/bin/bash
set -euo pipefail

BACKUP_DIR="/backup/veritabani"
DB_NAME="production_db"
TARIH=$(date +%Y%m%d_%H%M%S)
CORES=$(( $(nproc) > 4 ? 4 : $(nproc) ))  # En fazla 4 çekirdek kullan

mkdir -p "$BACKUP_DIR"

echo "[$(date)] Yedekleme basliyor: $DB_NAME"

pg_dump -U postgres "$DB_NAME" | 
  pigz -p "$CORES" -6 > "$BACKUP_DIR/${DB_NAME}_${TARIH}.sql.gz"

echo "[$(date)] Yedekleme tamamlandi: $(du -sh $BACKUP_DIR/${DB_NAME}_${TARIH}.sql.gz)"

# 30 günden eski yedekleri temizle
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete

echo "[$(date)] Eski yedekler temizlendi"

Bu script’te CORES hesaplaması önemli: nproc değeri 4’ten büyükse 4 çekirdek kullan, değilse mevcut tüm çekirdekleri kullan. Production sunucularda agresif kaynak kullanımından kaçınmak gerekir.

Hangi Aracı Hangi Durumda Kullanmalı?

Sıkıştırma formatı seçimi çoğunlukla ortamınıza bağlıdır. Pratik önerilerim şöyle:

  • pigz: Mevcut gzip iş akışınızı paralel hale getirmek için ideal. .tar.gz veya .gz formatı gerektiğinde ilk tercih. Gzip uyumlu çıktı istiyorsanız başka seçenek aramayın.
  • pbzip2: daha iyi sıkıştırma oranı isteyip .bz2 formatıyla çalışmanız gerektiğinde. PostgreSQL ve bazı eski sistemler bzip2 tercih eder.
  • xz -T 0: Maksimum sıkıştırma oranı şartysa ve hız ikinci plandaysa. Depolama maliyeti yüksekse, paket dağıtımında, uzun vadeli arşivlemede kullanın.
  • Küçük dosyalar için: Hiçbiri. Onlarca küçük dosya için tar ile önce bir arşiv oluşturun, sonra sıkıştırın. Thread overhead’i küçük dosyalarda kazancı sıfırlayabilir.

Sonuç

pigz ve pbzip2, sistem yöneticisinin araç kutusunda olması gereken basit ama etkili araçlar. Kurulumu dakika alıyor, mevcut iş akışlarına entegrasyonu neredeyse sıfır maliyetli ve kazanılan zaman bazen saatleri buluyor.

Özellikle yedekleme penceresi kısıtlı ortamlarda, büyük log arşivlerinde ve pipeline tabanlı veri aktarımlarında bu araçların farkını ilk kullanışta hissediyorsunuz. 8 çekirdekli bir sunucuda 6-7 kat hızlanma elde etmek, kahvenizin soğumasını beklemeden yedeklemenin bitmesini görmek, küçük ama tatmin edici bir his.

Son olarak: Bu araçları production’a almadan önce test ortamında deneyin, sıkıştırılmış dosyalarınızın bütünlüğünü pigz -t veya pbzip2 -t ile doğrulayın ve yedekleme script’lerinizi set -e ile yazın ki hata durumunda sessizce geçip gitmesin. Paralel çalışmak hızlıdır, ama hızlı ve güvenilir çalışmak daha iyidir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir