溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

php中怎么利用redis實(shí)現(xiàn)消息發(fā)布訂閱

發(fā)布時(shí)間:2021-06-24 17:44:37 來(lái)源:億速云 閱讀:254 作者:Leah 欄目:大數(shù)據(jù)

本篇文章給大家分享的是有關(guān)php中怎么利用redis實(shí)現(xiàn)消息發(fā)布訂閱,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

基礎(chǔ)介紹

Pub/Sub功能(means Publish, Subscribe)即發(fā)布及訂閱功能

  • 基于事件的系統(tǒng)中,Pub/Sub是目前廣泛使用的通信模型,它采用事件作為基本的通信機(jī)制,提供大規(guī)模系統(tǒng)所要求的松散耦合的交互模式:訂閱者(如客戶端)以事件訂閱的方式表達(dá)出它有興趣接收的一個(gè)事件或一類(lèi)事件;發(fā)布者(如服務(wù)器)可將訂閱者感興趣的事件隨時(shí)通知相關(guān)訂閱者。

  • 消息發(fā)布者,即publish客戶端,無(wú)需獨(dú)占鏈接,你可以在publish消息的同時(shí),使用同一個(gè)redis-client鏈接進(jìn)行其他操作(例如:INCR等)

  • 消息訂閱者,即subscribe客戶端,需要獨(dú)占鏈接,即進(jìn)行subscribe期間,redis-client無(wú)法穿插其他操作,此時(shí)client以阻塞的方式等待“publish端”的消息;這一點(diǎn)很好理解,因此subscribe端需要使用單獨(dú)的鏈接,甚至需要在額外的線程中使用。

當(dāng)使用銀行卡消費(fèi)的時(shí)候,銀行往往會(huì)通過(guò)微信、短信或郵件通知用戶這筆交易的信息,這便是一種發(fā)布訂閱模式,這里的發(fā)布是交易信息的發(fā)布,訂閱則是各個(gè)渠道。這在實(shí)際工作中十分常用,Redis 支持這樣的一個(gè)模式。

發(fā)布訂閱模式首先需要消息源,也就是要有消息發(fā)布出來(lái),比如例子中的銀行通知。首先是銀行的記賬系統(tǒng),收到了交易的命令,成功記賬后,它就會(huì)把消息發(fā)送出來(lái),這個(gè)時(shí)候,訂閱者就可以收到這個(gè)消息進(jìn)行處理了,觀察者模式就是這個(gè)模式的典型應(yīng)用了。

終端實(shí)現(xiàn)

訂閱,頻道為'chat'

php中怎么利用redis實(shí)現(xiàn)消息發(fā)布訂閱


發(fā)布消息

php中怎么利用redis實(shí)現(xiàn)消息發(fā)布訂閱

代碼實(shí)現(xiàn)

subscribe.php

<?phpini_set('default_socket_timeout', -1);  //php配置設(shè)置不超時(shí)$redis = new Redis();$redis->connect("127.0.0.1",6379);//$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);  //redis方式設(shè)置不超時(shí),推薦$redis->subscribe(['chan'],'callback');     //callback為回調(diào)函數(shù)名稱(chēng)//$redis->subscribe(['chan'],array(new TestCall(),'callback') ); //如果回調(diào)函數(shù)是類(lèi)中的方法名,這樣寫(xiě)// 回調(diào)函數(shù),這里寫(xiě)處理邏輯function callback($instance, $channelName, $message){ echo $channelName, "==>", $message, PHP_EOL; 
         //$instance,即為上面創(chuàng)建的redis實(shí)例對(duì)象,在回調(diào)函數(shù)中,默認(rèn)的這個(gè)參數(shù)就是,因此不需專(zhuān)門(mén)傳參。 這里除了SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE這4條命令之外其它命令都不能使用         //如果要使用redis中的其他命令,這樣實(shí)現(xiàn)         $newredis = new Redis();$newredis->connect("127.0.0.1", 6379);echo $newredis->get('test') . PHP_EOL;$newredis->close();
          //可以根據(jù)$channelName, $message,處理不同的業(yè)務(wù)邏輯          switch($chan) {   case 'chan-1':  ...  break; 
               case 'chan-2':  ...   break;   }   
           switch($message) {   case 'msg1':  ...  break; 
               case 'msg2':  ...   break;   }}

