aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Game-Server

MySQL-Replikation: Leitfaden zur Master-Replica-Einrichtung

Wenn ein Gameserver oder eine stark frequentierte Webanwendung wächst, hat eine einzelne Datenbank Mühe, den gesamten Lese- und Schreibverkehr allein zu tragen. Mit MySQL-Replikation verteilst du diese Last, indem du deine Daten von einem Hauptserver (Master) nahezu in Echtzeit auf eine oder mehrere Kopien (Replica/Slave) überträgst: Schreibvorgänge gehen an den Master, während schwere Lese-Queries auf die Replicas verteilt werden. In dieser Anleitung baust du eine Master-Replica-Topologie von Grund auf, nutzt den modernen GTID-basierten Ansatz und lernst, wie du den Zustand deiner Replica überwachst.

Wie funktioniert Replikation?

Im Kern der MySQL-Replikation steht das Binary Log (Binlog). Jeder datenverändernde Vorgang auf dem Master (INSERT, UPDATE, DELETE, DDL) wird in das Binlog geschrieben. Die Replica verbindet sich mit dem Master, kopiert dieses Log in ihr eigenes Relay Log und spielt die Events anschließend bei sich erneut ab. Der Prozess läuft mit zwei Threads:

  • I/O-Thread: liest das Binlog des Masters und schreibt es in das Relay Log der Replica.
  • SQL-Thread (Applier): wendet die Events aus dem Relay Log auf die Daten der Replica an.

Die Standardreplikation ist asynchron: Der Master committet seine Transaktion, ohne darauf zu warten, dass die Replica das Event empfangen hat. Dadurch kann die Replica dem Master einige Sekunden hinterherhinken, was als replication lag bezeichnet wird. Sich dessen bewusst zu sein, ist beim Entwurf der Leseverteilung entscheidend.

Den Master-Server konfigurieren

Der erste Schritt besteht darin, das Binary Log auf dem Master zu aktivieren und dem Server eine eindeutige Identität zu geben. Jeder Replikationsknoten muss eine netzwerkweit eindeutige server_id haben. Füge dies dem Abschnitt [mysqld] deiner my.cnf-Datei hinzu:

[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
bind_address = 0.0.0.0

binlog_format = ROW protokolliert Änderungen auf Zeilenebene und ist deutlich zuverlässiger als der Modus STATEMENT. gtid_mode = ON aktiviert die moderne GTID-basierte Replikation, die die Positionsverwaltung automatisiert. Starte den Dienst nach der Änderung neu:

sudo systemctl restart mysql

Lege anschließend einen dedizierten Benutzer an, mit dem sich die Replica verbindet. Gib ihm nur das Recht REPLICATION SLAVE; vergib keine weitreichenden Berechtigungen:

CREATE USER 'repl'@'%' IDENTIFIED BY 'StarkesPasswort!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

Bestehende Daten auf die Replica übertragen

Bevor die Replica aufholen kann, muss sie vom selben Punkt wie die bestehenden Daten starten. Der sauberste Weg, einen konsistenten Snapshot zu erstellen, ist mysqldump. Mit aktiviertem GTID wird das Start-GTID-Set direkt in den Dump eingebettet:

mysqldump --all-databases --single-transaction \
  --source-data=2 --triggers --routines --events \
  -u root -p > voll-backup.sql

--single-transaction erstellt einen konsistenten Snapshot der InnoDB-Tabellen, ohne sie zu sperren, und --source-data=2 fügt die Binlog-Position als Kommentar hinzu. Kopiere die Datei auf die Replica und importiere sie:

scp voll-backup.sql benutzer@replica-ip:/tmp/
# auf der Replica:
mysql -u root -p < /tmp/voll-backup.sql

Den Replica-Server verbinden

Gib der Replica in ihrer my.cnf eine andere server_id und erwäge, sie schreibgeschützt zu machen, damit ein versehentlicher Schreibvorgang die Replikation nicht zerstören kann:

[mysqld]
server_id = 2
gtid_mode = ON
enforce_gtid_consistency = ON
read_only = ON
super_read_only = ON
relay_log = /var/log/mysql/relay-bin.log

Nach dem Neustart des Dienstes richtest du die Replica auf den Master aus. In MySQL 8 verwenden die modernen Befehle die SOURCE-Terminologie:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = '10.0.0.1',
  SOURCE_USER = 'repl',
  SOURCE_PASSWORD = 'StarkesPasswort!',
  SOURCE_AUTO_POSITION = 1;

START REPLICA;

Dank GTID lässt SOURCE_AUTO_POSITION = 1 die Replica vom richtigen Punkt aus fortfahren, ohne dass du manuell einen Binlog-Dateinamen und eine Position eingeben musst. In älteren Versionen lautet die Entsprechung CHANGE MASTER TO ... MASTER_AUTO_POSITION = 1, gefolgt von START SLAVE.

Replikation überwachen und Fehler beheben

Um zu prüfen, ob die Replica tatsächlich läuft, fragst du ihren Status ab:

SHOW REPLICA STATUS\G

Achte in der Ausgabe besonders auf diese drei Felder:

  • Replica_IO_Running: Yes und Replica_SQL_Running: Yes — beide Threads müssen laufen.
  • Seconds_Behind_Source — um wie viele Sekunden die Replica dem Master hinterherhinkt. Wenn dieser Wert stetig steigt, kann die Replica die Last nicht aufholen.
  • Last_Error — ist dieses Feld nicht leer, ist der SQL-Thread beim Anwenden eines Events hängen geblieben.

Die häufigsten Ursachen für Lag sind langsame Festplatten, fehlende Indizes auf der Replica und Single-Threaded-Anwendung. In MySQL 8 kannst du Events parallel anwenden, indem du replica_parallel_workers erhöhst:

SET GLOBAL replica_parallel_workers = 4;

Wenn du stärkere Konsistenzgarantien benötigst, kannst du die semi-synchrone Replikation aktivieren; in diesem Modus bestätigt der Master einen Commit erst, wenn mindestens eine Replica das Event in ihr Relay Log geschrieben hat. Du musst das Plugin installieren und aktivieren:

INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = 1;

Die Leselast verteilen

Der eigentliche Zweck der Replikation ist die Aufteilung der Last. Halte in deiner Anwendung zwei Connection Pools vor: Schreibvorgänge und konsistenzkritische Queries wie SELECT ... FOR UPDATE gehen an den Master, während schwere Lesevorgänge wie Berichte und Listen an die Replicas gehen. Frameworks wie Laravel unterstützen das auf Konfigurationsebene:

'mysql' => [
  'read'  => ['host' => ['10.0.0.2']],
  'write' => ['host' => ['10.0.0.1']],
  'sticky' => true,
],

sticky => true ist ein entscheidendes Detail: Hast du innerhalb derselben Anfrage einen Schreibvorgang ausgeführt, leitet es auch die nachfolgenden Lesevorgänge an den Master, sodass du nicht aufgrund von Lag Daten liest, die auf der Replica noch nicht sichtbar sind.

Häufige Fragen

Ist Replikation dasselbe wie ein Backup?

Nein. Da die Replica jeden Vorgang des Masters wiederholt, löscht sie auch sofort eine Tabelle, die du versehentlich entfernt hast. Replikation dient der Hochverfügbarkeit und Lastverteilung; für die Datenwiederherstellung benötigst du weiterhin regelmäßige mysqldump- oder physische Backups.

Kann ich mehr als eine Replica hinzufügen?

Ja. Ein Master kann mehrere Replicas versorgen; gib jeder eine andere server_id und wiederhole dieselben Einrichtungsschritte. Das ist die gängigste Methode, um Lesevorgänge horizontal zu skalieren.

Was tue ich, wenn die Replica dem Master hinterherhinkt?

Überwache zuerst Seconds_Behind_Source. Bei anhaltendem Lag beschleunigst du die Festplatte der Replica (SSD/NVMe), erhöhst die Anzahl paralleler Applier-Worker und fügst die fehlenden Indizes auf der Replica hinzu. Auch das Aufteilen schwerer Bulk-Schreibvorgänge in kleinere Batches reduziert den Lag merklich.

Lass dich von der Datenbankschicht nicht ausbremsen, während du deinen Server skalierst. Möchtest du eine hochverfügbare MySQL-Replikationsarchitektur für deinen Gameserver oder dein Webprojekt entwerfen, nimm Kontakt mit mir auf und wir richten sie gemeinsam ein.

Bu kategorideki tüm yazılar →

Devamı için