文章目录
参考地址:https://blog.csdn.net/w15558056319/article/details/121490953
Redis的发布与订阅功能可以让客户端通过广播方式,将
消息(message)同时发送给可能存在的多个客户端,并且发送消息的客户端不需要知道接收消息的客户端的具体信息。换句话说,发布消息的客户端与接收消息的客户端两者之间没有直接联系。在Redis中,客户端可以通过订阅特定的
频道(channel)来接收发送至该频道的消息,我们把这些订阅频道的客户端称为订阅者(subscriber)。一个频道可以有任意多个订阅者,而一个订阅者也可以同时订阅任意多个频道。除此之外,客户端还可以通过向频道发送消息的方式,将消息发送给频道的所有订阅者,我们把这些发送消息的客户端称为发送者(publisher)。
发布订阅的实现场景
1、实时沟通消息系统
2、微信公众号(点击关注,后台发送一篇博客,订阅的用户就可以监听到)
3、电商中,用户下单成功之后向指定频道发送消息,下游业务订阅支付结果这个频道处理自己相关业务逻辑
4、粉丝关注功能、文章推送
…
还有一些比较复杂的场景,可以使用消息中间件来做,
kafkaRabbitMQActiveMQRocketMQ…等

示例:
有三个客户端订阅了一个 Channel1

当 Channel1 的后台发送了一个数据到 Channel1 的频道中,这三个订阅了 Channel1 的客户端就会同时收到这个数据

redis的List数据类型结构提供了blpop 、brpop命令结合rpush、lpush命令可以实现消息队列机制,基于双端链表实现的发布与订阅功能
🔷双端队列图解如下:

解析: 双端队列模式只能有一个或多个消费者轮着去消费,却不能将消息同时发给其他消费者
🔶发布/订阅模式图解如下:

解析: redis 订阅发布模式,生产者生产完消息通过频道分发消息,给订阅了该频道的所有消费
Redis有两种发布/订阅模式:
- 基于频道(Channel)的发布/订阅
- 基于模式(pattern)的发布/订阅
| 命令 | 描述 |
|---|---|
| subscribe channel [channel … ] | 订阅给定的一个或多个频道 |
| unsubscribe channel [channel … ] | 退订给定的频道,说明:若没有指定channel,则默认退订所有频道 |
| publish channel message | 将消息发送给指定频道 channel ,返回结果:接收到信息的订阅者数量,无订阅者返回0 |
| pubsub channels [argument [atgument …] ] | 查看订阅与发布系统的状态,说明:返回活跃频道列表(即至少有一个订阅者的频道,订阅模式的客户端除外) |
| 命令 | 描述 |
|---|---|
| psubscribe pattern1 [pattern…] | 订阅一个或多个符合给定模式的频道,说明:每个模式以 * 作为匹配符;例如 cn* 匹配所有以cn开头的频道:cn.java、cn.csdn |
| punsubscribe [pattern [pattern …] ] | 退订所有给定模式的频道,说明:pattern 未指定,则订阅的所有模式都会被退订,否则只退订指定的订阅的模式 |
“发布/订阅” 包含2种角色:发布者和订阅者。
发布者可以向指定的频道(channel)发送消息;
订阅者可以订阅一个或者多个频道(channel),所有订阅此频道的订阅者都会收到此消息。

用户可以通过执行
SUBSCRIBE命令,让客户端订阅给定的一个或多个频道。
# 示例:
127.0.0.1:6379> SUBSCRIBE news
Reading messages... (press Ctrl-C to quit)
1) "subscribe" 返回值类型:表示订阅成功!
2) "news" 订阅频道的名称
3) (integer) 1 当前客户端已订阅频道的数量
# 语法解析:
subscribe 订阅命令
news 订阅频道
# 注意:订阅后,该客户端会一直监听消息,如果发送者有消息发给频道,这里会立刻接收到消息
注意:进入订阅状态的客户端,不能使用除了
subscribe、unsubscribe、psubscribe 和 punsubscribe这四个属于"发布/订阅"之外的命令,否则会报错!——这里的客户端指的是
jedis、lettuce的客户端,redis-cli是无法退出订阅状态的!
用户可以通过执行
PUBLISH命令,将一条消息发送至给定频道
# 示例:
127.0.0.1:6379> PUBLISH news "hello world"
(integer) 1 # 接收到信息的订阅者数量,无订阅者返回0
127.0.0.1:6379>
# 语法解析:
publish 命令
news 订阅频道名
hello world 消息内容

