Replikation von MySQL-Datenbanken. Einführung

Ein modernes Produktionssystem kommt selten ohne Datenbankreplikation aus. Es ist ein leistungsstarkes Tool zur Verbesserung der Systemleistung und Fehlertoleranz, und es ist für den modernen Entwickler sehr wichtig, zumindest ein grundlegendes Verständnis der Replikation zu haben. In diesem Artikel werde ich einige Grundkenntnisse über die Replikation teilen und Ihnen ein einfaches Beispiel für die Konfiguration der Replikation in MySQL mit Docker zeigen.



Bild



Was ist Replikation und warum wird sie benötigt?



Replikation an sich bezieht sich auf den Prozess des Synchronisierens mehrerer Kopien eines Objekts. In unserem Fall ist ein solches Objekt der Datenbankserver, und die Daten selbst sind von größtem Wert. Wenn wir zwei oder mehr Server haben und auf irgendeine Weise einen synchronisierten Datensatz auf diesen verwalten, haben wir die Systemreplikation implementiert. Auch die manuelle Option c mysqldump -> mysql load



ist Replikation.



Es versteht sich, dass die Datenreplikation selbst keinen Wert hat und nur ein Werkzeug zur Lösung der folgenden Aufgaben ist:



  • Verbesserung der Datenleseleistung. Mithilfe der Replikation können wir mehrere Kopien des Servers verwalten und die Last auf diese verteilen.
  • . , . , .
  • . , , , .
  • . , ( , ), , .
  • . , , .
  • . .


MySQL



Der Replikationsprozess umfasst die Weitergabe von Datenänderungen vom Master-Server (normalerweise als Master bezeichnet ) an einen oder mehrere Slave-Server (Slave, Slave ). Es gibt auch komplexere Konfigurationen, insbesondere mit mehreren Master-Servern, aber für jede Änderung auf einem bestimmten Master-Server werden die verbleibenden Master bedingt zu Slaves und verbrauchen diese Änderungen.



Im Allgemeinen besteht die MySQL-Replikation aus drei Schritten:



  1. Der Master-Server schreibt Datenänderungen in das Protokoll. Dieses Protokoll wird als binäres Protokoll bezeichnet , und Änderungen werden als binäre Protokollereignisse bezeichnet .
  2. Der Slave kopiert die Änderungen in das Binärprotokoll in ein eigenes Protokoll, das als Relay-Protokoll bezeichnet wird .
  3. Der Slave spielt die Änderungen aus dem Relaisprotokoll erneut ab und wendet sie auf seine eigenen Daten an.


Replikationstypen



Es gibt zwei grundlegend unterschiedliche Ansätze für die Replikation: Befehl für Befehl und Zeile für Zeile . Bei der Befehl-für-Befehl-Replikation werden Datenänderungsanforderungen (INSERT, UPDATE, DELETE) im Master-Protokoll protokolliert, und die Slaves reproduzieren dieselben Befehle genau. Bei der zeilenweisen Replikation ändert das Protokoll direkt die Zeilen in den Tabellen, und die gleichen tatsächlichen Änderungen werden dann auf den Slave angewendet.



Da es keine Silberkugel gibt, hat jede dieser Methoden ihre eigenen Vor- und Nachteile. Die Replikation per Befehl ist einfacher zu implementieren und zu verstehen und reduziert die Belastung des Masters und des Netzwerks. Die Replikation pro Befehl kann jedoch zu unvorhersehbaren Effekten führen, wenn nicht deterministische Funktionen wie NOW (), RAND () usw. verwendet werden. Es kann auch Probleme geben, die durch nicht synchronisierte Daten zwischen Master und Slave verursacht werden. Die zeilenweise Replikation führt zu besser vorhersehbaren Ergebnissen, da tatsächliche Datenänderungen erfasst und reproduziert werden. Diese Methode kann jedoch die Belastung des Master-Servers, der jede Änderung im Protokoll protokollieren muss, und des Netzwerks, über das sich diese Änderungen verbreiten, erheblich erhöhen.



MySQL unterstützt beide Replikationsmethoden, und die Standardeinstellung (wir können sagen, die empfohlene) hat sich je nach Version geändert. Moderne Versionen wie MySQL 8 verwenden standardmäßig die zeilenbasierte Replikation.



