Veritabanı katmanında tek nokta arızası (single point of failure) yaşamak, gecenin üçünde telefon almak demektir. MySQL Galera Cluster tam da bu kabusu önlemek için var. Birden fazla node üzerinde senkron replikasyon yaparak hem yüksek erişilebilirlik hem de otomatik failover sağlar. Bu yazıda sıfırdan kurulumdan, izleme ve sorun gidermeye kadar her şeyi ele alacağız.
Galera Cluster Nedir ve Nasıl Çalışır?
Galera, MySQL/MariaDB üzerine inşa edilmiş bir senkron multi-master replikasyon kütüphanesidir. Klasik MySQL master-slave yapısından temel farkı şudur: Galera’da her node hem okuma hem yazma kabul eder ve bir transaction commit edilebilmesi için cluster’daki node’ların çoğunluğunun onayı gerekir. Bu mekanizmaya writeset replication denir.
Temel çalışma prensibi şöyle özetlenebilir:
- Senkron replikasyon: Bir node’a yazılan veri, commit anında tüm node’lara yayılır, asenkron gecikmesi yoktur.
- Certification based replication: Her transaction bir writeset olarak paketlenir ve tüm node’larda çakışma kontrolünden geçer.
- Automatic node provisioning: Yeni bir node cluster’a katıldığında SST (State Snapshot Transfer) veya IST (Incremental State Transfer) ile otomatik senkronize olur.
- Quorum mekanizması: Node sayısının yarısından fazlası ayakta olduğu sürece cluster çalışmaya devam eder. Bu yüzden minimum 3 node önerilir.
Galera’nın bir dezavantajı da var: Her yazma işlemi tüm node’lara yayıldığı için ağ gecikmesi kritik hale gelir. Aynı datacenter içinde harika çalışır ama coğrafi olarak dağık node’larda dikkatli olunmalıdır.
Lab Ortamı ve Ön Hazırlık
Bu yazıda 3 node’lu bir Galera Cluster kuracağız. Sunucu bilgileri şu şekilde:
- galera-node1: 192.168.10.11
- galera-node2: 192.168.10.12
- galera-node3: 192.168.10.13
İşletim sistemi olarak Ubuntu 22.04 kullanıyorum, MariaDB 10.11 üzerinde Galera 4 çalışacak. Tüm komutları aksi belirtilmedikçe her üç node’da da çalıştırmanız gerekiyor.
Sistem Hazırlığı
Önce hostname ve hosts ayarlarını yapalım. Her node’da kendi hostname’ini ve diğerlerinin IP-hostname eşleşmelerini /etc/hosts dosyasına ekleyelim:
# Her node'da ilgili hostname'i set et
# galera-node1 üzerinde:
hostnamectl set-hostname galera-node1
# /etc/hosts dosyasına tüm node'larda ekle:
cat >> /etc/hosts << 'EOF'
192.168.10.11 galera-node1
192.168.10.12 galera-node2
192.168.10.13 galera-node3
EOF
Firewall kurallarını da ayarlamamız gerekiyor. Galera şu portları kullanır:
- 3306: MySQL istemci bağlantıları
- 4444: SST (State Snapshot Transfer)
- 4567: Galera cluster replikasyon trafiği (TCP ve UDP)
- 4568: IST (Incremental State Transfer)
# UFW ile port açma (tüm node'larda)
ufw allow from 192.168.10.0/24 to any port 3306
ufw allow from 192.168.10.0/24 to any port 4444
ufw allow from 192.168.10.0/24 to any port 4567
ufw allow from 192.168.10.0/24 to any port 4568
ufw reload
MariaDB ve Galera Kurulumu
# MariaDB repository ekle
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup |
sudo bash -s -- --mariadb-server-version="mariadb-10.11"
# Galera dahil MariaDB kur
apt update
apt install -y mariadb-server mariadb-client galera-4 rsync
# Servisi şimdilik durdur
systemctl stop mariadb
Kurulum tamamlandıktan sonra temel güvenlik ayarlarını yapalım:
# mysql_secure_installation çalıştır
mysql_secure_installation
# Root şifresi belirle, anonymous user kaldır, test db kaldır
Galera Konfigürasyonu
Bu adım en kritik kısım. Her node’da /etc/mysql/conf.d/galera.cnf dosyasını oluşturacağız. İçerik node’dan node’a küçük farklılıklar gösteriyor.
galera-node1 için /etc/mysql/conf.d/galera.cnf:
cat > /etc/mysql/conf.d/galera.cnf << 'EOF'
[mysqld]
# Temel Galera ayarları
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0
# Galera Provider
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
# Cluster ayarları
wsrep_cluster_name="galera_production"
wsrep_cluster_address="gcomm://192.168.10.11,192.168.10.12,192.168.10.13"
# Node kimlik bilgileri
wsrep_node_address="192.168.10.11"
wsrep_node_name="galera-node1"
# SST yöntemi
wsrep_sst_method=rsync
# Performance ayarları
wsrep_slave_threads=4
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=1G
EOF
Node2 ve Node3 için sadece wsrep_node_address ve wsrep_node_name satırlarını değiştirmeniz yeterli:
# galera-node2 için bu iki satırı değiştir:
wsrep_node_address="192.168.10.12"
wsrep_node_name="galera-node2"
# galera-node3 için:
wsrep_node_address="192.168.10.13"
wsrep_node_name="galera-node3"
Bazı önemli parametreleri açıklayalım:
- wsrep_on=ON: Galera replikasyonunu aktif eder.
- innodb_autoinc_lock_mode=2: Multi-master ortamında auto increment çakışmalarını önler, interleaved modu kullanır.
- binlog_format=ROW: Galera sadece ROW formatını destekler, statement-based çalışmaz.
- wsrep_sst_method=rsync: Yeni node eklenirken tam snapshot için rsync kullanılır. Mariabackup da iyi bir alternatiftir, özellikle büyük veritabanlarında downtime’ı azaltır.
- wsrep_slave_threads=4: Replikasyon için kullanılacak thread sayısı. CPU core sayısının 1-1.5 katı genellikle iyi bir başlangıç noktasıdır.
Cluster’ı Başlatma
İlk bootstrap işlemi önemli. Cluster’ı sıfırdan başlatmak için ilk node’u özel bir komutla açmamız gerekiyor:
# SADECE galera-node1 üzerinde, ilk kez başlatmak için:
galera_new_cluster
# Cluster durumunu kontrol et
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size';"
# Sonuç: 1 (henüz sadece bu node var)
Şimdi diğer node’ları normal şekilde başlatabiliriz:
# galera-node2 ve galera-node3 üzerinde:
systemctl start mariadb
# Birkaç saniye bekle, sonra node1'de kontrol et:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep%';"
wsrep_cluster_size değerinin 3 olduğunu görmeniz gerekiyor. wsrep_local_state_comment ise Synced olmalıdır.
Cluster Sağlık Kontrolü
Galera’yı izlemek için kullanabileceğiniz temel sorguları bir script haline getirelim:
#!/bin/bash
# galera_health_check.sh
MYSQL_USER="root"
MYSQL_PASS="sifreniz"
LOG_FILE="/var/log/galera_health.log"
check_galera() {
local host=$1
echo "=== $host Galera Durumu ===" | tee -a $LOG_FILE
mysql -u $MYSQL_USER -p$MYSQL_PASS -h $host -e "
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME IN (
'WSREP_CLUSTER_SIZE',
'WSREP_CLUSTER_STATUS',
'WSREP_LOCAL_STATE_COMMENT',
'WSREP_READY',
'WSREP_FLOW_CONTROL_PAUSED',
'WSREP_CERT_DEPS_DISTANCE'
);
" 2>/dev/null | tee -a $LOG_FILE
}
for node in 192.168.10.11 192.168.10.12 192.168.10.13; do
check_galera $node
done
# Kritik değerleri kontrol et
CLUSTER_SIZE=$(mysql -u $MYSQL_USER -p$MYSQL_PASS -e
"SHOW STATUS LIKE 'wsrep_cluster_size';" 2>/dev/null | awk '/wsrep_cluster_size/{print $2}')
if [ "$CLUSTER_SIZE" -lt 3 ]; then
echo "UYARI: Cluster size $CLUSTER_SIZE! Bir veya daha fazla node kayıp!" |
tee -a $LOG_FILE
# Buraya alert mekanizmanı ekle (mail, slack webhook vs.)
fi
Bu scripti cron ile her 5 dakikada bir çalıştırabilirsiniz:
chmod +x /usr/local/bin/galera_health_check.sh
echo "*/5 * * * * root /usr/local/bin/galera_health_check.sh" > /etc/cron.d/galera_health
HAProxy ile Load Balancing
Galera her node’un yazma kabul etmesiyle birlikte gelir ama uygulama katmanında hangi node’a bağlanacağınızı yönetmek için bir load balancer gereklidir. HAProxy bu iş için mükemmeldir. Ayrı bir sunucuya (veya keepalived ile iki HAProxy’yi aktif-pasif yapılandırarak) kurabilirsiniz:
apt install -y haproxy
cat > /etc/haproxy/haproxy.cfg << 'EOF'
global
log /dev/log local0
maxconn 50000
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
# İstatistik arayüzü
listen stats
bind *:8080
stats enable
stats uri /haproxy_stats
stats refresh 10s
stats auth admin:guclu_sifre
# MySQL yük dengeleme
listen mysql_cluster
bind *:3306
mode tcp
balance leastconn
option mysql-check user haproxy_check
server galera-node1 192.168.10.11:3306 check weight 1
server galera-node2 192.168.10.12:3306 check weight 1
server galera-node3 192.168.10.13:3306 check weight 1
EOF
systemctl restart haproxy
HAProxy’nin MySQL health check yapabilmesi için cluster’da özel bir kullanıcı oluşturun:
# Herhangi bir Galera node'unda çalıştır, tüm node'lara yayılır:
mysql -u root -p -e "
CREATE USER 'haproxy_check'@'%' IDENTIFIED BY '';
FLUSH PRIVILEGES;
"
Gerçek Dünya Senaryosu: Node Kaybı ve Recovery
Üretim ortamında en sık karşılaştığım senaryo şu: Bir node beklenmedik şekilde kapanıyor, diskten doluyor veya network bölünmesi (split-brain) yaşanıyor.
Normal Node Kaybı
Bir node kapandığında Galera otomatik olarak devam eder (quorum korunduğu sürece). Node tekrar ayağa kalktığında IST ile otomatik senkronize olur:
# node2 çöktükten sonra tekrar başlatma
systemctl start mariadb
# Senkronizasyon durumunu izle
watch -n 1 'mysql -u root -p"sifre" -e "SHOW STATUS LIKE "wsrep_local_state_comment";" 2>/dev/null'
# Joining -> Joined -> Synced geçişini göreceksin
Split-Brain Durumu
2 node’un birbirinden haberdar olamadığı ama her ikisinin de çalışmaya devam ettiği durum tehlikelidir. Galera quorum mekanizması sayesinde azınlıktaki node write işlemlerini reddeder:
# Hangi node'un "Primary Component" olduğunu kontrol et
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_status';"
# Primary: Normal çalışıyor
# Non-Primary: Bu node yazma kabul etmiyor, quorum kaybetti
Eğer tüm cluster kapandıysa ve hangi node’un en güncel olduğunu bulmak istiyorsanız:
# Her node'da kontrol et
cat /var/lib/mysql/grastate.dat
# seqno değeri en yüksek olan node en güncel veriyi içeriyor
# safe_to_bootstrap: 1 olan node bootstrap için hazır
Tam Cluster Recovery
En kötü senaryo: Tüm node’lar kapandı ve cluster’ı sıfırdan kaldırmanız gerekiyor:
# En yüksek seqno'ya sahip node'da (grastate.dat'ta safe_to_bootstrap: 0 ise önce 1 yap)
# /var/lib/mysql/grastate.dat dosyasını düzenle:
sed -i 's/safe_to_bootstrap: 0/safe_to_bootstrap: 1/' /var/lib/mysql/grastate.dat
# Sadece bu node'da bootstrap:
galera_new_cluster
# Diğer node'ları sırayla başlat:
# node2 ve node3 üzerinde:
systemctl start mariadb
Uyarı: safe_to_bootstrap değerini manuel olarak değiştirmek veri kaybına yol açabilir. Bunu sadece hangi node’un en güncel olduğundan emin olduğunuzda yapın.
Performans Optimizasyonu
Galera’yı üretimde çalıştırırken birkaç kritik ayar performansı doğrudan etkiler:
# /etc/mysql/conf.d/galera.cnf dosyasına eklenecek performance ayarları
[mysqld]
# Flow control - replikasyon baskısını yönetir
wsrep_provider_options="gcache.size=512M; gcs.fc_limit=100; gcs.fc_factor=0.8"
# Paralel replikasyon - çok yazmalı ortamlarda kritik
wsrep_slave_threads=8
# InnoDB buffer pool - RAM'in %70-80'i
innodb_buffer_pool_size=8G
innodb_buffer_pool_instances=8
# Binary log kapatılabilir (sadece Galera replication kullanıyorsa)
# Ama point-in-time recovery için açık tutmak daha güvenli
# skip-log-bin
# Deadlock olasılığını azalt
innodb_deadlock_detect=ON
innodb_lock_wait_timeout=50
gcache.size parametresi özellikle önemlidir. Bu cache, node yeniden bağlandığında IST için kullanılır. Eğer bir node çok uzun süre offline kaldıysa ve gcache bu süredeki değişiklikleri tutamıyorsa, sistem SST’ye (tam snapshot) geçmek zorunda kalır ki bu çok daha yavaştır. Yazma yoğunluğuna göre 512MB ile 2GB arasında ayarlamak mantıklıdır.
Monitoring: Prometheus ve Grafana Entegrasyonu
Uzun vadede Galera’yı izlemek için mysqld_exporter kullanabilirsiniz:
# mysqld_exporter kur
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.1/mysqld_exporter-0.15.1.linux-amd64.tar.gz
tar xzf mysqld_exporter-0.15.1.linux-amd64.tar.gz
mv mysqld_exporter-0.15.1.linux-amd64/mysqld_exporter /usr/local/bin/
# Exporter için MySQL kullanıcısı oluştur
mysql -u root -p -e "
CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'exporter_sifre';
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
FLUSH PRIVILEGES;
"
# Credentials dosyası
cat > /etc/mysql/.my.cnf << 'EOF'
[client]
user=exporter
password=exporter_sifre
EOF
chmod 600 /etc/mysql/.my.cnf
# Systemd service
cat > /etc/systemd/system/mysqld_exporter.service << 'EOF'
[Unit]
Description=MySQL Exporter
After=network.target
[Service]
User=prometheus
ExecStart=/usr/local/bin/mysqld_exporter
--config.my-cnf=/etc/mysql/.my.cnf
--collect.global_status
--collect.info_schema.innodb_metrics
--web.listen-address=:9104
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now mysqld_exporter
Grafana’da Galera için kullanabileceğiniz hazır dashboard ID’leri şunlardır: 7362 (MySQL Overview) ve özellikle wsrep metriklerini gösteren custom dashboard’lar community tarafından paylaşılmaktadır.
İzlemeniz gereken kritik metrikler:
- wsrep_cluster_size: Her zaman 3 olmalı (3 node’lu cluster için)
- wsrep_flow_control_paused: 0’a yakın olmalı, yüksekse replikasyon baskı altında
- wsrep_cert_deps_distance: Paralel uygulanabilecek transaction sayısı, wsrep_slave_threads ayarı için referans
- wsrep_local_send_queue_avg: Gönderim kuyruğu, ağ sorunlarının göstergesi
- wsrep_local_recv_queue_avg: Alım kuyruğu, node’un gelen trafiği kaldıramadığını gösterir
Backup Stratejisi
Galera çalışıyor diye backup almayı ihmal etmeyin. Multi-master yapı veri kaybına karşı koruma sağlar ama mantıksal hataları (yanlışlıkla silinen tablo gibi) engellemez.
#!/bin/bash
# galera_backup.sh - Mariabackup ile hot backup
BACKUP_DIR="/backup/galera/$(date +%Y%m%d_%H%M%S)"
MYSQL_USER="root"
MYSQL_PASS="sifreniz"
RETENTION_DAYS=7
mkdir -p $BACKUP_DIR
echo "Backup başlıyor: $(date)"
# Mariabackup ile hot backup (servisi durdurmadan)
mariabackup --backup
--target-dir=$BACKUP_DIR
--user=$MYSQL_USER
--password=$MYSQL_PASS
--galera-info # Bu parametre Galera seqno bilgisini de kaydeder
# Backup'ı hazırla (prepare aşaması)
mariabackup --prepare --target-dir=$BACKUP_DIR
# Eski backup'ları temizle
find /backup/galera -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} ;
echo "Backup tamamlandı: $BACKUP_DIR"
echo "Boyut: $(du -sh $BACKUP_DIR | cut -f1)"
--galera-info parametresi backup dizinine xtrabackup_galera_info dosyası oluşturur. Bu dosya backup anındaki wsrep_local_state_uuid ve wsrep_last_committed değerlerini içerir; restore sonrası IST kullanmak istediğinizde bu bilgilere ihtiyacınız olabilir.
Sık Karşılaşılan Sorunlar
SST takılı kalıyor: Büyük veritabanlarında rsync yerine mariabackup kullanın. wsrep_sst_method=mariabackup daha güvenilirdir ve donor node’u kilitlemez.
Yüksek replikasyon gecikmesi: wsrep_flow_control_paused değerine bakın. Yüksekse en yavaş node tüm cluster’ı yavaşlatıyor demektir. O node’u inceleyin, donanım sorunu veya ağ problemi olabilir.
Auto increment çakışmaları: innodb_autoinc_lock_mode=2 ayarının yapıldığından emin olun. Ayrıca wsrep_auto_increment_control=ON varsayılan olarak aktiftir ve her node farklı aralıklarda ID üretir (node1: 1,4,7… node2: 2,5,8… node3: 3,6,9…).
Node cluster’a katılamıyor: wsrep_cluster_address içindeki IP’leri kontrol edin. Firewall kurallarını ve SELinux/AppArmor politikalarını gözden geçirin.
Sonuç
MySQL Galera Cluster, doğru kurulduğunda gerçekten güvenilir bir yüksek erişilebilirlik çözümü sunar. Senkron replikasyon sayesinde veri kaybı riski minimize edilir, herhangi bir node otomatik olarak failover alır ve uygulamanız kesintisiz çalışmaya devam eder.
Ancak şunu unutmayın: Galera sihirli bir değnek değil. Ağ kalitesi, node boyutlarının dengeli tutulması ve düzenli izleme olmadan cluster zamanla sorun çıkarır. Özellikle wsrep_flow_control_paused metriğini sürekli izleyin, bu tek başına cluster’ın sağlık durumu hakkında çok şey söyler.
Üretim ortamına geçmeden önce mutlaka şu senaryoları test edin: Tek node kaybı, iki node kaybı, tam cluster restart ve network bölünmesi. Bu testleri gece üç’te değil, mesai saatlerinde ve hazırlıklıyken yapın. Galera güvenilir bir teknoloji ama onu tanımak ve davranışlarını önceden bilmek, gerçek kriz anlarında sakin kalmanızı sağlar.