Implémentation PHP pure du protocole de réplication MySQL. Cela vous permet de recevoir des événements tels que l'insertion, la mise à jour, la suppression avec leurs données et requêtes SQL brutes.
Basé sur un excellent travail de créateurs:https://github.com/noplay/python-mysql-replication et https://github.com/fengxiangyun/mysql-replication
Dans ton projet
composer require krowinski/php-mysql-replication
ou autonome
git clone https://github.com/krowinski/php-mysql-replication.git
composer install -o
PHP
MYSQL
Dans le fichier de configuration de votre serveur MySQL, vous devez activer la réplication :
[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
Événements de réplication MySQL expliqués https://dev.mysql.com/doc/internals/en/event-meanings.html
Privilèges utilisateur MySQL :
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'user'@'host';
GRANT SELECT ON `dbName`.* TO 'user'@'host';
Utilisez ConfigBuilder ou ConfigFactory pour créer une configuration. Options disponibles :
'user' - votre utilisateur mysql (obligatoire)
'ip' ou 'host' - votre hôte/ip mysql (obligatoire)
'password' - votre mot de passe mysql (obligatoire)
'port' - votre port hôte MySQL (3306 par défaut)
'charset' - jeu de caractères de connexion à la base de données (utf8 par défaut)
'gtid' - marqueur(s) GTID à partir duquel commencer (format 9b1c8d18-2a76-11e5-a26b-000c2976f3f3:1-177592)
'mariaDbGtid' - Marqueur(s) GTID MariaDB à partir duquel démarrer (format 1-1-3,0-1-88)
'slaveId' - identifiant d'esclave de script pour l'identification (par défaut : 666) (AFFICHER LES HÔTES ESCLAVE)
'binLogFileName' - nom du fichier journal bin à partir duquel démarrer
'binLogPosition' - position du journal bin à partir de laquelle commencer
'eventsOnly' - tableau pour écouter les événements (liste complète dans le fichier ConstEventType.php)
'eventsIgnore' - tableau pour ignorer les événements (liste complète dans le fichier ConstEventType.php)
'tablesOnly' - tableau pour écouter uniquement sur les tables données (par défaut toutes les tables)
'databasesOnly' - tableau pour écouter uniquement sur des bases de données données (par défaut toutes les bases de données)
'tableCacheSize' - certaines données sont collectées à partir du schéma d'informations, ces données sont mises en cache.
'custom' - si certains paramètres doivent être définis dans leurs propres classes étendues/implémentées
'heartbeatPeriod' - définit l'intervalle en secondes entre les battements de cœur de réplication. Chaque fois que le journal binaire du maître est mis à jour avec un événement, la période d'attente pour le prochain battement de cœur est réinitialisée. l'intervalle est une valeur décimale comprise entre 0 et 4294967 secondes et une résolution en millisecondes ; la plus petite valeur non nulle est 0,001. Les pulsations sont envoyées par le maître uniquement s'il n'y a aucun événement non envoyé dans le fichier journal binaire pendant une période supérieure à l'intervalle.
'saveUuid' - définit l'uuid de l'esclave pour l'identification (par défaut : 0015d2b6-8a06-4e5e-8c07-206ef3fbd274)
Rubis : https://github.com/y310/kodama
Java : https://github.com/shyiko/mysql-binlog-connector-java
ALLER : https://github.com/siddontang/go-mysql
Python : https://github.com/noplay/python-mysql-replication
.NET : https://github.com/rusuly/MySqlCdc
Tous les exemples sont disponibles dans le répertoire des exemples
Cet exemple va transférer tous les événements de réplication vers la console :
N'oubliez pas de modifier la configuration de votre utilisateur, de votre hôte et de votre mot de passe.
L'utilisateur doit disposer des privilèges de réplication [ REPLICATION CLIENT, SELECT]
php example/dump_events.php
Pour les événements SQL de test :
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 ;
Le résultat sera similaire à ceci (dépend de la configuration, par exemple GTID désactivé/activé) :
=== 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
Testé sur 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)
Eh bien, tout d’abord, MYSQL ne vous donne pas d’appels asynchrones. Vous devez généralement programmer cela dans votre application (en répartissant des événements et en les ajoutant à un système de file d'attente et si votre base de données a de nombreux points d'entrée comme le Web, d'autres microservices backend, il n'est pas toujours bon marché d'ajouter un traitement à chacun d'eux. Mais en utilisant la réplication MySQL protocole, vous pouvez écouter les événements d'écriture et les traiter ensuite de manière asynchrone (le meilleur combo consiste à ajouter un élément à un système de file d'attente comme RabbitMQ, Redis ou Kafka). Également dans le cache d'invalidation, la réplication du moteur de recherche, les analyses et les audits en temps réel.
Eh bien, tout d'abord, vous devez savoir que de nombreux événements peuvent survenir, comme si vous mettez à jour 1 000 000 d'enregistrements dans la table "bar" et que vous avez besoin de cette insertion de votre table "foo". Ensuite, tout doit être traité par script, et vous devez attendre vos données. C'est normal et c'est comme ça que ça marche. Vous pouvez accélérer en utilisant les options de configuration. De plus, si le script plante, vous devez enregistrer de temps en temps la position du binlog (ou gtid) pour démarrer à partir de cette position lorsque vous exécutez à nouveau ce script afin d'éviter les doublons.
Comme je l'ai mentionné en 1 point, utilisez un système de file d'attente comme RabbitMQ, Redis ou Kafka, ils vous donneront la possibilité de traiter des données dans plusieurs scripts.
Créez un problème sur lequel j'essaierai de travailler pendant mon temps libre :)
Il fonctionne comme n'importe quel autre MYSQL en mode esclave et donne la même surcharge.
Pour résoudre ce problème, le mieux est d'augmenter les configurations de base de données net_read_timeout
et net_write_timeout
à 3600. (tx Bijimon)
Défini dans my.conf binlog_row_image=full
pour corriger la réception de mises à jour partielles uniquement.
Définissez dans my.conf log_slave_updates=on
pour résoudre ce problème (#71)(#66)
Le paramètre MYSQL par défaut génère une grosse goutte de flux qui nécessite plus de RAM/CPU. Vous pouvez modifier cela pour un flux plus petit en utilisant la variable binlog_row_event_max_size
[https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary- log.html#sysvar_binlog_row_event_max_size] pour diviser en morceaux plus petits