Das zweite Prinzip der Aufteilung der Replikationsansätze ist die Anzahl der Master-Server... Das Vorhandensein eines Master-Servers impliziert, dass nur Datenänderungen akzeptiert werden. Dies ist eine Art Standard, von dem Änderungen bereits an viele Slaves weitergegeben werden. Bei der Master-Master-Replikation erhalten wir sowohl Gewinn als auch Probleme. Einer der Vorteile ist beispielsweise, dass wir Remote-Clients aus Sydney und Helsinki eine ebenso schnelle Möglichkeit bieten können, ihre Änderungen in die Datenbank zu schreiben. Dies führt zum Hauptnachteil, wenn beide Clients gleichzeitig dieselben Daten geändert haben, deren Änderungen als endgültig gelten, deren Transaktion festgeschrieben und deren Transaktion zurückgesetzt wird.



Es ist auch erwähnenswert, dass das Vorhandensein eines Master-Replikationsmasters im Allgemeinen die Leistung beim Schreiben von Daten im System nicht steigern kann. Stellen wir uns vor, unser einziger Master kann bis zu 1000 Anfragen pro Zeiteinheit verarbeiten. Durch Hinzufügen eines replizierten zweiten Masters können wir nicht 1000 Anforderungen für jeden von ihnen verarbeiten, da sie zusätzlich zur Verarbeitung „ihrer“ Anforderungen die auf dem zweiten Master vorgenommenen Änderungen anwenden müssen. Dies führt im Fall einer Befehl-für-Befehl-Replikation dazu, dass beide nicht mehr als die schwächsten von ihnen insgesamt belastet werden. Bei einer zeilenweisen Replikation ist der Effekt nicht vollständig vorhersehbar und kann je nach bestimmten Bedingungen entweder positiv oder negativ sein.



Ein Beispiel für die Erstellung einer einfachen Replikation in MySQL



Jetzt ist es an der Zeit, eine einfache Replikationskonfiguration in MySQL zu erstellen. Dazu werden wir die Docker und MySQL Bilder verwenden dockerhub , sowie die Welt - Datenbank .



Zunächst werden wir zwei Container starten, von denen einer später als Master und der andere als Slave konfiguriert wird. Vernetzen wir sie, damit sie miteinander sprechen können.



docker run -d --name samplereplication-master -e MYSQL_ALLOW_EMPTY_PASSWORD=true -v ~/path/to/world/dump:/docker-entrypoint-initdb.d  mysql:8.0

docker run -d --name samplereplication-slave -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:8.0

docker network create samplereplication
docker network connect samplereplication samplereplication-master
docker network connect samplereplication samplereplication-slave

      
      





Die Volume-Verbindung mit dem Speicherauszug world.sql wird für den Master-Container angegeben, um das Vorhandensein einer anfänglichen Basis darauf zu simulieren. Beim Erstellen eines Containers lädt mysql SQL-Skripte herunter und führt sie aus, die sich im Verzeichnis docker-entrypoint-initdb.d befinden.



Um mit Konfigurationsdateien arbeiten zu können, benötigen wir einen Texteditor. Jeder bequeme kann verwendet werden, ich bevorzuge vim.



docker exec samplereplication-master apt-get update && docker exec samplereplication-master apt-get install -y vim 
docker exec samplereplication-slave apt-get update && docker exec samplereplication-slave apt-get install -y vim

      
      





Erstellen Sie zunächst ein Konto auf dem Master, das für die Replikation verwendet wird:



docker exec -it samplereplication-master mysql

      
      





mysql> CREATE USER 'replication'@'%';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';

      
      





Als nächstes ändern wir die Konfigurationsdateien für den Master-Server:



docker exec -it samplereplication-master bash
~ vi /etc/mysql/my.cnf

      
      





Die folgenden Parameter sollten der Datei my.cnf im Abschnitt [mysqld] hinzugefügt werden:



server_id = 1 #     
log_bin = mysql-bin #       

      
      





Beim Aktivieren / Deaktivieren des Binärprotokolls ist ein Neustart des Servers erforderlich. Im Fall von Docker wird der Container neu geladen.



docker restart samplereplication-master

      
      





Stellen Sie sicher, dass das Binärprotokoll aktiviert ist. Bestimmte Werte wie Dateiname und Position können variieren.



mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      156 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

      
      





Um die Datenreplikation zu starten, muss der Slave in den Status des Masters „hochgezogen“ werden. Dazu müssen Sie den Assistenten selbst vorübergehend blockieren, um eine Momentaufnahme der tatsächlichen Daten zu erstellen.



mysql> FLUSH TABLES WITH READ LOCK;

      
      





Als nächstes exportieren wir mit mysqldump Daten aus der Datenbank. In diesem Beispiel können Sie natürlich dieselbe world.sql verwenden, aber kommen wir einem realistischeren Szenario näher.



docker exec samplereplication-master mysqldump world > /path/to/dump/on/host/world.sql

      
      