用户在使用
SUBSCRIBE命令订阅一个或多个频道之后,如果不想再收到某个频道的消息,那么可以使用UNSUBSCRIBE命令退订指定的频道。
UNSUBSCRIBE命令允许用户给定任意多个频道。如果用户没有给定任何频道,直接以无参数方式执行UNSUBSCRIBE命令,那么命令将退订当前客户端已经订阅的所有频道。
如果有某个/某些模式和该频道匹配,所有订阅这个/这些频道的客户端也同样会收到信息。
图解
下图展示了一个带有频道和模式的例子, 其中 com.ahead.\* 频道匹配了 com.ahead.juc 频道和 com.ahead.thread 频道, 并且有不同的客户端分别订阅它们三个,如下图:
当有信息发送到
com.ahead.thread频道时, 信息除了发送给 client 4 和 client 5 之外, 还会发送给订阅com.ahead.*频道模式的 client x 和 client y

🔷 解析:
反之也是,如果当有消息发送给 com.ahead.juc 频道,消息发送给订阅了 juc 频道的客户端之外,还会发送给订阅了 com.ahead.* 频道的客户端: client x 、client y
🔶 注意:
通配符中 ? 表示1个占位符
* 表示任意个占位符(包括0)
?* 表示1个以上占位符。
用户可以通过执行
PSUBSCRIBE命令,让客户端订阅给定的一个或多个模式。
# 示例:
127.0.0.1:6379> PSUBSCRIBE a? news.* # 订阅 “a?” "com.*" 2种模式频道
Reading messages... (press Ctrl-C to quit) # 进入订阅状态后处于阻塞,可以按Ctrl+C键退出订阅状态
1) "psubscribe" 返回值的类型:显示订阅成功
2) "a?" 订阅的模式
3) (integer) 1 目前已订阅的模式的数量
1) "psubscribe"
2) "news.*"
3) (integer) 2
1) "pmessage" 返回值的类型:信息
2) "a?" 信息匹配的模式:a?
3) "ab" 信息本身的目标频道:aa
4) "hello world" 信息的内容:"hello world"
1) "pmessage"
2) "news.*"
3) "news.dbname"
4) "redis mysql oracle"

# 示例:
# 发布者第一条命令
# 结果:没有接收到消息,匹配失败,不满足 “a?” ,“?”表示一个占位符, a后面的sdf有3个占位符
127.0.0.1:6379> PUBLISH asdf "hello world"
(integer) 0
# 发布者第二条命令,匹配到一个订阅
127.0.0.1:6379> PUBLISH ab "hello world"
(integer) 1
# 发布者第二条命令,news.dbname 满足 new.* 匹配规则
127.0.0.1:6379> PUBLISH news.dbname "redis mysql oracle"
(integer) 1
127.0.0.1:6379>

