php实现redis消息发布订阅
基础介绍
Pub/Sub功能(means Publish, Subscribe)即发布及订阅功能
- 基于事件的系统中,Pub/Sub是目前广泛使用的通信模型,它采用事件作为基本的通信机制,提供大规模系统所要求的松散耦合的交互模式:订阅者(如客户端)以事件订阅的方式表达出它有兴趣接收的一个事件或一类事件;发布者(如服务器)可将订阅者感兴趣的事件随时通知相关订阅者。
- 消息发布者,即publish客户端,无需独占链接,你可以在publish消息的同时,使用同一个redis-client链接进行其他操作(例如:INCR等)
- 消息订阅者,即subscribe客户端,需要独占链接,即进行subscribe期间,redis-client无法穿插其他操作,此时client以阻塞的方式等待“publish端”的消息;这一点很好理解,因此subscribe端需要使用单独的链接,甚至需要在额外的线程中使用。
当使用银行卡消费的时候,银行往往会通过微信、短信或邮件通知用户这笔交易的信息,这便是一种发布订阅模式,这里的发布是交易信息的发布,订阅则是各个渠道。这在实际工作中十分常用,Redis 支持这样的一个模式。
发布订阅模式首先需要消息源,也就是要有消息发布出来,比如例子中的银行通知。首先是银行的记账系统,收到了交易的命令,成功记账后,它就会把消息发送出来,这个时候,订阅者就可以收到这个消息进行处理了,观察者模式就是这个模式的典型应用了。
终端实现
订阅,频道为'chat'
发布消息
代码实现
subscribe.php
<?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 获取模式匹配方式的订阅
转载至:https://zhuanlan.zhihu.com/p/155667437
php实现redis消息发布订阅的更多相关文章
- springboot2.X 集成redis+消息发布订阅
需求场景:分布式项目中,每个子项目有各自的 user 数据库, 在综合管理系统中存放这所有用户信息, 为了保持综合管理系统用户的完整性, 子系统添加用户后将用户信息以json格式保存至redis,然后 ...
- redis 实现发布订阅的功能
redis 除了作为缓存的功能外还可以用作消息中间件的功能,这片博客主要是介绍一下 redis 整合spring 实现消息的发布和订阅功能: 1:redis依赖,依赖两个包,redis 包, spri ...
- Redis 学习(三) —— 事务、消息发布订阅
一.Redis事务 Redis 提供的事务机制与传统的数据库事务有些不同,传统数据库事务必须维护以下特性:原子性(Atomicity), 一致性(Consistency),隔离性(Isolation) ...
- 【springboot】【redis】springboot+redis实现发布订阅功能,实现redis的消息队列的功能
springboot+redis实现发布订阅功能,实现redis的消息队列的功能 参考:https://www.cnblogs.com/cx987514451/p/9529611.html 思考一个问 ...
- redis实现消息发布/订阅
redis实现简单的消息发布/订阅模式. 消息订阅者: package org.common.component; import org.slf4j.Logger; import org.slf4j. ...
- springboot集成redis实现消息发布订阅模式-双通道(跨多服务器)
基础配置参考https://blog.csdn.net/llll234/article/details/80966952 查看了基础配置那么会遇到一下几个问题: 1.实际应用中可能会订阅多个通道,而一 ...
- 基于Redis消息的订阅发布应用场景
目录 基于Redis消息的订阅发布应用场景 1.应用背景 2.困境 2.1 锁表风险 2.2 实时性差 2.3 增加编程复杂性 2.4 实时效果 3.解决方案 3.1 前端传值给服务端 3.2 服务端 ...
- redis的发布订阅模式
概要 redis的每个server实例都维护着一个保存服务器状态的redisServer结构 struct redisServer { /* Pubsub */ // 字典,键为频道, ...
- StackExchange.Redis 使用-发布订阅 (二)
使用Redis的发布订阅功能 redis另一个常见的用途是发布订阅功能 . 它非常的简单 ,当连接失败时 ConnectionMultiplexer 会自动重新进行订阅 . ISubscriber s ...
随机推荐
- vuex中辅助函数的使用方法
mapState import { mapState } from 'vuex' export default { // ... computed:{ ...mapState({ // 箭头函数可使代 ...
- 让人头疼的AI bug (随想)
虽然概念上,人工智能和机器学习不等同.但是本文提及的AI,指的是基于机器学习的AI. 一个软件产品,出了错误叫bug,bug需要修.那一个机器学习的模型,准确率在那摆着呢,大伙心知肚明是有一定的犯 ...
- 操作系统---在内核中重新加载GDT和堆栈
摘要 用BIOS方式启动计算机后,BIOS先读取引导扇区,引导扇区再从外部存储设备中读取加载器,加载器读取内核.进入内核后,把加载器中建立的GDT复制到内核中. 这篇文章的最大价值也许在末尾,对C语言 ...
- 【Arduino学习笔记08】使用串口监视器显示数据
代码及相关说明: 1 // 示例:读取模拟输入并显示在串口监视器中 2 3 const int ANALOG_IN = 0; 4 int val = 0; 5 6 void setup(){ 7 Se ...
- Java 重入锁和读写锁
本文部分摘自<Java 并发编程的艺术> 重入锁 重入锁 ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁.除此之外,该锁还支持获取锁时 ...
- springboot系列四:springboot整合mybatis jsp
一.用IDEA 创建maven项目 项目目录结构 1.添加pom jar依赖 <?xml version="1.0" encoding="UTF-8"?& ...
- css实现京东顶部导航条
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- 【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
什么是 PaaS?Platform as a Service 平台即服务 (PaaS) 是云中的完整开发和部署环境,你可以使用其中资源交付内容,从基于云的简单应用到启用云的复杂企业应用程序皆可.你以即 ...
- Rust 内置 trait :PartialEq 和 Eq
GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...
- 手把手教你如何使用Charles抓包
一.为什么使用charles 前几天因为需要通过抓包定位问题,打开了尘封已久的fiddler,结果打开软件后什么也干不了,别说手机抓包了,打开软件什么请求也抓不到. 很多时候都是如此,如果一个方案不行 ...