實現mysql和redis之間的觸發數據同步——mysql 觸發器+gearman+php.worker

上回一次我們已經實現了 redis 作爲 mysql 的緩存服務器,但是如果更新了 mysql,redis

中仍然會有對應的 KEY,數據就不會更新,此時就會出現 mysql 和 redis 數據不一致的情

況。


詳情請見        基於redis緩存數據庫實現lnmp架構高速訪問



所以接下來就要通過 mysql 觸發器將改變的數據同步到 redis 中。

因爲mysql和redis數據格式不同,不能實現直接同步,所以


將MySQL數據首先放入Gearman中,然後通過一個自己編寫的PHP Gearman Worker,將數據同步到Redis。



Gearman 是一個支持分佈式的任務分發框架:

Gearman Job Server: Gearman 核心程序,需要編譯安裝並以守護進程形式運行在後臺。

Gearman Client:可以理解爲任務的請求者。

Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯並通過守護進程方式運行.



Gearman Worker 接收到 Gearman Client 傳遞的任務內容後,會按順序處理。

大致流程:

1)下面要編寫的 mysql 觸發器,就相當於 Gearman 的客戶端。

2)修改表,插入表就相當於直接下發任務。

3)再通過 lib_mysqludf_json UDF 庫函數將關係數據映射爲 JSON 格式

4)再通過 gearman-mysql-udf 插件將任務加入到 Gearman 的任務隊列中

5)最後通過redis_worker.php,也就是 Gearman 的 worker 端來完成 redis 數據庫的更新。



詳細配置見下文...


server12(lnmp)


php裝載gearman插件

    //yum install rubygems-1.3.7-5.el6.noarch.rpm -y
   cd /mnt/redis/
   yum install libgearman-* lib* -y
   yum install gearmand-1.1.8-2.el6.x86_64.rpm -y

   tar zxf gearman-1.1.2.tgz
   cd gearman-1.1.2
   phpize     #進入預編譯環境
   ./configure
   make && make install
   ls /usr/lib64/php/modules    #查看當前模塊
   cd /etc/php.d/
   cp mysql.ini gearman.ini
     
   vim gearman.ini
   2 extension=gearman.so
/etc/init.d/php-fpm restart


查看gearman模塊是否添加成功.

查看mysql redis gearman 模塊是否都添加成功...

[root@server12 php.d]# php -m |grep gearman
gearman
[root@server12 php.d]# php -m |grep mysql
mysql
mysqli
pdo_mysql
[root@server12 php.d]# php -m |grep redis
redis


vim worker.php

  1 <?php
 2 $worker = new GearmanWorker();
 3 $worker->addServer();
 4 $worker->addFunction('syncToRedis', 'syncToRedis');
 5
 6 $redis = new Redis();
 7 $redis->connect('172.25.88.13', 6379);    #redis數據庫所在的主機IP
 8
 9 while($worker->work());
10 function syncToRedis($job)
11 {
12         global $redis;
13         $workString = $job->workload();
14         $work = json_decode($workString);
15         if(!isset($work->id)){
16                 return false;
17         }
18         $redis->set($work->id, $work->name);
19 }
20 ?>
[root@server12 redis]# nohup php worker.php &>/dev/null &   #不間斷地運行命令。

[root@server12 redis]# ps ax
1361 pts/0    S      0:00 php worker.php


[root@server12 php.d]# /etc/init.d/gearmand start
Starting gearmand:                                         [  OK  ]
[root@server12 php.d]# netstat -antlpue |grep 4730
tcp        0      0 0.0.0.0:4730                0.0.0.0:*                   LISTEN      495        17787      3594/gearmand      
tcp        0      0 :::4730                     :::*                        LISTEN      495        17788      3594/gearmand


server11:數據庫


生成libgearman_mysql_udf模塊

這個插件是用來管理調用 Gearman 的分佈式的隊列。

