利用gearman實現redis緩衝mysql

來源:互聯網
上載者:User

標籤:快取資料庫 redis mysql gearman

環境:

    centos6.5

    mysql5.6

gearman簡介:

        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。


1、安裝gearman

    實驗中的系統yum源在centos6.5內建的網路yum源的基礎上,增加了epel的源,EPEL (Extra Packages for Enterprise Linux,企業版Linux的額外軟體包) 是Fedora小組維護的一個軟體倉庫項目,為RHEL/CentOS提供他們預設不提供的軟體包。使用這個源可以免去很多麻煩,省去源碼編譯的麻煩,需要注意的是,不論是使用centos內建的網路yum源還是epel擴充源,都需要你的IP能夠訪問到公網。

    安裝gearman、php、php的gearman擴充、nc工具

yum install -y php-pecl-gearman libgearman  libgearman-devel gearmand nc

    啟動gearman服務

/etc/init.d/gearmand start

    驗證gearman是否成功啟動,如果返回的結果中有4730連接埠,那麼表示服務已經正常啟動了

[[email protected] ~]# netstat -alnutp |grep gearman

2、類比Gearman的工作原理:

    使用下列命令查看Gearman的隊列

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

    結果如下

writeLog        0       0       0

    四列含義:1-任務名稱;2-等待隊列任務數;3-運行中的任務數;4-正在啟動並執行worker進程數;


    編譯一段php代碼類比Gearman的Client:client.php

<?php    $client = new GearmanClient();    $client->addServer();    $client->doBackground(‘writeLog‘, ‘Log content‘);    echo ‘檔案已經在後台操作‘;    echo "\n";

    執行client.php

php client.php

    這時,再次查看Gearman的隊列,發現等待隊列中有一個任務

writeLog        1       0       0

    

    編寫一段php代碼類比Gearman的Worker:worker.php

    該worker的作用是將用戶端傳遞給Gearman的字串‘Log content‘寫入到目前的目錄下的gearman.log檔案中

<?php    $worker = new GearmanWorker();    $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);    }

    以nohup的方式後台啟動worker.php

nohup php worker.php &

    再次查看Gearman的隊列,發現等待的任務變成0,worker進程變成了1,gearman.log有了內容

writeLog        0       0       1
[[email protected] ~]# cat gearman.log Log content

3、安裝mysql-server、mysql、php-mysql(php串連mysql的驅動,非必須,這裡是為了稍後用程式比較從Redis和Mysql中分別讀取資料的效率)。實驗中,由於我的機子上之前已將安裝了mysql5.6,所以就直接使用mysql5.6做實驗了。當然也可以使用yum開安裝mysql,可能安裝的mysql版本不是5.6,但是完全沒有關係。

    安裝mysql相關軟體

yum install -y mysql-server mysql php-mysql

    啟動mysql

/etc/init.d/mysql start

4、安裝lib_mysqludf_json

wget  https://github.com/mysqludf/lib_mysqludf_json/archive/master.zipmv master master.zipunzip master.zipcd lib_mysqludf_json-masterrm -rf lib_mysqludf_json.so gcc $(mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c

這時重新編譯產生了lib_mysqludf_json.so,然後需要把lib_mysqludf_json.so拷貝到mysql的外掛程式目錄下,查看mysql的外掛程式目錄:

[[email protected] ~]# mysql -u root -pupbjsxt --execute="show variables like ‘%plugin%‘;"    +---------------+--------------------------+| Variable_name | Value                    |+---------------+--------------------------+| plugin_dir    | /usr/lib64/mysql/plugin/ |+---------------+--------------------------+
[[email protected] lib_mysqludf_json-master]# cp lib_mysqludf_json.so /usr/lib64/mysql/plugin/

5、安裝gearman-mysql-udf

wget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz   tar xf gearman-mysql-udf-0.6.tar.gz -C ./cd gearman-mysql-udf-0.6./configure --with-mysql=/usr/bin/mysql_config --libdir=/usr/lib64/mysql/plugin/make && make install

該外掛程式直接安裝到了mysql的外掛程式目錄下。

6、連入mysql,建立對應的function、trigger及設定gearman server資訊

[[email protected] ~]# mysql -u root -p****** mysql> CREATE FUNCTION json_object RETURNS STRING SONAME ‘lib_mysqludf_json.so‘;mysql> CREATE FUNCTION gman_do_background RETURNS STRING SONAME ‘libgearman_mysql_udf.so‘;mysql> CREATE FUNCTION gman_servers_set RETURNS STRING SONAME ‘libgearman_mysql_udf.so‘## 為javashop中的test表建立觸發器mysql> use javashop;mysql> describe test;+-------+----------+------+-----+---------+-------+| Field | Type     | Null | Key | Default | Extra |+-------+----------+------+-----+---------+-------+| id    | int(11)  | YES  |     | NULL    |       || name  | char(20) | YES  |     | NULL    |       |+-------+----------+------+-----+---------+-------+2 rows in set (0.00 sec)mysql> source trigger.sql## 設定gearman server資訊mysql>SELECT gman_servers_set(‘127.0.0.1:4730‘);

    trigger.sql指令檔內容如下

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

