經過Gearman實現MySQL到Redis的數據同步

對於變化頻率很是快的數據來講,若是還選擇傳統的靜態緩存方式(Memocached、File System等)展現數據,可能在緩存的存取上會有很大的開銷,並不能很好的知足須要,而Redis這樣基於內存的NoSQL數據庫,就很是適合擔任實時數據的容器。

可是每每咱們又有數據可靠性的需求,採用MySQL做爲數據存儲,不會由於內存問題而引發數據丟失,同時也能夠利用關係數據庫的特性實現不少功能。

因此就會很天然的想到是否能夠採用MySQL做爲數據存儲引擎,Redis則做爲Cache。而這種需求目前尚未看到有特別成熟的解決方案或工具,所以本文將嘗試採用Gearman+PHP+MySQL UDF的組合異步實現MySQL到Redis的數據複製。

MySQL到Redis數據複製方案
不管MySQL仍是Redis,自身都帶有數據同步的機制,像比較經常使用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog來實現的,這樣的數據複製其實仍是一個異步過程,只不過當服務器都在同一內網時,異步的延遲幾乎能夠忽略。

那麼理論上咱們也能夠用一樣方式,分析MySQL的binlog文件並將數據插入Redis。可是這須要對binlog文件以及MySQL有很是深刻的理解,同時因爲binlog存在Statement/Row/Mixedlevel多種形式,分析binlog實現同步的工做量是很是大的。

所以這裏選擇了一種開發成本更加低廉的方式,借用已經比較成熟的MySQL UDF,將MySQL數據首先放入Gearman中,而後經過一個本身編寫的PHP Gearman Worker,將數據同步到Redis。比分析binlog的方式增長了很多流程,可是實現成本更低,更容易操做。
Gearman的安裝與使用

Gearman是一個支持分佈式的任務分發框架。設計簡潔,得到了很是普遍的支持。一個典型的Gearman應用包括如下這些部分:php

  • Gearman Job Server:Gearman核心程序,須要編譯安裝並以守護進程形式運行在後臺
  • Gearman Client:能夠理解爲任務的收件員,好比我要在後臺執行一個發送郵件的任務,能夠在程序中調用一個Gearman Client並傳入郵件的信息,而後就能夠將執行結果當即展現給用戶,而任務自己會慢慢在後臺運行。
  • Gearman Worker:任務的真正執行者,通常須要本身編寫具體邏輯並經過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容後,會按順序處理。

之前曾經介紹過相似的後臺任務處理項目Resque。二者的設計其實很是接近,簡單能夠類比爲:mysql

  • Gearman Job Server:對應Resque的Redis部分
  • Gearman Client:對應Resque的Queue操做
  • Gearman Worker:對應Resque的Worker和Job

這裏之因此選擇Gearman而不是Resque是由於Gearman提供了比較好用的MySQL UDF,工做量更小。

安裝Gearman及PHP Gearman擴展
如下均以Ubuntu12.04爲例。linux

apt-get install gearman gearman-server libgearman-dev

檢查Gearman的運行情況:git

/etc/init.d/gearman-job-server status * gearmand is running

說明Gearman已經安裝成功。
PHP的Gearman擴展能夠經過pecl直接安裝github

pecl install gearman
echo "extension=gearman.so">/etc/php5/conf.d/gearman.ini service php5-fpm restart

可是實測發現ubuntu默認安裝的gearman版本太低,直接運行pecl install gearman會報錯redis

configure: error: libgearman version 1.1.0or later required

所以Gearman + PHP擴展建議經過編譯方式安裝,這裏爲了簡單說明,選擇安裝舊版本擴展:sql

pecl install gearman-1.0.3

Gearman + PHP實例
爲了更容易理解後文Gearman的運行流程,這裏不妨從一個最簡單的Gearman實例來講明,好比咱們要進行一個文件處理的操做,首先編寫一個Gearman Client並命名爲client.php:數據庫

<?php $client =newGearmanClient(); $client->addServer(); $client->doBackground('writeLog','Log content'); echo '文件已經在後臺操做';

運行這個文件,至關於模擬用戶請求一個Web頁面後,將處理結束的信息返回用戶:json

php client.php

查看一下Gearman的情況:ubuntu

(echo status ; sleep 0.1)| netcat127.0.0.14730

能夠看到輸出爲

writeLog        100.

說明咱們已經在Gearman中創建了一個名爲writeLog的任務,而且有1個任務在隊列等待中。
而上面的4列分別表明當前的Gearman的運行狀態

  1. 任務名稱
  2. 在等待隊列中的任務
  3. 正在運行的任務
  4. 正在運行的Worker進程

可使用watch進行實時監控:

