通過Gearman實現MySQL到Redis的資料同步

來源:互聯網
上載者:User

通過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應用程式套件括以下這些部分:

  • Gearman Job Server:Gearman核心程式,需要編譯安裝並以守護進程形式運行在後台
  • Gearman Client:可以理解為任務的收件員,比如我要在後台執行一個發送郵件的任務,可以在程式中調用一個Gearman Client並傳入郵件的資訊,然後就可以將執行結果立即展示給使用者,而任務本身會慢慢在後台運行。
  • Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯並通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容後,會按順序處理。

以前曾經介紹過類似的背景工作處理項目Resque。兩者的設計其實非常接近,簡單可以類比為:

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

這裡之所以選擇Gearman而不是Resque是因為Gearman提供了比較好用的MySQL UDF,工作量更小。

安裝Gearman及PHP Gearman擴充
以下均以Ubuntu12.04為例。

apt-get install gearman gearman-server libgearman-dev

檢查Gearman的健全狀態:

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

說明Gearman已經安裝成功。
PHP的Gearman擴充可以通過pecl直接安裝

pecl install gearmanecho "extension=gearman.so">/etc/php5/conf.d/gearman.iniservice php5-fpm restart

但是實測發現ubuntu預設安裝的gearman版本過低,直接運行pecl install gearman會報錯

configure: error: libgearman version 1.1.0or later required

因此Gearman + PHP擴充建議通過編譯方式安裝,這裡為了簡單說明,選擇安裝舊版本擴充:

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頁面後,將處理結束的資訊返回使用者:

php client.php

查看一下Gearman的狀況:

(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_json和gearman-mysql-udf的組合。

安裝lib_mysqludf_json
使用lib_mysqludf_json的原因是因為Gearman只接受字串作為入口參數,可以通過lib_mysqludf_json將MySQL中的資料編碼為JSON字串

apt-get install libmysqlclient-devwget https://github.com/mysqludf/lib_mysqludf_json/archive/master.zipunzip master.zipcd lib_mysqludf_json-master/rm lib_mysqludf_json.sogcc $(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-devwget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gztar -xzf gearman-mysql-udf-0.6.tar.gzcd 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 redisecho "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安裝及簡單測試

Redis叢集明細文檔

Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis串連Redis

Redis系列-安裝部署維護篇

CentOS 6.3安裝Redis

Redis安裝部署學習筆記

Redis設定檔redis.conf 詳解

Redis 的詳細介紹:請點這裡
Redis 的:請點這裡

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

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.