yum install mysql-devel -y
tar zxf gearman-mysql-udf-0.6.tar.gz
yum install lib* -y
[root@server11 redis]# ll lib*
-rw-r--r-- 1 root root  67428 Apr  2 21:43 libevent-1.4.13-4.el6.x86_64.rpm
-rw-r--r-- 1 root root  75620 Apr  2 21:43 libevent-devel-1.4.13-4.el6.x86_64.rpm
-rw-r--r-- 1 root root 198408 Apr  2 21:43 libevent-doc-1.4.13-4.el6.noarch.rpm
-rw-r--r-- 1 root root  30460 Apr  2 21:43 libevent-headers-1.4.13-4.el6.noarch.rpm
-rw-r--r-- 1 root root  71272 Apr  2 21:43 libgearman-1.1.8-2.el6.x86_64.rpm
-rw-r--r-- 1 root root 219472 Apr  2 21:43 libgearman-devel-1.1.8-2.el6.x86_64.rpm


./configure --with-mysql=/usr/bin/mysql_config --libdir=/usr/lib64/mysql/plugin/
make && make install


註冊 UDF 函數

mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME
   -> 'libgearman_mysql_udf.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME
   -> 'libgearman_mysql_udf.so';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mysql.func;
+--------------------+-----+-------------------------+----------+
| name               | ret | dl                      | type     |
+--------------------+-----+-------------------------+----------+
| gman_do_background |   0 | libgearman_mysql_udf.so | function |
| gman_servers_set   |   0 | libgearman_mysql_udf.so | function |
+--------------------+-----+-------------------------+----------+
2 rows in set (0.00 sec)


生成lib_mysqludf_json.so模塊

lib_mysqludf_json UDF 庫函數將關係數據映射爲 JSON 格式。通常,數據庫中的數據映

射爲 JSON 格式,是通過程序來轉換的.


[root@server11 lib_mysqludf_json-master]# gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
[root@server11 lib_mysqludf_json-master]# ls
lib_mysqludf_json.c     lib_mysqludf_json.so   README.md
lib_mysqludf_json.html  lib_mysqludf_json.sql
[root@server11 lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/


註冊 json 函數

mysql> CREATE FUNCTION json_object RETURNS STRING SONAME
   -> 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mysql.func;
+--------------------+-----+-------------------------+----------+
| name               | ret | dl                      | type     |
+--------------------+-----+-------------------------+----------+
| gman_do_background |   0 | libgearman_mysql_udf.so | function |
| gman_servers_set   |   0 | libgearman_mysql_udf.so | function |
| json_object        |   0 | lib_mysqludf_json.so    | function |
+--------------------+-----+-------------------------+----------+
3 rows in set (0.00 sec)


編寫 mysql 觸發器


vim test.sql

DELIMITER $$
CREATE TRIGGER datatoredis AFTER UPDATE ON test FOR EACH ROW BEGIN
   SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`));
 END$$
DELIMITER ;

[root@server11 redis]# mysql < test.sql    


查看觸發器

mysql> SHOW TRIGGERS FROM test;
| datatoredis | UPDATE | test  | BEGIN
   SET @RECV=gman_do_background('syncToRedis', json_object(NEW.id as `id`, NEW.name as `name`));
 END | AFTER  | NULL    |          | root@localhost | latin1               | latin1_swedish_ci    | latin1_swedish_ci  |
+-------------+--------+-------+--------------------------------------------------


指定 gearman 的服務信息

mysql> select gman_servers_set('172.25.88.12:4730');    #gearman所在的主機
+---------------------------------------+
| gman_servers_set('172.25.88.12:4730') |
+---------------------------------------+
| 172.25.88.12:4730                     |
+---------------------------------------+
1 row in set (0.00 sec)


server13(redis):

簡單配置保證redis服務開啓即可.

詳細配置移步:

基於redis緩存數據庫實現lnmp架構高速訪問


檢驗

server11:

mysql> update test.test set name ='ddd' where id =3;

server12:

[root@server13 redis]# redis-cli 

127.0.0.1:6379> get 3 "ddd"


更新mysql數據庫的值,也能實時同步到redis中,並被客戶端獲取


客戶端:

瀏覽器訪問 http://172.25.88.12/

wKioL1jni_zzXoNcAABLzhMEbOo974.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章