与退订频道的
UNSUBSCRIBE命令类似,Redis 也提供了用于退订模式的PUNSUBSCRIBE命令
PUNSUBSCRIBE [pattern [pattern ...]]
# 示例:
PUNSUBSCRIBE news.*
与
UNSUBSCRIBE命令一样,各个客户端对于PUNSUBSCRIBE命令的需求也是不同的,有些客户端需要用到PUNSUBSCRIBE命令,而有些客户端则不需要。例如:
Redis自带的命令行客户端
redis-cli在执行PSUBSCRIBE命令之后就会进入阻塞状态,只能通过同时按下Ctrl键和C键来退出程序,因此它并不需要用到PUNSUBSCRIBE命令。
用户可以通过执行
PUBSUB CHANNELS命令来列出目前被订阅的所有频道,如果给定了可选的pattern参数,那么命令只会列出与给定模式相匹配的频道。
PUBSUB CHANNELS [pattern]
# 示例:
127.0.0.1:6379> PUBSUB CHANNELS
127.0.0.1:6379> PUBSUB CHANNELS news.*
用户可以通过执行
PUBSUB NUMSUB命令,查看任意多个给定频道的订阅者数量
PUBSUB NUMSUB [channel [channel ...]]
# 示例:
PUBSUB NUMSUB news.dbname
1) "news.dbname"
2) (integer) 2 频道订阅数量
通过执行
PUBSUB NUMPAT命令,用户可以看到目前被订阅模式的总数量
# 示例:
127.0.0.1:6379> PUBSUB NUMPAT
(integer) 2
客户端需要及时消费和处理消息。
客户端订阅了
channel之后,如果接收消息不及时,可能导致DCS实例消息堆积,当达到消息堆积阈值(默认值为32MB),或者达到某种程度(默认8MB)一段时间(默认为1分钟)后,服务器端会自动断开该客户端连接,避免导致内部内存耗尽。
客户端需要支持重连。
当连接断开之后,客户端需要使用
subscribe或者psubscribe重新进行订阅,否则无法继续接收消息。
不建议用于消息可靠性要求高的场景中。
Redis的
pubsub不是一种可靠的消息系统。当出现客户端连接退出,或者极端情况下服务端发生主备切换时,未消费的消息会被丢弃。
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:
尝试从我的AngularJS端将数据发布到Rails服务器时出现问题。服务器错误:ActionController::RoutingError(Noroutematches[OPTIONS]"/users"):actionpack(4.1.9)lib/action_dispatch/middleware/debug_exceptions.rb:21:in`call'actionpack(4.1.9)lib/action_dispatch/middleware/show_exceptions.rb:30:in`call'railties(4.1.9)lib/rails/rack/logg
当音乐碰上区块链技术,会擦出怎样的火花?或许周杰伦已经给了我们答案。8月29日下午,B站独家首发周杰伦限定珍藏Demo独家访谈VCR,周杰伦在VCR里分享了《晴天》《青花瓷》《搁浅》《爱在西元前》四首经典歌曲Demo背后的创作故事,并首次公布18年前未发布的神秘作品《纽约地铁》的Demo。在VCR中,方文山和杰威尔音乐提及到“多亏了区块链技术,现在我们可以将这些Demos,变成独一无二具有收藏价值的艺术品,这些Demos可以在薄盒(国内数藏平台)上听到。”如何将音乐与区块链技术相结合,薄盒方面称:“薄盒作为区块链技术服务方,打破传统对于区块链技术只能作为数字收藏的理解。聚焦于区块链技术赋能,在
我想上传我在运行时用Ruby生成的数据,就像从block中提供上传数据一样。我找到的所有示例仅展示了如何流式传输必须在请求之前位于磁盘上的文件,但我不想缓冲该文件。除了滚动我自己的套接字连接之外,最好的解决方案是什么?这是一个伪代码示例:post_stream('127.0.0.1','/stream/')do|body|generate_xmldo|segment|body 最佳答案 有效的代码。require'thread'require'net/http'require'base64'require'openssl'class
昨晚看到IDEA官推宣布IntelliJIDEA2023.1正式发布了。简单看了一下,发现这次的新版本包含了许多改进,进一步优化了用户体验,提高了便捷性。至于是否升级最新版本完全是个人意愿,如果觉得新版本没有让自己感兴趣的改进,完全就不用升级,影响不大。软件的版本迭代非常正常,正确看待即可,不持续改进就会慢慢被淘汰!根据官方介绍:IntelliJIDEA2023.1针对新的用户界面进行了大量重构,这些改进都是基于收到的宝贵反馈而实现的。官方还实施了性能增强措施,使得Maven导入更快,并且在打开项目时IDE功能更早地可用。由于后台提交检查,新版本提供了简化的提交流程。IntelliJIDEA
Unity数据可视化图表插件XCharts3.0发布历时8个多月,业余时间,断断续续,XCharts3.0总算发布了。如果要打个满意度,我给3.0版本来个80分。对于代码框架结构设计的调整改动,基本符合预期,甚是满意。相比之前的1.0和2.0版本,我认为3.0才是一个拿得出手给广大开发者使用的版本。1.0发布的时候,很兴奋,从0.1到1.0,也磨了一年,真的等不及想给大家试用了,还特地写过一篇文章以示庆祝。那个时候,1.0虽然还还不够完善,功能也不够丰富,但它是XCharts的开始,没有1.0,也就没有后面的2.0和3.0。后面的2.0发布,做了很多改进和优化,随着版本迭代,慢慢的发现有不少硬
将stripe的API与RubyonRails结合使用我无法保存订阅。我能够检索、更新和保存客户对象:customer=Stripe::Customer.retrieve(some_customer_id)#thisworkscustomer.save#thisworks我还可以检索订阅:subscription=customer.subscriptions.retrieve("some_subscription_id")#这个有效但是,在尝试保存订阅时:subscription.save#这不起作用我不断得到这个:NoMethodError:undefinedmethod`save'
我有一个模型依赖于一个单独的、联合的模型。classMagazine图像是多态的,可以附加到许多对象(页面和文章),而不仅仅是杂志。杂志需要在相关图像发生任何变化时自行更新该杂志还保存了一张自己的截图,可用于宣传:classMagazine现在如果图像发生变化,杂志也需要更新其截图。所以杂志真的需要知道图片什么时候出了问题。所以我们可以天真地直接从封面图片触发屏幕截图更新classImage...但是图片不应该代表杂志做事然而,图片可以用于许多不同的对象,实际上不应该对杂志进行特定的操作,因为这不是图片的责任。该图像也可能附加到页面或文章,并且不需要为它们做各种事情。“正常”的rail
我在使用ActionCable时遇到问题,每当我运行我的程序时,我都会收到一条错误消息,提示SubscriptionClassnotfoundConversationChannel当我尝试发送消息时,我得到了这个日志SuccessfullyupgradedtoWebSocket(REQUEST_METHOD:GET,HTTP_CONNECTION:Upgrade,HTTP_UPGRADE:websocket)Subscriptionclassnotfound:"ConversationChannel"Couldnotexecutecommandfrom{"command"=>"mess