配置 gearman 实现数据同步
Gearman是一个支持分布式的任务分发框架。
Gearman Job Server:Gearman核心程序,以守护进程形式运行在后台。
Gearman Client:可以理解为任务的收件员,比如我要在后台执行一个发送邮件的任务,可以在程序中调用一个Gearman Client并传入邮件的信息,然后就可以将执行结果立即展示给用户,而任务本身会慢慢在后台运行。
Gearman Worker:任务的真正执行者,一般需要自己编写具体逻辑并通过守护进程方式运行。
Gearman Worker接收到Gearman Client传递的任务内容后,会按顺序处理。
首先利用mysql UDF(通过了lib_mysqludf_json和gearman-mysql-udf的组合实现)在mysql中的数据发生改变时触动触发器将数据传入Gearman中,这时的mysql相当于Gearman的clinet。然后运行自己编写的php程序作为worker,将Gearman中的数据传到Redis中去,这时的Redis相当于是Gearman的consumer。
安装 lib_mysqludf_json
lib_mysqludf_json UDF 库函数将关系数据映射为 JSON 格式。通常,数据库中的数据映
射为 JSON 格式,是通过程序来转换的。
需要安装gcc、mariadb-devel和lib_mysqludf_json-master
[root@server4 ~]# yum install -y mariadb-devel
[root@server4 ~]# ls
anaconda-screenshots lib_mysqludf_json-master.zip test.sql
[root@server4 ~]# yum install -y unzip
[root@server4 ~]# unzip lib_mysqludf_json-master.zip
[root@server4 ~]# cd lib_mysqludf_json-master/
[root@server4 lib_mysqludf_json-master]# yum install -y gcc ##安装gcc
[root@server4 lib_mysqludf_json-master]# ls
[root@server4 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
[root@server4 plugin]# pwd ##plugin所在目录
/usr/lib64/mysql/plugin
[root@server4 plugin]# mysql
MariaDB [(none)]> show global variables like 'plugin_dir';
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| plugin_dir | /usr/lib64/mysql/plugin/ |
+---------------+--------------------------+
1 row in set (0.00 sec)MariaDB [(none)]> exit
Bye
[root@server4 plugin]# cd
[root@server4 ~]# cd lib_mysqludf_json-master/
[root@server4 lib_mysqludf_json-master]# ls
lib_mysqludf_json.c lib_mysqludf_json.so README.md
lib_mysqludf_json.html lib_mysqludf_json.sql
[root@server4 lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/
[root@server4 lib_mysqludf_json-master]# cd /usr/lib64/mysql/plugin/
[root@server4 plugin]# ls
[root@server4 plugin]# mysqlMariaDB [(none)]> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so'; ##注册 UDF 函数MariaDB [(none)]> select * from mysql.func;
安装 gearman-mysql-udf
这个插件是用来管理调用 Gearman 的分布式的队列。
Gearman MySQL UDF in Launchpad
[root@server4 ~]# tar zxf gearman-mysql-udf-0.6.tar.gz
[root@server4 ~]# ls
anaconda-screenshots libgearman-devel-1.1.12-18.el7.x86_64.rpm
gearman-mysql-udf-0.6 lib_mysqludf_json-master
gearman-mysql-udf-0.6.tar.gz lib_mysqludf_json-master.zip
libevent-devel-2.0.21-4.el7.x86_64.rpm test.sql
libgearman-1.1.12-18.el7.x86_64.rpm
[root@server4 ~]# yum install -y libgearman-* libevent-*
[root@server4 ~]# cd gearman-mysql-udf-0.6/
[root@server4 gearman-mysql-udf-0.6]# ls
aclocal.m4 ChangeLog config.h.in configure COPYING m4 Makefile.in README
AUTHORS config config.log configure.ac libgearman_mysql_udf Makefile.am NEWS
[root@server4 gearman-mysql-udf-0.6]# ./configure --libdir=/usr/lib64/mysql/plugin/ --with-mysql ##编译[root@server4 gearman-mysql-udf-0.6]# make && make install
注册 UDF 函数
[root@server4 gearman-mysql-udf-0.6]# cd /usr/lib64/mysql/plugin
[root@server4 plugin]# ls
[root@server4 plugin]# mysql
MariaDB [(none)]> CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';MariaDB [(none)]> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';MariaDB [(none)]> select * from mysql.func; ##查看函数
在server2中:
[root@server2 ~]# ls
anaconda-screenshots php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm
gearmand-1.1.12-18.el7.x86_64.rpm php-pecl-redis-2.2.8-1.el7.x86_64.rpm
libgearman-1.1.12-18.el7.x86_64.rpm redis-6.2.4
mysql-5.7.31 redis-6.2.4.tar.gz
mysql-boost-5.7.31.tar.gz test
nginx-1.20.2 test.php
nginx-1.20.2.tar.gz test.sql
php-fpm-5.4.16-46.el7.x86_64.rpm
[root@server2 ~]# yum install gearmand-1.1.12-18.el7.x86_64.rpm libgearman-1.1.12-18.el7.x86_64.rpm
[root@server2 ~]# systemctl start gearmand.service
[root@server2 ~]# netstat -antlup
server2中要开启4730端口:
在server4中:
MariaDB [(none)]> SELECT gman_servers_set('172.25.52.2:4730'); ##指定 gearman 的服务信息
编写 mysql 触发器
[root@server4 ~]# vim test.sql
use test;
#CREATE TABLE `test` (`id` int(7) NOT NULL AUTO_INCREMENT, `name` char(8) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#INSERT INTO `test` VALUES (1,'test1'),(2,'test2'),(3,'test3'),(4,'test4'),(5,'test5'),(6,'test6'),(7,'test7'),(8,'test8'),(9,'test9');DELIMITER $$
CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGINSET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`)); END$$
DELIMITER ;
[root@server4 ~]# mysql < test.sql
[root@server4 ~]# mysql
MariaDB [(none)]> SHOW TRIGGERS FROM test;
编写 gearman 的 worker 端( 在server2中)
[root@server2 ~]# ls
anaconda-screenshots nginx-1.20.2.tar.gz test
gearmand-1.1.12-18.el7.x86_64.rpm php-fpm-5.4.16-46.el7.x86_64.rpm test.php
libgearman-1.1.12-18.el7.x86_64.rpm php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm test.sql
mysql-5.7.31 php-pecl-redis-2.2.8-1.el7.x86_64.rpm worker.php
mysql-boost-5.7.31.tar.gz redis-6.2.4
nginx-1.20.2 redis-6.2.4.tar.gz
[root@server2 ~]# vim worker.php
<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis', 'syncToRedis');$redis = new Redis();
$redis->connect('172.25.52.3', 6379);while($worker->work());
function syncToRedis($job)
{global $redis;$workString = $job->workload();$work = json_decode($workString);if(!isset($work->id)){return false;}$redis->set($work->id, $work->name);
}
?>
[root@server2 ~]# php -m | grep redis
redis
[root@server2 ~]# yum install php-pecl-gearman-1.1.2-1.el7.x86_64.rpm -y
[root@server2 ~]# php -m | grep redis
redis
[root@server2 ~]# php -m | grep gearman
gearman
[root@server2 ~]# systemctl reload php-fpm
[root@server2 ~]# ls
anaconda-screenshots php-pecl-igbinary-1.2.1-1.el7.x86_64.rpm
gearmand-1.1.12-18.el7.x86_64.rpm php-pecl-redis-2.2.8-1.el7.x86_64.rpm
libgearman-1.1.12-18.el7.x86_64.rpm redis-6.2.4
mysql-5.7.31 redis-6.2.4.tar.gz
mysql-boost-5.7.31.tar.gz test
nginx-1.20.2 test.php
nginx-1.20.2.tar.gz test.sql
php-fpm-5.4.16-46.el7.x86_64.rpm worker.php
php-pecl-gearman-1.1.2-1.el7.x86_64.rpm
[root@server2 ~]# mv worker.php /usr/local/
[root@server2 ~]# which php
/usr/bin/php
[root@server2 ~]# php /usr/local/worker.php ##开启
测试:
在server4中:MariaDB [(none)]> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
MariaDB [test]> update test set name='gyy' where id=1;
Query OK, 1 row affected (0.06 sec)
Rows matched: 1 Changed: 1 Warnings: 0MariaDB [test]> select * from test;
在server3中(redis-cli)
127.0.0.1:6379> get 1
"gyy"
127.0.0.1:6379> get 2
"test2"
127.0.0.1:6379> get 1
"gyy"
127.0.0.1:6379> get 1
"gyy"
127.0.0.1:6379> get 1
"gyy"
127.0.0.1:6379> get 1
"cyy"
127.0.0.1:6379> get 1
"cyy"
127.0.0.1:6379>
浏览器访问: http://172.25.52.2/test.php
在数据库中修改:
MariaDB [test]> update test set name='cyy' where id=1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0MariaDB [test]>
在redis查看:
浏览器访问: http://172.25.52.2/test.php ------->实现数据的同步