PHP发布订阅sub/pub介绍|PHP发布订阅sub/pub介绍 & 监听Redis订阅模式的通道是否开启
php 监听Redis订阅模式的通道是否开启
今天阅读一篇文章,是讲腾讯开源项目爱好正安正超,以文言文的形式书写,给人极度舒适感,感兴趣的朋友可以查阅:CDC达人:安正超
喜欢里面的一句话,送给调侃php的好事者:
超以 PHP 便宜而用之。是时,有好事者,于网络热议何语最佳。初学者常惑矣,问超当何择。超曰:皆器也,何谓最佳?PHP 宜初创而性能劣,C 则性能优而不易达,何为最佳?能成事者最佳。若以利向,均可获利,若以志向,均可精深。如果以后还是走技术路线,开源和分享即是我的目标。
好了废话不多说,进入正题。 以下是Redis对发布/订阅( pub/sub)模式的介绍:
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。举个非常简单的例子:
Redis 客户端可以订阅任意数量的频道。
文章图片
image
subscribe.php
//监听者
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
echo 'reading c1 ...\n';
//设置超时控制
$redis->setOption(Redis::OPT_READ_TIMEOUT,-1);
$redis->subscribe(['c1','c2'],function(Redis $instance, $channel, $message){
echo 'recieve message from '.$channel.':'.$message.'\n';
});
publish.php
connect('127.0.0.1',6379);
$res = $redis->publish('c1','发布消息');
echo 'clents'.$res;
php subscribe.php 进程停留在当前命令框php 执行另外一个publish.php 文件,则可查收到 ‘发布消息’的内容。
这样就实现了php 异步的处理。
什么场景下运用redis的发布、订阅功能? 关于订阅功能,可以在发送短信,邮件,和通知消息给第三方平台
比如传统的下单模式:
用户下单>创建订单->创建订单的详情->订单日志->短信通知(微信通知)
在消息通知中,如果网络延迟,或者第三方网络问题,导致下单超时,或者下单失败,这样用户的体验感就差了。
如果加入发布,订阅功能,即可解决这一不好的用户体验
创建订单时,发布一条消息给redis订阅的一个通道,让其异步执行,如果对发布、订阅有深厚的理解之后,掌握了异常处理,回滚机制之后甚至可以把订单详情,和订单日志加入订阅中。
虽说redis 的订阅功能如此之强大,但是redis 也不是专业做发布订阅的软件,在键值缓存中,redis 占很大的优势,因为redis自带没有像rabibitMQ对发布订阅应用场景这么广。
RabbitMQ和Redis的对比。
RabbitMQ和Redis都可以做队列,但是他们还是有区别的。比如,Redis的消息队列,如果在从队列pop出去的时候,worker处理失败的话,数据不会回到队列中,需要从业务中手动把失败的处理数据push到队列中;而RabbitMQ可以自动处理失败的worker使数据不丢失;RabbitMQ还可以保证数据在传输过程中持久化,在通道和队列中的数据可以设置为持久化。首先Redis严格来说并不是消息队列,它是一个内存数据库,不过因为其某些特性适合用来充当队列,所以也多被用于做简单的mq, Redis之父倒是开发了个真正的消息队列disque,有兴趣可以看看。
相比起Redis,RabbitMQ有更加完善的MQ机制,这里我们仅讨论消息的durable(持久性),后续一系列其他机制有时间再交流。
RabbitMQ有一个消息确认机制来保证消息的不丢失:客户端从队列中取出消息之后,可能需要一段时间才能处理完成,如果在这个过程中,客户端出错了,异常退出了,而数据还没有处理完成,那么非常不幸,这段数据就丢失了,因为RabbitMQ默认会把此消息标记为已完成,然后从队列中移除,消息确认是客户端从RabbitMQ中取出消息,并处理完成之后,会发送一个ack告诉RabbitMQ,消息处理完成,当RabbitMQ收到客户端的获取消息请求之后,或标记为处理中,当再次收到ack之后,才会标记为已完成,然后从队列中删除。当RabbitMQ检测到客户端和自己断开链接之后,还没收到ack,则会重新将消息放回消息队列,交给下一个客户端处理,保证消息不丢失,也就是说,RabbitMQ给了客户端足够长的时间来做数据处理。如何监听redis订阅管道是否开启 有时候,可能会有很多原因,使订阅的通道停止了,但是程序还是一直publish 到订阅中,如果做了异常处理还好,但是我想即使订阅关掉了,我还执行程序,但是就会卡一点,检测到订阅关闭之后可以发送邮箱给管理人员,进行处理。
之前我查阅文档,好像没有这回事,如果有可以相告,所以我就想到以文件锁的形式来判断,订阅通道是否开启,因为订阅是长时间停驻在进程中。
在subscribe中添加:
加锁
$file = fopen(__DIR__.'lock.txt','w+');
flock($file,LOCK_EX|LOCK_NB);
publish 中检测,是否加锁,加锁程序订阅正在监听,无则反
检测 在publish.php 中添加
$file = fopen(__DIR__.'lock.txt', 'w+');
if (flock($file, LOCK_EX | LOCK_NB)) {
//订阅失败,直接执行程序,影响程序效率,发短信通知管理员开启订阅} else {
//检测到订阅开启,放心交给订阅通道
}
【PHP发布订阅sub/pub介绍|PHP发布订阅sub/pub介绍 & 监听Redis订阅模式的通道是否开启】如果对您有所帮助欢迎,欢迎关注!
推荐阅读
- thinkphp|thinkphp 3.2 如何调用第三方类库
- CGI,FastCGI,PHP-CGI与PHP-FPM
- 图文小编《杨浦、成毅》为你发布!无价之宝随意摆放的公园
- 用npm发布一个包的教程并编写一个vue的插件发布
- 【译】Rails|【译】Rails 5.0正式发布(Action Cable,API模式等)
- 运用flutter|运用flutter 构建一个发布版(release)APK
- PHP开发-Mac搭建ThinkPHP5.0
- Vue组件之事件总线和消息发布订阅详解
- K8S|K8S 生态周报| Istio 即将发布重大安全更新,多个版本受影响
- Redis——发布订阅/消息队列