PHP實現redis訂閱和發佈(用於異步任務處理)

1.概念
名稱及含義
channel 頻道:生產者和消費者直接操做的對象
publish 生產者:向channel發送消息
subscribe 消費者:訂閱一個或多個channel
psubscribe 消費者:匹配訂閱一個或多個channel
punsubscribe 退訂:匹配退訂,無參數則退訂所有channel
unsubscribe 退訂:退訂指定的channel,無參數則退訂所有channel
pubsub 列出當前活動channel(至少有一個訂閱)php

2.注意事項
1)生產者publish消息時打開一個鏈接,publish後鏈接能夠當即關閉
2)channel只接收publish發送的消息,自身不存儲消息,若是channel沒有被訂閱,則消息丟棄
3)訂閱的消費者須要一直在線,阻塞獲取消息,鏈接斷開表示當即退訂html

3.redis能夠實現發佈訂閱和消息隊列的功能,二者的區別在於:
1)redis的訂閱者能夠是多個,且能夠同時處理髮布上來的消息,若是訂閱者不在線(服務沒有啓動)消息將丟失,消息沒有持久化。發佈和訂閱是一塊執行的,缺乏一個直接忽略這個消息
2)消息隊列只能有一個客戶端來處理,處理完以後消息就被標記或刪除,即便服務端沒有啓動消息也不會丟失
3)二者的使用場景要根據業務數據的準確度,敏感性決定,好比日誌就能夠用redis發佈訂閱來實現,丟失一點也沒有關係redis

4.直接使用php-redis擴展提供的方法實現發佈訂閱
1)消費者訂閱Subscribe.php
<?php
//設置php腳本執行時間
set_time_limit(0);
//設置socket鏈接超時時間
ini_set('default_socket_timeout', -1);
//聲明測試頻道名稱
$channelName = "testPubSub";
$channelName2 = "testPubSub2";
try {
  $redis = new Redis();
  //創建一個長連接
  $redis->pconnect('ip', 6379);
  //阻塞獲取消息
  $redis->subscribe(array($channelName, $channelName2), function ($redis, $chan, $msg) {
    echo "channel:".$chan.",message:".$msg."\n";
  });
} catch (Exception $e) {
  echo $e->getMessage();
}json

2)生產者發送消息Publish.php
<?php
$channelName = "testPubSub";
$channelName2 = "testPubSub2";
//向指定頻道發送消息
try {
  $redis = new Redis();
  $redis->connect('192.168.75.132', 6379);
  for ($i=0;$i<5;$i++) {
    $data = array('key' => 'key'.$i, 'data' => 'testdata');
    $ret = $redis->publish($channelName, json_encode($data));
    print_r($ret);
  }
} catch (Exception $e) {
  echo $e->getMessage();
}socket

3)執行消費者訂閱,開始阻塞獲取消息php Subscribe.php測試

4)執行生產者,開始發送消息php Publish.phpspa

php .\Publish.php
22222
#返回執行結果:頻道的訂閱數量
查看消費者終端日誌

php .\Subscribe.php
channel:testPubSub,message:{"key":"key0","data":"testdata"}
channel:testPubSub,message:{"key":"key1","data":"testdata"}
channel:testPubSub,message:{"key":"key2","data":"testdata"}
channel:testPubSub,message:{"key":"key3","data":"testdata"}
channel:testPubSub,message:{"key":"key4","data":"testdata"}code

轉自:https://www.jmsite.cn/blog-586.htmlhtm

相關文章
相關標籤/搜索