7、在mysql中更新一條資料,然後查看gearman的隊列

mysql> update test set name=‘redis‘ where id=10;Query OK, 1 row affected (0.03 sec)Rows matched: 1  Changed: 1  Warnings: 0
writeLog        0       0       1syncToRedis     1       0       0

可見mysql觸發器已經成功的將資料傳入到gearman中了。

8、安裝redis、php-pecl-redis(php串連redis的驅動)

yum install php-pecl-redis redis -y

    啟動redis

/etc/init.d/redis   start

    登入redis用戶端,查看當前記憶體中的資料

[[email protected] ~]# redis-cli redis 127.0.0.1:6379> keys *(empty list or set)

這時,redis中並沒有資料。

9、編寫一個worker程式,負責將gearman中的資料傳入到redis中去:redis_worker.php

<?php    $worker = new GearmanWorker();    $worker->addServer();    $worker->addFunction(‘syncToRedis‘, ‘syncToRedis‘);    $redis = new Redis();    $redis->connect(‘127.0.0.1‘);    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, $workString);    }

10、以nohup的方式後台運行redis_worker.php

nohup php redis_worker.php &

    這時,再查看gearman的隊列

writeLog        0       0       1syncToRedis     0       0       1

    發現syncToRedis任務之前等待的任務數變為了0,正在啟動並執行worker進程數變為了1。

    檢查redis中是否緩衝了資料

[[email protected] ~]# redis-cli redis 127.0.0.1:6379> keys *1) "10"redis 127.0.0.1:6379> get 10"{\"id\":10,\"name\":\"redis\"}"

    發現redis中已經成功的緩衝了mysql中更新的資料,至此功能實現。


11、從redis中讀取資料和從mysql中讀取資料效能比較

    編寫php代碼,從redis中讀取資料:php_redis.php

<?php      $stime=microtime(true); //擷取程式開始執行的時間      $redis = new Redis();     $redis->connect(‘127.0.0.1‘);     echo $redis->get(‘10‘);      echo "\n";    $redis->close();     $etime=microtime(true);//擷取程式執行結束的時間      $total=$etime-$stime;   //計算差值      echo "$total".‘秒‘;      echo "\n";?>

    編寫php代碼,從mysql中讀取資料:php_mysql.php

<?php    $stime=microtime(true); //擷取程式開始執行的時間      $con = mysql_connect("127.0.0.1","root","******");    $r2 = mysql_select_db("javashop");    $result = mysql_query("SELECT * FROM test limit 1");    while ($row = mysql_fetch_array($result)) {        echo $row[‘id‘] . " --> " . $row[‘name‘];        echo "\n";    }    mysql_close($con);    $etime=microtime(true);//擷取程式執行結束的時間      $total=$etime-$stime;   //計算差值      echo "$total".‘秒‘;      echo "\n"?>

    分別運行兩個php程式

[[email protected] ~]# php php_redis.php {"id":10,"name":"redis"}0.00059199333190918秒[[email protected] ~]# php php_mysql.php 10 --> redis0.0043718814849854秒[[email protected] ~]# bc <<< 0.0043718814849854/0.000591993331909187

    通過對一條記錄的查詢,可以發現,從mysql中擷取資料的時間長度是redis中擷取資料時間長度的7倍,可見度能的提升幾乎達一個數量級。


注意點:

    親測印證了mysql在重啟後會丟失之前設定的gearman server的資訊,解決辦法如下:

    在mysql的datadir目錄下建立init_file.sql檔案,內容為gearman server的資訊的設定

echo  "SELECT gman_servers_set(‘127.0.0.1:4730‘);" > /var/lib/mysql/init_file.sql

    然後在mysql的設定檔的[mysqld]項中添加如下內容

init-file=/var/lib/mysql/init_file.sql

    然後重啟mysql,更新一條記錄再試試看!


參考:http://avnpc.com/pages/mysql-replication-to-redis-by-gearman


PS:完成了第一篇部落格,希望大家多多指教,祝生活愉快!

本文出自 “不逼自己就不自知有多牛逼” 部落格,請務必保留此出處http://quenlang.blog.51cto.com/4813803/1568567

利用gearman實現redis緩衝mysql

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.