PHP puro Implementación del protocolo de replicación MySQL. Esto le permite recibir eventos como insertar, actualizar, eliminar con sus datos y consultas SQL sin procesar.
Basado en un gran trabajo de los creadores: https://github.com/noplay/python-mysql-replication y https://github.com/fengxiangyun/mysql-replication
en tu proyecto
composer require krowinski/php-mysql-replication
o independiente
git clone https://github.com/krowinski/php-mysql-replication.git
composer install -o
PHP
MySQL
En el archivo de configuración de su servidor MySQL necesita habilitar la replicación:
[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
Explicación de los eventos de replicación de MySQL https://dev.mysql.com/doc/internals/en/event-meanings.html
Privilegios de usuario de MySQL:
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'user'@'host';
GRANT SELECT ON `dbName`.* TO 'user'@'host';
Utilice ConfigBuilder o ConfigFactory para crear la configuración. Opciones disponibles:
'usuario' - su usuario de mysql (obligatorio)
'ip' o 'host' - su host/ip de mysql (obligatorio)
'contraseña' - su contraseña de MySQL (obligatoria)
'puerto': su puerto de host mysql (predeterminado 3306)
'charset' - conjunto de caracteres de conexión a la base de datos (utf8 predeterminado)
'gtid': marcador(es) GTID desde el que comenzar (formato 9b1c8d18-2a76-11e5-a26b-000c2976f3f3:1-177592)
'mariaDbGtid' - Marcador(es) GTID de MariaDB para comenzar (formato 1-1-3,0-1-88)
'slaveId' - ID de esclavo del script para identificación (predeterminado: 666) (MOSTRAR HOSTS ESCLAVOS)
'binLogFileName': nombre del archivo de registro bin desde el que comenzar
'binLogPosition': posición del registro del contenedor desde donde comenzar
'eventsOnly' - matriz para escuchar eventos (lista completa en el archivo ConstEventType.php)
'eventsIgnore' - matriz para ignorar eventos (lista completa en el archivo ConstEventType.php)
'tablesOnly': matriz para escuchar solo en tablas determinadas (por defecto, todas las tablas)
'databasesOnly': matriz para escuchar solo en bases de datos determinadas (por defecto, todas las bases de datos)
'tableCacheSize': algunos datos se recopilan del esquema de información y estos datos se almacenan en caché.
'personalizado' - si algunos parámetros deben establecerse en clases propias extendidas/implementadas
'heartbeatPeriod': establece el intervalo en segundos entre los latidos de replicación. Cada vez que el registro binario del maestro se actualiza con un evento, se restablece el período de espera para el siguiente latido. intervalo es un valor decimal que tiene un rango de 0 a 4294967 segundos y una resolución en milisegundos; el valor más pequeño distinto de cero es 0,001. El maestro envía los latidos solo si no hay eventos no enviados en el archivo de registro binario durante un período mayor que el intervalo.
'saveUuid': establece el uuid esclavo para la identificación (predeterminado: 0015d2b6-8a06-4e5e-8c07-206ef3fbd274)
Rubí: https://github.com/y310/kodama
Java: https://github.com/shyiko/mysql-binlog-connector-java
IR: https://github.com/siddontang/go-mysql
Python: https://github.com/noplay/python-mysql-replication
.NET: https://github.com/rusuly/MySqlCdc
Todos los ejemplos están disponibles en el directorio de ejemplos.
Este ejemplo volcará todos los eventos de replicación a la consola:
Recuerde cambiar la configuración de su usuario, host y contraseña.
El usuario debe tener privilegios de replicación [CLIENTE DE REPLICACIÓN, SELECCIONAR]
php example/dump_events.php
Para eventos de SQL de prueba:
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 ;
La salida será similar a esta (depende de la configuración, por ejemplo, GTID activado/desactivado):
=== 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
Probado en máquina virtual
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)
Bueno, antes que nada, MYSQL no te ofrece llamadas asíncronas. Por lo general, necesita programar esto en su aplicación (despachando eventos y agregándolos a algún sistema de cola y si su base de datos tiene muchos puntos de entrada como la web, backend de otros microservicios, no siempre es barato agregar procesamiento a todos ellos. Pero usar la replicación de MySQL protocolo, puede escuchar eventos de escritura y procesarlos de forma asincrónica (la mejor combinación es agregar elementos a algún sistema de cola como Rabbitmq, Redis o Kafka. También para invalidar caché, replicación de motores de búsqueda, análisis y auditorías en tiempo real).
Bueno, antes que nada, debes saber que pueden ocurrir muchos eventos, como si actualizas 1.000.000 de registros en la tabla "bar" y necesitas insertar este desde tu tabla "foo". Entonces todo debe procesarse mediante un script. y debes esperar tus datos. Esto es normal y así es como funciona. Puede acelerar usando las opciones de configuración. Además, si el script falla, debe guardar de vez en cuando la posición del binlog (o gtid) para comenzar desde esta posición cuando ejecute este script nuevamente para evitar duplicados.
Como mencioné en 1 punto, use sistemas de cola como Rabbitmq, Redis o Kafka, le brindarán la capacidad de procesar datos en múltiples scripts.
Crea un problema. Intentaré trabajar en ello en mi tiempo libre :)
Funciona como cualquier otro MYSQL en modo esclavo y genera la misma sobrecarga.
Para solucionar este problema, lo mejor es aumentar las configuraciones de base de datos net_read_timeout
y net_write_timeout
a 3600. (tx Bijimon)
Establezca en my.conf binlog_row_image=full
para corregir la recepción solo de actualizaciones parciales.
Establezca en my.conf log_slave_updates=on
para solucionar este problema (#71)(#66)
La configuración predeterminada de MYSQL genera una gran cantidad de flujo que requiere más RAM/CPU. Puede cambiar esto para un flujo más pequeño usando 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] para dividir en partes más pequeñas