php 发布订阅模式,PHP发布订阅sub/pub Demo & 监听Redis订阅模式的通道是否开启

php 监听Redis订阅模式的通道是否开启

今天阅读一篇文章,是讲腾讯开源项目爱好正安正超,以文言文的形式书写,给人极度舒适感,感兴趣的朋友可以查阅:CDC达人:安正超

喜欢里面的一句话,送给调侃php的好事者:

超以 PHP 便宜而用之。是时,有好事者,于网络热议何语最佳。初学者常惑矣,问超当何择。超曰:皆器也,何谓最佳?PHP 宜初创而性能劣,C 则性能优而不易达,何为最佳?能成事者最佳。若以利向,均可获利,若以志向,均可精深。

如果以后还是走技术路线,学习开源和分享即是我的目标。

好了废话不多说,进入正题。

以下是Redis对发布/订阅( pub/sub)模式的介绍:

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

Redis 客户端可以订阅任意数量的频道。

c63ccb018d0aaf38ad685e273909484e.png

举个非常简单的例子:

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

//发布者

$redis = new Redis();

$redis->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 中检测,是否加锁,加锁程序订阅正在监听,无则反

检测

$file = fopen(__DIR__.'lock.txt', 'w+');

if (flock($file, LOCK_EX | LOCK_NB)) {

//订阅失败,直接执行程序,影响程序效率,发短信通知管理员开启订阅

} else {

//检测到订阅开启,放心交给订阅通道

如果对您有所帮助欢迎,欢迎关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值