Reine PHP-Implementierung des MySQL-Replikationsprotokolls. Dadurch können Sie Ereignisse wie Einfügen, Aktualisieren, Löschen mit ihren Daten und unformatierten SQL-Abfragen empfangen.
Basierend auf einer großartigen Arbeit der Entwickler: https://github.com/noplay/python-mysql-replication und https://github.com/fengxiangyun/mysql-replication
In deinem Projekt
composer require krowinski/php-mysql-replication
oder eigenständig
git clone https://github.com/krowinski/php-mysql-replication.git
composer install -o
PHP
MYSQL
In Ihrer MySQL-Serverkonfigurationsdatei müssen Sie die Replikation aktivieren:
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
binlog-format = row #Very important if you want to receive write, update and delete row events
MySQL-Replikationsereignisse erklärt https://dev.mysql.com/doc/internals/en/event-meanings.html
MySQL-Benutzerrechte:
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'user'@'host';
GRANT SELECT ON `dbName`.* TO 'user'@'host';
Verwenden Sie ConfigBuilder oder ConfigFactory, um die Konfiguration zu erstellen. Verfügbare Optionen:
'user' – Ihr MySQL-Benutzer (obligatorisch)
'ip' oder 'host' – Ihr MySQL-Host/Ihre MySQL-IP (obligatorisch)
'password' – Ihr MySQL-Passwort (obligatorisch)
'port' – Ihr MySQL-Host-Port (Standard 3306)
'charset' – DB-Verbindungszeichensatz (Standard utf8)
'gtid' – GTID-Marker, mit denen begonnen werden soll (Format 9b1c8d18-2a76-11e5-a26b-000c2976f3f3:1-177592)
'mariaDbGtid' – MariaDB-GTID-Marker, mit denen begonnen werden soll (Format 1-1-3,0-1-88)
'slaveId' – Skript-Slave-ID zur Identifizierung (Standard: 666) (SHOW SLAVE HOSTS)
„binLogFileName“ – Name der Bin-Protokolldatei, mit der begonnen werden soll
'binLogPosition' – Bin-Log-Position, von der aus begonnen werden soll
'eventsOnly' – Array zum Abhören von Ereignissen (vollständige Liste in der Datei ConstEventType.php)
'eventsIgnore' – Array zum Ignorieren von Ereignissen (vollständige Liste in der Datei ConstEventType.php)
'tablesOnly' – Array, das nur bestimmte Tabellen überwacht (standardmäßig alle Tabellen)
„databasesOnly“ – Array, um nur bestimmte Datenbanken abzuhören (standardmäßig alle Datenbanken)
„tableCacheSize“ – einige Daten werden aus dem Informationsschema gesammelt, diese Daten werden zwischengespeichert.
'custom' – wenn einige Parameter in erweiterten/implementierten eigenen Klassen festgelegt werden müssen
„heartbeatPeriod“ – legt das Intervall in Sekunden zwischen den Replikations-Heartbeats fest. Immer wenn das Binärprotokoll des Masters mit einem Ereignis aktualisiert wird, wird die Wartezeit für den nächsten Heartbeat zurückgesetzt. Intervall ist ein Dezimalwert im Bereich von 0 bis 4294967 Sekunden und einer Auflösung in Millisekunden. Der kleinste Wert ungleich Null ist 0,001. Heartbeats werden vom Master nur gesendet, wenn in der binären Protokolldatei über einen längeren Zeitraum als das Intervall keine nicht gesendeten Ereignisse vorhanden sind.
'saveUuid' – legt die Slave-UUID zur Identifizierung fest (Standard: 0015d2b6-8a06-4e5e-8c07-206ef3fbd274)
Ruby: https://github.com/y310/kodama
Java: https://github.com/shyiko/mysql-binlog-connector-java
GO: https://github.com/siddontang/go-mysql
Python: https://github.com/noplay/python-mysql-replication
.NET: https://github.com/rusuly/MySqlCdc
Alle Beispiele sind im Beispielverzeichnis verfügbar
In diesem Beispiel werden alle Replikationsereignisse an die Konsole ausgegeben:
Denken Sie daran, die Konfiguration für Ihren Benutzer, Host und Ihr Passwort zu ändern.
Der Benutzer sollte über Replikationsberechtigungen verfügen [ REPLICATION CLIENT, SELECT]
php example/dump_events.php
Für Test-SQL-Ereignisse:
CREATE DATABASE php_mysql_replication ;
use php_mysql_replication;
CREATE TABLE test4 (id int NOT NULL AUTO_INCREMENT, data VARCHAR ( 255 ), data2 VARCHAR ( 255 ), PRIMARY KEY (id));
INSERT INTO test4 (data,data2) VALUES ( " Hello " , " World " );
UPDATE test4 SET data = " World " , data2 = " Hello " WHERE id = 1 ;
DELETE FROM test4 WHERE id = 1 ;
Die Ausgabe sieht ähnlich aus (abhängig von der Konfiguration, zum Beispiel GTID aus/ein):
=== Event format description ===
Date: 2017-07-06T13:31:11+00:00
Log position: 0
Event size: 116
Memory usage 2.4 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803092
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13675
Memory usage 2.42 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803237
Event size: 145
Database: php_mysql_replication
Execution time: 0
Query: CREATE DATABASE php_mysql_replication
Memory usage 2.45 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803285
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13676
Memory usage 2.45 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803500
Event size: 215
Database: php_mysql_replication
Execution time: 0
Query: CREATE TABLE test4 (id int NOT NULL AUTO_INCREMENT, data VARCHAR(255), data2 VARCHAR(255), PRIMARY KEY(id))
Memory usage 2.45 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803548
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13677
Memory usage 2.45 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803637
Event size: 89
Database: php_mysql_replication
Execution time: 0
Query: BEGIN
Memory usage 2.45 MB
=== Event tableMap ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803708
Event size: 71
Table: test4
Database: php_mysql_replication
Table Id: 866
Columns amount: 3
Memory usage 2.71 MB
=== Event write ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803762
Event size: 54
Table: test4
Affected columns: 3
Changed rows: 1
Values: Array
(
[0] => Array
(
[id] => 1
[data] => Hello
[data2] => World
)
)
Memory usage 2.74 MB
=== Event xid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803793
Event size: 31
Transaction ID: 662802
Memory usage 2.75 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803841
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13678
Memory usage 2.75 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57803930
Event size: 89
Database: php_mysql_replication
Execution time: 0
Query: BEGIN
Memory usage 2.76 MB
=== Event tableMap ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804001
Event size: 71
Table: test4
Database: php_mysql_replication
Table Id: 866
Columns amount: 3
Memory usage 2.75 MB
=== Event update ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804075
Event size: 74
Table: test4
Affected columns: 3
Changed rows: 1
Values: Array
(
[0] => Array
(
[before] => Array
(
[id] => 1
[data] => Hello
[data2] => World
)
[after] => Array
(
[id] => 1
[data] => World
[data2] => Hello
)
)
)
Memory usage 2.76 MB
=== Event xid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804106
Event size: 31
Transaction ID: 662803
Memory usage 2.76 MB
=== Event gtid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804154
Event size: 48
Commit: true
GTID NEXT: 3403c535-624f-11e7-9940-0800275713ee:13679
Memory usage 2.76 MB
=== Event query ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804243
Event size: 89
Database: php_mysql_replication
Execution time: 0
Query: BEGIN
Memory usage 2.76 MB
=== Event tableMap ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804314
Event size: 71
Table: test4
Database: php_mysql_replication
Table Id: 866
Columns amount: 3
Memory usage 2.76 MB
=== Event delete ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804368
Event size: 54
Table: test4
Affected columns: 3
Changed rows: 1
Values: Array
(
[0] => Array
(
[id] => 1
[data] => World
[data2] => Hello
)
)
Memory usage 2.77 MB
=== Event xid ===
Date: 2017-07-06T15:23:44+00:00
Log position: 57804399
Event size: 31
Transaction ID: 662804
Memory usage 2.77 MB
Getestet auf VM
Debian 8.7
PHP 5.6.30
Percona 5.6.35
inxi
CPU(s)~4 Single core Intel Core i5-2500Ks (-SMP-) clocked at 5901 Mhz Kernel~3.16.0-4-amd64 x86_64 Up~1 day Mem~1340.3/1996.9MB HDD~41.9GB(27.7% used) Procs~122 Client~Shell inxi~2.1.28
php example/benchmark.php
Start insert data
7442 event by seconds (1000 total)
7679 event by seconds (2000 total)
7914 event by seconds (3000 total)
7904 event by seconds (4000 total)
7965 event by seconds (5000 total)
8006 event by seconds (6000 total)
8048 event by seconds (7000 total)
8038 event by seconds (8000 total)
8040 event by seconds (9000 total)
8055 event by seconds (10000 total)
8058 event by seconds (11000 total)
8071 event by seconds (12000 total)
Zunächst einmal gibt Ihnen MYSQL keine asynchronen Aufrufe. Normalerweise müssen Sie dies in Ihrer Anwendung programmieren (durch Ereignisauslösung und Hinzufügen zu einem Warteschlangensystem). Wenn Ihre Datenbank über viele Einstiegspunkte wie das Web, das Backend und andere Mikrodienste verfügt, ist es nicht immer günstig, allen Mikrodiensten Verarbeitung hinzuzufügen. Aber mit der MySQL-Replikation Protokoll, das Sie auf Schreibereignisse abhören und dann asynchron verarbeiten können (die beste Kombination ist das Hinzufügen von Elementen zu einem Warteschlangensystem wie RabbitMQ, Redis oder Kafka). Auch beim Invalidieren des Caches, bei der Suchmaschinenreplikation, bei Echtzeitanalysen und Audits.
Nun, zunächst müssen Sie wissen, dass viele Ereignisse eintreten können, z. B. wenn Sie 1.000.000 Datensätze in der Tabelle „bar“ aktualisieren und diesen einen Eintrag aus Ihrer Tabelle „foo“ benötigen. Dann müssen alle per Skript verarbeitet werden. und Sie müssen auf Ihre Daten warten. Das ist normal und so funktioniert es. Sie können die Geschwindigkeit mithilfe von Konfigurationsoptionen erhöhen. Wenn das Skript abstürzt, müssen Sie außerdem von Zeit zu Zeit die Position im Binlog (oder GTID) speichern, um an dieser Position zu beginnen, wenn Sie dieses Skript erneut ausführen, um Duplikate zu vermeiden.
Wie ich in 1 Punkt erwähnt habe, verwenden Sie Warteschlangensysteme wie Rabbitmq, Redis oder Kafka, damit Sie Daten in mehreren Skripten verarbeiten können.
Erstellen Sie ein Problem. Ich werde versuchen, in meiner Freizeit daran zu arbeiten :)
Es funktioniert wie jedes andere MYSQL im Slave-Modus und verursacht den gleichen Overhead.
Um dies zu beheben, erhöhen Sie am besten die Datenbankkonfigurationen net_read_timeout
und net_write_timeout
auf 3600. (tx Bijimon)
Legen Sie in my.conf binlog_row_image=full
fest, um zu verhindern, dass nur Teilaktualisierungen empfangen werden.
Legen Sie in my.conf log_slave_updates=on
, um dies zu beheben (#71)(#66)
Die Standard-MYSQL-Einstellung generiert einen großen Stream-Blob. Dies erfordert mehr RAM/CPU. Sie können dies für einen kleineren Stream ändern, indem Sie die Variable binlog_row_event_max_size
verwenden [https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary- log.html#sysvar_binlog_row_event_max_size], um es in kleinere Teile aufzuteilen