1. 程式人生 > >php redis pub/sub(Publish/Subscribe,釋出/訂閱的資訊系統)之基本使用

php redis pub/sub(Publish/Subscribe,釋出/訂閱的資訊系統)之基本使用

一.場景介紹

最近的一個專案需要用到釋出/訂閱的資訊系統,以做到最新實時訊息的通知。經查詢後發現了redis pub/sub(釋出/訂閱的資訊系統)可以滿足我的開發需求,而且學習成本和使用成本也比較低。

二.什麼是redis pub/sub

資料檢視

大家在看我的blog的同時可以開啟redis官方對於redis pub/sub的介紹,感覺看英文文件吃力的話 :cry: ,可以看redis中文網的翻譯介紹.

Pub/Sub功能(means Publish, Subscribe)即釋出及訂閱功能

  1. 基於事件的系統中,Pub/Sub是目前廣泛使用的通訊模型,它採用事件作為基本的通訊機制,提供大規模系統所要求的鬆散耦合的互動模式:訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的一個事件或一類事件;釋出者(如伺服器)可將訂閱者感興趣的事件隨時通知相關訂閱者。
  2. 訊息釋出者,即publish客戶端,無需獨佔連結,你可以在publish訊息的同時,使用同一個redis-client連結進行其他操作(例如:INCR等)
  3. 訊息訂閱者,即subscribe客戶端,需要獨佔連結,即進行subscribe期間,redis-client無法穿插其他操作,此時client以阻塞的方式等待“publish端”的訊息;這一點很好理解,因此subscribe端需要使用單獨的連結,甚至需要在額外的執行緒中使用。

三.redis pub sub(publish subscribe)之基本使用

下面我將配著實圖(用我的本地機器環境)來為大家講解redis的pub/sub怎麼去使用 .

沒有安裝phpredis擴充套件的或者沒有redis服務的,請參考我的 另一篇blog ,有詳細的安裝介紹,這裡不再贅述了。

1、啟動redis服務端

2、啟動redis客戶端,並做為subscribe訂閱端

新開一個終端,啟動redis客戶端,並做為subscribe客戶端(訊息訂閱者),訂閱一個名字叫test的頻道資訊:

3、啟動redis客戶端,並做為publish客戶端

釋出一個名字叫test的頻道,資訊是:hello,world

4、檢視訂閱到的訊息

再切換到2步驟中的redis客戶端視窗,會發現,已經訂閱到了剛才釋出的 'hello,world'訊息:

其中,test為頻道名稱,hello,world即為訊息

5、模式匹配訂閱

Redis 的Pub/Sub實現支援模式匹配。

客戶端可以訂閱全風格的模式以便接收所有來自能匹配到給定模式的頻道的訊息。 比如,將接收所有發到 test.name,test.phone,test.address...等等的訊息,該這樣寫:

PUBSCRIBE test.*

在終端回車後,同時再新的窗口裡分別釋出兩個頻道的訊息,名字分別為:test.name和test.phone,然後切換到訂閱端的窗口裡,結果如下圖所示:

由上圖可以看出,在訂閱了test.*頻道後,一共收到了 test.name和test.phone兩個頻道的訊息,這就是模式匹配訂閱。

那麼取消訂閱匹配該模式的客戶端也比較簡單:

PUNSUBSCRIBE test.*

好,以上的這些簡單的demo,就是關於redis pub/sub(Publish/Subscribe,釋出/訂閱的資訊系統)的最基本使用。說了這麼多,跟php也沒有掛上什麼鉤,彆著急,重要的都往往最後出場。

四.php redis pub/sub

phpredis的安裝

redis的客戶端連線支援多種語言。這裡我用的是php的phpredis,它是用c語言編寫的,目前已經作為php的一個模組擴充套件,沒有安裝的可以參考我的 另一篇blog ,已經安裝的可以忽略此步驟.

命令手冊

詳細請看github 這裡 。 這裡我列出一些常用的:

Redis::__construct建構函式
$redis = new Redis();
connect, open 連結redis服務
引數
host: string,服務地址
port: int,埠號
timeout: float,連結時長 (可選, 預設為 0 ,不限連結時間)
注: 在redis.conf中也有時間,預設為300

pconnect, popen 不會主動關閉的連結
參考上面

setOption 設定redis模式

getOption 檢視redis設定的模式

ping 檢視連線狀態

get 得到某個key的值(string值)
如果該key不存在,return false

set 寫入key 和 value(string值)
如果寫入成功,return ture

setex 帶生存時間的寫入值
$redis->setex('key', 3600, 'value'); // sets key → value, with 1h TTL.
setnx 判斷是否重複的,寫入值
$redis->setnx('key', 'value');
$redis->setnx('key', 'value');

delete 刪除指定key的值
返回已經刪除key的個數(長整數)
$redis->delete('key1', 'key2');
$redis->delete(array('key3', 'key4', 'key5'));

更詳細的使用請參考這裡 ,我就不寫太多,因為我要直接摞程式碼了.

publish(訊息釋出端):pub.php

/**
 * redis sub(訊息訂閱端)
 * @ blog: phping.sinaapp.com
 * @date 2016-04-24 15:00
 */
$redis = new Redis();
// 第一個引數為redis伺服器的ip,第二個為埠
$res = $redis->connect('127.0.0.1', 6379);
// test為釋出的頻道名稱,hello,world為釋出的訊息
$res = $redis->publish('test','hello,world');

subscribe(訊息訂閱端): sub.php

/**
 * redis sub(訊息訂閱端)
 * @ blog: phping.sinaapp.com
 * @date 2016-04-24 15:00
 */

$redis = new Redis();
$res = $redis->pconnect('127.0.0.1', 6379,0);
$redis->subscribe(array('test'), 'callback');

// 回撥函式,這裡寫處理邏輯
function callback($instance, $channelName, $message) {
 echo $channelName, "==>", $message,PHP_EOL;
}

開始訂閱redis訊息

前面已經提到過,訊息訂閱者,即subscribe客戶端,需要獨佔連結,即進行subscribe期間,redis-client無法穿插其他操作,此時client以阻塞的方式等待“publish端”的訊息,所以我們用命令列來執行:

php啟動redis訂閱端

則 訂閱訊息的redis客戶端已經啟動,隨時等待發布過來的訊息並訂閱該訊息. 釋出redis訊息 同樣,命令列執行訊息釋出端的指令碼即可:

php pub.php

切換到訊息訂閱端的視窗

發現終端有輸出,如下圖

哈哈,是不是 收到了釋出端釋出的'hello,world'這條訊息呢。