watch -n 1"(echo status; sleep 0.1) | nc 127.0.0.1 4730"

而後咱們須要編寫一個Gearman Worker命名爲worker.php:

<?php $worker =newGearmanWorker(); $worker->addServer(); $worker->addFunction('writeLog','writeLog');while($worker->work());function writeLog($job){ $log = $job->workload();file_put_contents(__DIR__ .'/gearman.log', $log ."\n", FILE_APPEND | LOCK_EX);}

Worker使用一個while死循環實現守護進程,運行

php worker.php

能夠看到Gearman狀態變爲:

writeLog        001


同時查看同目錄下gearman.log,內容應爲從Client傳入的值Log content

經過MySQL UDF + Trigger同步數據到Gearman
MySQL要實現與外部程序互通的最好方式仍是經過MySQL UDF(MySQL user defined functions)來實現。爲了讓MySQL能將數據傳入Gearman,這裏使用了lib_mysqludf_jsongearman-mysql-udf的組合。

安裝lib_mysqludf_json
使用lib_mysqludf_json的緣由是由於Gearman只接受字符串做爲入口參數,能夠經過lib_mysqludf_json將MySQL中的數據編碼爲JSON字符串

apt-get install libmysqlclient-dev wget https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip unzip master.zip cd lib_mysqludf_json-master/ rm lib_mysqludf_json.so gcc $(mysql_config --cflags)-shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c

能夠看到從新編譯生成了 lib_mysqludf_json.so 文件,此時須要查看MySQL的插件安裝路徑:

mysql -u root -pPASSWORD --execute="show variables like '%plugin%';"+---------------+------------------------+|Variable_name|Value|+---------------+------------------------+| plugin_dir |/usr/lib/mysql/plugin/|+---------------+------------------------+

而後將 lib_mysqludf_json.so 文件複製到對應位置:

cp lib_mysqludf_json.so /usr/lib/mysql/plugin/

最後登入MySQL運行語句註冊UDF函數:

CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';

安裝gearman-mysql-udf
方法幾乎同樣:

apt-get install libgearman-dev wget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz tar -xzf gearman-mysql-udf-0.6.tar.gz cd gearman-mysql-udf-0.6./configure --with-mysql=/usr/bin/mysql_config --libdir=/usr/lib/mysql/plugin/ make && make install

登入MySQL運行語句註冊UDF函數:

CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so'; CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';

最後指定Gearman服務器的信息:

SELECT gman_servers_set('127.0.0.1:4730');

經過MySQL觸發器實現數據同步
最終同步哪些數據,同步的條件,仍是須要根據實際狀況決定,好比我但願將數據表data的數據在每次更新時同步,那麼編寫Trigger以下:

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

嘗試在數據庫中更新一條數據查看Gearman是否生效。

Gearman PHP Worker將MySQL數據異步複製到Redis
Redis做爲時下當熱的NoSQL緩存解決方案無需過多介紹,其安裝及使用也很是簡單:

apt-get install redis-server pecl install redis echo "extension=redis.so">/etc/php5/conf.d/redis.ini

而後編寫一個Gearman Worker:redis_worker.php

#!/usr/bin/env php<? $worker =newGearmanWorker(); $worker->addServer(); $worker->addFunction('syncToRedis','syncToRedis'); $redis =newRedis(); $redis->connect('127.0.0.1',6379);while($worker->work());function syncToRedis($job){global $redis; $workString = $job->workload(); $work = json_decode($workString);if(!isset($work->id)){returnfalse;} $redis->set($work->id, $workString);}

最後須要將Worker在後臺運行:

nohup php redis_worker.php &

經過這種方式將MySQL數據複製到Redis,經測試單Worker基本能夠瞬時完成。

Ubuntu 14.04下Redis安裝及簡單測試 http://www.linuxidc.com/Linux/2014-05/101544.htm

Redis集羣明細文檔 http://www.linuxidc.com/Linux/2013-09/90118.htm

Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis鏈接Redis http://www.linuxidc.com/Linux/2013-06/85816.htm

Redis系列-安裝部署維護篇 http://www.linuxidc.com/Linux/2012-12/75627.htm

CentOS 6.3安裝Redis http://www.linuxidc.com/Linux/2012-12/75314.htm

Redis安裝部署學習筆記 http://www.linuxidc.com/Linux/2014-07/104306.htm

Redis配置文件redis.conf 詳解 http://www.linuxidc.com/Linux/2013-11/92524.htm

Redis 的詳細介紹請點這裏 
Redis 的下載地址請點這裏

from:http://avnpc.com/pages/mysql-replication-to-redis-by-gearman%20

本文永久更新連接地址http://www.linuxidc.com/Linux/2015-01/111380.htm

相關文章
相關標籤/搜索