Danach müssen Sie den Befehl SHOW MASTER STATUS erneut ausführen und die Werte für Datei und Position speichern oder notieren. Dies sind die sogenannten Koordinaten des Binärprotokolls. Von ihnen werden wir weiter darauf hinweisen, den Sklaven zu starten. Jetzt können wir den Master wieder freischalten:



mysql> UNLOCK TABLES;

      
      





Der Master ist konfiguriert und bereit, auf andere Server zu replizieren. Gehen wir jetzt zum Sklaven. Laden Sie zunächst den Dump vom Master hinein.



docker cp /path/to/dump/on/host/world.sql samplereplication-slave:/tmp/world.sql
docker exec -it samplereplication-slave mysql
mysql> CREATE DATABASE `world`;
docker exec -it samplereplication-slave bash
~ mysql world < /tmp/world.sql

      
      





Und dann werden wir die Slave-Konfiguration ändern, indem wir Parameter hinzufügen:



log_bin = mysql-bin  #      
server_id = 2  #   
relay-log = /var/lib/mysql/mysql-relay-bin #    
relay-log-index = /var/lib/mysql/mysql-relay-bin.index  #        
read_only = 1  #     “ ”

      
      





Laden Sie danach den Slave neu:



docker restart samplereplication-slave

      
      





Und jetzt müssen wir dem Slave mitteilen, welcher Server der Master dafür sein wird und wo mit dem Replizieren von Daten begonnen werden soll. Anstelle von MASTER_LOG_FILE und MASTER_LOG_POS müssen Sie die Werte ersetzen, die aus dem SHOW MASTER STATUS auf dem Master erhalten wurden. Diese Parameter werden zusammen als binäre Protokollkoordinaten bezeichnet.



mysql> CHANGE MASTER TO MASTER_HOST='samplereplication-master', MASTER_USER='replication', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=156;

      
      





Beginnen wir mit der Wiedergabe des Relay-Protokolls und überprüfen den Replikationsstatus:



mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G

      
      





Sklavenstatus
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: samplereplication-master
                  Master_User: replication
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 156
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 324
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 156
              Relay_Log_Space: 533
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: c341beb7-3a33-11eb-9440-0242ac110002
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)
      
      







Wenn alles gut gegangen ist, sollte Ihr Status ähnlich aussehen. Schlüsselparameter hier:



  • Slave_IO_State - eigentlich der Replikationsstatus.
  • Read_Master_Log_Pos ist die letzte Position, die aus dem Masterprotokoll gelesen wurde.
  • Relay_Master_Log_File - Die aktuelle Master-Protokolldatei.
  • Seconds_Behind_Master - Slave liegt in Sekunden hinter dem Master zurück.
  • Last_IO_Error , Last_SQL_Error - Replikationsfehler, falls vorhanden.


Versuchen wir, die Daten auf dem Master zu ändern:



docker exec -it samplereplication-master mysql

      
      





mysql> USE world;
mysql> INSERT INTO city (Name, CountryCode, District, Population) VALUES ('Test-Replication', 'ALB', 'Test', 42);

      
      





Und überprüfe, ob sie auf dem Sklaven erschienen sind.



docker exec -it samplereplication-slave mysql

      
      





mysql> USE world;
mysql> SELECT * FROM city ORDER BY ID DESC LIMIT 1;
+------+------------------+-------------+----------+------------+
| ID   | Name             | CountryCode | District | Population |
+------+------------------+-------------+----------+------------+
| 4081 | Test-Replication | ALB         | Test     |         42 |
+------+------------------+-------------+----------+------------+
1 row in set (0.00 sec)

      
      





Ausgezeichnet! Der eingegebene Datensatz ist auch auf dem Slave sichtbar. Herzlichen Glückwunsch, Sie haben jetzt Ihre erste MySQL-Replikation erstellt!



Fazit



Ich hoffe, dass ich im Rahmen dieses Artikels ein grundlegendes Verständnis der Replikationsprozesse vermitteln, mich mit der Verwendung dieses Tools vertraut machen und versuchen konnte, ein einfaches Beispiel für die Replikation in MySQL unabhängig zu implementieren. Das Thema Replikation und seine praktische Anwendung ist äußerst umfangreich. Wenn Sie an diesem Thema interessiert sind, kann ich die folgenden Quellen zum Studium empfehlen:



  • Bericht "Funktionsweise der MySQL-Replikation" von Andrey Aksenov (Sphinx)
  • Das Buch „MySQL to the Maximum. Optimierung, Replikation, Backup “- Baron Schwartz, Petr Zaitsev, Vadim Tkachenko
  • "Highload" - hier finden Sie spezifische Rezepte für die Datenreplikation


Ich hoffe, Sie fanden diesen Artikel hilfreich und freuen uns über Ihr Feedback und Ihre Kommentare!



All Articles