publish.php

<?php

$redis = new Redis();
$redis->connect("127.0.0.1",6379);

$redis->publish('chan','this is a message');

代碼介紹

  1. subscribe.php中設(shè)置不超時(shí)

方法1:ini_set('default_socket_timeout', -1);方法2: $redis->setOption(Redis::OPT_READ_TIMEOUT, -1);

如果不設(shè)置不超時(shí),60s后會(huì)報(bào)一個(gè)錯(cuò)誤

PHP Fatal error: Uncaught RedisException: read error on connection to 127.0.0.1:6379 in subscribe.php:6

方式一的實(shí)現(xiàn),是通過(guò)臨時(shí)修改ini的配置值,default_socket_timeout默認(rèn)為60s,default_socket_timeout是socket流的超時(shí)參數(shù),即socket流從建立到傳輸再到關(guān)閉整個(gè)過(guò)程必須要在這個(gè)參數(shù)設(shè)置的時(shí)間以?xún)?nèi)完成,如果不能完成,那么PHP將自動(dòng)結(jié)束這個(gè)socket并返回一個(gè)警告。

php中怎么利用redis實(shí)現(xiàn)消息發(fā)布訂閱

方式二是通過(guò)修改redis的配置項(xiàng),因此僅對(duì)redis連接生效,相對(duì)于方式1,不會(huì)產(chǎn)生意外的對(duì)其他方法的影響。

批量訂閱

redis的psubscribe支持通過(guò)模式匹配的方式實(shí)現(xiàn)批量訂閱,訂閱方式

回調(diào)函數(shù)寫(xiě)函數(shù)名或者redis->psubscribe(['my*'],array(new TestCall(),'psubscribe')); //回調(diào)函數(shù)為類(lèi)中的方法,類(lèi)名寫(xiě)你自己定義的類(lèi)

subscribe.php

<?php//ini_set('default_socket_timeout', -1);  //不超時(shí)$redis = new Redis();$redis->connect("127.0.0.1",6379);$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);//匹配方式1:發(fā)布可用$redis->publish('mymest','this is a message');//$redis->psubscribe(['my*'],'psubscribe');    
//匹配方式2:發(fā)布可用$redis->publish('mydest','this is a message');//$redis->psubscribe(['my?est'],'psubscribe');//匹配方式3:發(fā)布可用$redis->publish('myaest','this is a message');或$redis->publish('myeest','this is a message');$redis->psubscribe(['my[ae]est'],'psubscribe');function psubscribe($redis, $pattern, $chan, $msg) {  echo "Pattern: $pattern\n";  echo "Channel: $chan\n";  echo "Payload: $msg\n";}

模式匹配規(guī)則

支持以下幾種,以hello舉例:

h?llo subscribes to hello, hallo and hxllo
h*llo subscribes to hllo and heeeello
h[ae]llo subscribes to hello and hallo, but not hillo
特殊字符用\轉(zhuǎn)義

pubsub方法介紹

public function pubsub( argument )

pubsub獲取pub/sub系統(tǒng)的信息,$keyword可用為"channels", "numsub", 或者"numpat",三種,傳入不同的keyword返回的數(shù)據(jù)不同

* $redis->pubsub('channels'); // All channels 獲取所有的頻道,返回?cái)?shù)組     * $redis->pubsub('channels', '*pattern*'); // Just channels matching your pattern,返回符合匹配模式的頻道     * $redis->pubsub('numsub', array('chan1', 'chan2')); // Get subscriber counts for 'chan1' and 'chan2'    //返回每個(gè)訂閱頻道的數(shù)量,返回?cái)?shù)組     * $redis->pubsub('numpat'); // Get the number of pattern subscribers 獲取模式匹配方式的訂閱

以上就是php中怎么利用redis實(shí)現(xiàn)消息發(fā)布訂閱,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI