Redis pub/sub(Publish,Subscribe)

目錄

Redis pub/sub(Publish,Subscribe)

1         Pub/Sub功能

2         Pub/Sub機制

3         Pub/Sub redis當中的實現

4         Php-redis擴展測試

5         Redis pub/sub python客戶端測試

6         Redis pub/subnode.js結合

7         Redis pub/sub壓力測試

8         Redis pub/sub服務應用場景分析

9         附件:

 


1、 Pub/Sub功能

Pub/Sub功能(means Publish, Subscribe即發佈及訂閱功能。基於事件的系統中,Pub/Sub是目前廣泛使用的通信模型,它採用事件作爲基本的通信機制,提供大規模系統所要求的鬆散耦合的交互模式:訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的一個事件或一類事件;發佈者(如服務器)可將訂閱者感興趣的事件隨時通知相關訂閱者。

 

Redis <wbr>pub/sub(Publish,Subscribe)

Publisher/subscribe 簡易模型

 

2、 Pub/Sub機制

Pub/Sub功能(means Publish,Subscribe即發佈及訂閱功能Redis <wbr>pub/sub(Publish,Subscribe)


 

1.       時間非耦合:發佈者和訂閱者不必同時在線,它們不必同時參與交互。

Redis <wbr>pub/sub(Publish,Subscribe)

 

2.       空間非耦合:發佈者和訂閱者不必相互知道對方所在的位置。發佈者通過事件服務發佈事件,訂閱者通過事件服務間接獲得事件。發佈者和訂閱者不需要擁有直接到對方的引用,也不必知道有多少個訂閱者或者是發佈者參與交互。

Redis <wbr>pub/sub(Publish,Subscribe)

 

3.       同步非耦合:發佈者/訂閱者是異步模式。發佈者可不斷地生產事件,而訂閱者(通過一個回調)則可異步地得到產生事件的通知。

Redis <wbr>pub/sub(Publish,Subscribe)




 

分類:

按照訂閱方式分爲基於主題(topic-based)、基於內容(content-based)、基於類型(type-based)的pub/sub方式。

 

 

 Redis <wbr>pub/sub(Publish,Subscribe)


 

 

總結:

Pub/Sub是可適用於可擴展要求高、鬆散耦合系統的分佈式交互模型。

在抽象層中,它的時間非耦合、空間非耦合和同步非耦合性可允許參與者不依賴另一個而獨立操作,具有一定的可擴展性;然而在實現層,可擴展性仍受其他原因的牽制。

例如:1、靈活的訂閱要求複雜的過濾和路由算法;

      2、高可用性開銷(事件偵聽、日誌重傳);

      3、消息認可帶來的網絡流量消耗;

4、龐大的訂閱者數據帶來的系統開銷;

基於事件的Pub/Sub中間件的開發與利用在一定程度上可以提高系統的效率。

3、 Pub/Sub redis當中的實現

Redis-cli連接測試命令行參考附件I

協議測試命令

 

l  訂閱者(redis-cli)連接訂閱

/usr/local/bin/redis-cli  -h 10.54.37.212 -p 6380


Redis <wbr>pub/sub(Publish,Subscribe)

 

redis-cli充當訂閱者訂閱(first second)兩個topic

SUBSCRIBE first second

Redis <wbr>pub/sub(Publish,Subscribe)

 

l  發佈者(redis-cli)連接發佈

/usr/local/bin/redis-cli  -h 10.54.37.212 -p 6380

Pubish first wangbin

Publish second wangbin_second

Redis <wbr>pub/sub(Publish,Subscribe)

l  訂閱者(redis-cli)信息接收

 

 Redis <wbr>pub/sub(Publish,Subscribe)


l  取消訂閱UNSUBSCRIBE測試

Redis-cli對取消訂閱有bug可以使用telnet 進行測試

 

Redis <wbr>pub/sub(Publish,Subscribe)

取消訂閱測試成功;

l  匹配模式訂閱PSUBSCRIBE測試

訂閱者:

Redis <wbr>pub/sub(Publish,Subscribe)

 

發佈者:

publish news.wangbin wangbin_patterncommand

Redis <wbr>pub/sub(Publish,Subscribe)

 

l  匹配模式取消訂閱PUNSUBSCRIBE測試

telnet下測試如下:

PSUBSCRIBE news.*  wangbin*

punsubscribe wangbin*

Redis <wbr>pub/sub(Publish,Subscribe)

 

測試成功!

4、 Php-redis擴展測試

https://github.com/nicolasff/phpredis pecl擴展包目前只提供了兩個接口 publish  subscribe

phpredisc寫的php模塊

https://github.com/jamm/Memory/blob/master/RedisServer.php

php這個是php是基於redis protocolfsocketopen鏈接後操作的類庫,提供的接口比較全面;publish可以進入數據,但是subscrbie沒有阻塞;

可以在原類包當中修改其加入對阻塞模形的支持;

發佈功能:

$redis = new Redis();

$res = $redis->connect($REDIS_HOSTS['CACHE']['host'], $REDIS_HOSTS['CACHE']['port'], 1 );

$res = $redis->publish($key,$value);

定閱功能:                           

$redis = new Redis();

$res = $redis->pconnect($REDIS_HOSTS['CACHE']['host'], $REDIS_HOSTS['CACHE']['port']);

$res = $redis->subscribe(array($key),array('SinaRedis','subscribe_handler'));

第二個參數爲回調方法;

public static function subscribe_handler($redis, $channel, $msg){

            print_r($redis);

            echo $chan;

            echo $msg;

            return true;

  }

 

定閱 redis_subscriber.php

SinaRedis::subscribe('wangbin_test');

發佈redis_publisher.php

測試收到訂閱者收到發佈的內容

 

 Redis <wbr>pub/sub(Publish,Subscribe)


Php-redis擴展bug

段錯誤:

無論是connect 還是pcconnect 當超時斷後,會報錯segmentation fault;

超時設置bug

仍會斷開解決方法:ini_set('default_socket_timeout', -1);// it works fine

Web Server端測試

Web端訂閱應用

Apacheob_flush flush後可以輸出,但是會漏下最後一條;求解決方案

Nginx 會報504錯誤;求解決方法

Nginx 模塊與redis直接連接呢?

Php-Fpm有沒有什麼設置呢

5、 Redis pub/sub python客戶端測試

Wget https://github.com/downloads/andymccurdy/redis-py/redis-2.2.4.tar.gz

tar -xvf   redis-2.2.4.tar.gz

cd redis-2.2.4

python setup.py intall

安裝成功

交互模式下測試:

發佈者:

Python

Type "help", "copyright", "credits" or "license" for more information.

>>> import redis

>>> r = redis.Redis('10.54.37.212',6380);

>>> r.publish('wangbin_test','this is a information');

59L

>>> 

訂閱者:

[root@hadoop-master1 python]# python

Python 2.4.3 (#1, Sep  3 2009, 15:37:12)

[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import redis

>>> r = redis.Redis('10.54.37.212',6380);

>>> r.subscribe('wangbin_test');

>>> for msg in r.listen(): \

...     print msg

{'pattern': None, 'type': 'message', 'channel': 'wangbin_test', 'data': 'this is a information'}

收到json字符串

Publisher.py

Redis <wbr>pub/sub(Publish,Subscribe)

 

Subscribe.py

 

 Redis <wbr>pub/sub(Publish,Subscribe)


6、 Redis pub/subnode.js結合

Wget http://nodejs.org/dist/v0.6.6/node-v0.6.6.tar.gz

Tar –xvf node-v0.6.6.tar.gz

Cd node-v0.6.6

./configure

Make

Make install

Node 安裝在/usr/localbin

添加到環境變量裏面:

export  PATH=/usr/local/bin/:$PATH

安裝:npm

curl -O http://npmjs.org/install.sh

sh install.sh

安裝成功

Tar 版本過低,升級下

wget http://ftp.gnu.org/gnu/tar/tar-1.26.tar.gz

./configure --prefix=/usr --bindir=/bin --libexecdir=/usr/bin 

Make

Make install

Tar –version

tar (GNU tar) 1.26 升級成功

安裝socket.io  express hiredis redis

/usr/local/bin/npm  install socket.io

/usr/local/bin/npm  install express

/usr/local/bin/npm  install hiredis redis

事件驅動用例:

Publish.js

var redis = require("redis");

 

try{

 

    var client = redis.createClient(6380,'10.54.37.212');

 

    client.on(

        "error",

        function(err){

            console.log("err"+err);

            }

 

    );

    client.on('ready',

        function(){

            client.publish('wangbin_test',"test,i am test");

            client.publish('wangbin_test2',"test, i am test2");

            client.end();

            }

    );

}

catch(e){

        console.log("err:"+e);

}

Subscribe.js

var redis = require("redis");

 

try{

    var client = redis.createClient(6380,'10.54.37.212');

    client.on(

        "error",

        function(err){

            console.log("err"+err);

            }

    );

    client.on('ready',

        function(){

            client.subscribe('wangbin_test');

            client.subscribe('wangbin_test2');

            //client.end();

            }

    );

    client.on('subscribe',

        function(channel,count){

            console.log("channel:" + channel + ", count:"+count);

            }

    );

    client.on('message',

        function(channel,message){

            console.log("channel:" + channel + ", msg:"+message);

            }

    );

    client.on('unsubscribe',

        function(channel,count){

            console.log("channel:" + channel + ", count:"+count);

            }

    );

}

catch(e){

        console.log("err:"+e);

}

測試結果:

Redis <wbr>pub/sub(Publish,Subscribe)

 

另外還支持:pmessage, psubscribe, punsubscribe 事件監聽;

---------------------------------------------------------------------------------------------------------

Node.js  Socket.io redis pub/sub主動推送數據到瀏覽器前端

另外還支持:pmessage, psubscribe, punsubscribe 事件監聽;

 

Server.js

var app = require('http').createServer(handler)

  , io = require('socket.io').listen(app)

  , fs = require('fs');

var redis = require('redis');

var redis_client  = redis.createClient(6380,'10.54.37.212');

app.listen(3000);

function handler (req, res) {

  fs.readFile(__dirname + '/index.html',

  function (err, data) {

    if (err) {

      res.writeHead(500);

      return res.end('Error loading index.html');

    }

 

    res.writeHead(200);

    res.end(data);

  });

}

io.sockets.on('connection', function (socket) {

  socket.emit('news', { hello: 'world' });

      redis_client.subscribe('wangbin_test');

      redis_client.on('message',

        function(channel,message){

             socket.emit('news', message);

             console.log("channel:" + channel + ", msg:"+message);

         }

         );

 

  socket.on('my other event', function (data) {

    console.log(data);

  });

 

});

Index.html

<script src="/socket.io/socket.io.js"></script>

<script>

  var socket = io.connect('http://10.54.37.212');

    socket.on('news', function (data) {

       

        alert(data);

                socket.emit('my other event', { my: 'data' });

                  });

</script>

Redis-cli發送消息:

Publish wangbin_test test

Server.js訂閱監控收到消息後通過socket.io主動pushbrower

瀏覽器收到消息

Redis <wbr>pub/sub(Publish,Subscribe)

 

7、 Redis pub/sub壓力測試

redis-benchmarkredis的讀寫性能工具

生成測試數據源:

for  i  in `seq 10000000` ;do echo  -ne  'publish   wangbin_test "'$i'"\r\n' >> publish.data; done;

 

           發佈:

for i in $(seq 10);do (cat publish.data;sleep 100;)  | nc 10.54.37.212  6380  ;done;

 

訂閱(模擬多個客戶端同時訂閱)

(echo -ne 'subscribe wangbin_test\r\n';sleep 10000)  | nc 10.54.37.212 6380 | grep  "\".*\"" > subscribe_01.txt  &

(echo -ne 'subscribe wangbin_test\r\n';sleep 10000)  | nc 10.54.37.212 6380 | grep  "\".*\"" > subscribe_02.txt  &

(echo -ne 'subscribe wangbin_test\r\n';sleep 10000)  | nc 10.54.37.212 6380 | grep  "\".*\"" > subscribe_03.txt  &

(echo -ne 'subscribe wangbin_test\r\n';sleep 10000)  | nc 10.54.37.212 6380 | grep  "\".*\"" > subscribe_04.txt  &

(echo -ne 'subscribe wangbin_test\r\n';sleep 10000)  | nc 10.54.37.212 6380 | grep  "\".*\"" > subscribe_05.txt  &

(echo -ne 'subscribe wangbin_test\r\n';sleep 10000)  | nc 10.54.37.212 6380 | grep  "\".*\"" > subscribe_06.txt  &
    
 性能監控測試

watch -d -n 1 'wc -l  subscribe_*.txt '

或者:

for i in $(seq 15); do wc -l subscribe_*.txt > result_$i.txt ;sleep 1;  done;

測試結果爲:

每秒返回的數據爲4-5w/s

8、 Redis pub/sub服務應用場景分析

其他PECL 擴展[SAM]Simple Asynchronous Messaging

9、 附件:

       i.             Redis-cli命令信息:

  -h <hostname>    域名或ip

  -p <port>        端口號 (default: 6379)

  -s <socket>      例如:/usr/local/bin/redis-cli  -s  /tmp/redis.sock

  -a <password>   密碼

  -r <repeat>      重複次數

  -i <interval>         重複時間隔時間

  -n <db>         數據庫個數

  -x              最後的標準輸入

  -d <delimiter>    分隔符

  --raw           原始格式回覆

  --latency        採集延遲模式

 

Redis <wbr>pub/sub(Publish,Subscribe)

 

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