基础介绍
Pub/Sub功能(means Publish, Subscribe)即发布及订阅功能php
- 基于事件的系统中,Pub/Sub是目前普遍使用的通讯模型,它采用事件做为基本的通讯机制,提供大规模系统所要求的松散耦合的交互模式:订阅者(如客户端)以事件订阅的方式表达出它有兴趣接收的一个事件或一类事件;发布者(如服务器)可将订阅者感兴趣的事件随时通知相关订阅者。
- 消息发布者,即publish客户端,无需独占连接,你能够在publish消息的同时,使用同一个redis-client连接进行其余操做(例如:INCR等)
- 消息订阅者,即subscribe客户端,须要独占连接,即进行subscribe期间,redis-client没法穿插其余操做,此时client以阻塞的方式等待“publish端”的消息;这一点很好理解,所以subscribe端须要使用单独的连接,甚至须要在额外的线程中使用。
当使用银行卡消费的时候,银行每每会经过微信、短信或邮件通知用户这笔交易的信息,这即是一种发布订阅模式,这里的发布是交易信息的发布,订阅则是各个渠道。这在实际工做中十分经常使用,Redis 支持这样的一个模式。laravel
发布订阅模式首先须要消息源,也就是要有消息发布出来,好比例子中的银行通知。首先是银行的记帐系统,收到了交易的命令,成功记帐后,它就会把消息发送出来,这个时候,订阅者就能够收到这个消息进行处理了,观察者模式就是这个模式的典型应用了。面试
终端实现
订阅,频道为'chat'redis
发布消息sql
代码实现
subscribe.phpshell
<?php ini_set('default_socket_timeout', -1); //php配置设置不超时 $redis = new Redis(); $redis->connect("127.0.0.1",6379); //$redis->setOption(Redis::OPT_READ_TIMEOUT, -1); //redis方式设置不超时,推荐 $redis->subscribe(['chan'],'callback'); //callback为回调函数名称 //$redis->subscribe(['chan'],array(new TestCall(),'callback') ); //若是回调函数是类中的方法名,这样写 // 回调函数,这里写处理逻辑 function callback($instance, $channelName, $message) { echo $channelName, "==>", $message, PHP_EOL; //$instance,即为上面建立的redis实例对象,在回调函数中,默认的这个参数就是,所以不需专门传参。 这里除了SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE这4条命令以外其它命令都不能使用 //若是要使用redis中的其余命令,这样实现 $newredis = new Redis(); $newredis->connect("127.0.0.1", 6379); echo $newredis->get('test') . PHP_EOL; $newredis->close(); //能够根据$channelName, $message,处理不一样的业务逻辑 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');
代码介绍
- subscribe.php中设置不超时
方法1:ini_set('default_socket_timeout', -1);方法2: $redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
若是不设置不超时,60s后会报一个错误服务器
PHP Fatal error: Uncaught RedisException: read error on connection to 127.0.0.1:6379 in subscribe.php:6
方式一的实现,是经过临时修改ini的配置值,default_socket_timeout默认为60s,default_socket_timeout是socket流的超时参数,即socket流从创建到传输再到关闭整个过程必需要在这个参数设置的时间之内完成,若是不能完成,那么PHP将自动结束这个socket并返回一个警告。微信
方式二是经过修改redis的配置项,所以仅对redis链接生效,相对于方式1,不会产生意外的对其余方法的影响。架构
批量订阅
redis的psubscribe支持经过模式匹配的方式实现批量订阅,订阅方式
回调函数写函数名或者redis->psubscribe(['my*'],array(new TestCall(),'psubscribe')); //回调函数为类中的方法,类名写你本身定义的类
subscribe.php
<?php //ini_set('default_socket_timeout', -1); //不超时 $redis = new Redis(); $redis->connect("127.0.0.1",6379); $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); //匹配方式1:发布可用$redis->publish('mymest','this is a message'); //$redis->psubscribe(['my*'],'psubscribe'); //匹配方式2:发布可用$redis->publish('mydest','this is a message'); //$redis->psubscribe(['my?est'],'psubscribe'); //匹配方式3:发布可用$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"; }
模式匹配规则
支持如下几种,以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
特殊字符用\转义
pubsub方法介绍
public function pubsub( argument )
pubsub获取pub/sub系统的信息,$keyword可用为"channels", "numsub", 或者"numpat",三种,传入不一样的keyword返回的数据不一样
* $redis->pubsub('channels'); // All channels 获取全部的频道,返回数组 * $redis->pubsub('channels', '*pattern*'); // Just channels matching your pattern,返回符合匹配模式的频道 * $redis->pubsub('numsub', array('chan1', 'chan2')); // Get subscriber counts for 'chan1' and 'chan2' //返回每一个订阅频道的数量,返回数组 * $redis->pubsub('numpat'); // Get the number of pattern subscribers 获取模式匹配方式的订阅
以上内容但愿帮助到你们, 不少PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提高,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货须要的能够免费分享给你们 ,须要戳这里 PHP进阶架构师>>>实战视频、大厂面试文档免费获取