zoukankan      html  css  js  c++  java
  • Redis发布订阅模式-1

    发布订阅模式

    发布订阅模式可以说是耳熟能详了,它是属于设计模式中的行为模式,最大的好处就是起到解耦的作用,发布者不用关心在消息产生之后需要做什么,发布者只需要在通道里说“我发布了”,不用管有什么业务逻辑需要处理也不用管有多少的逻辑要处理,很简单明了。

    我们平时用来解耦业务的消息队列就是实现了发布订阅模式,所以Redis可以在一些情况下做为消息队列来使用。

    还是贴一张图把(网上盗的),解释下这种模式。

    img


    接下来看看在Redis中怎么实现

    相关常用命令

    PSUBSCRIBE pattern1 pattern2 //订阅一个或者多个符合给定模式的通道  ? ?* 和 * ?标识一个占位符,*标识多个占位符包括0个 ?*标识一个以上的占位符
    PUBLISH channel1 message1   //发布消息到指定的通道
    PUNSUBSCRIBE pattern1 pattern2 //退订一个或者多个符合给定模式的通道,不传pattern 代表退订所有
    SUBSCRIBE channel1 channel2 //订阅一个或者多个通道 
    UNSUBSCRIBE channel1 channel2 //退订一个或者多个通道 不传channel 代表退订所有
    

    命令不复杂,我们来操作一下吧 首先发送一个命令到a_1的通道中,因为现在没有订阅者所以返回了0

    1588153340852

    我们新开一个客户端订阅这个通道,可以看到成功订阅了,返回了当前客户端订阅的通道数量,但是没有收到在订阅之前已经发送的消息,所以Redis的发布订阅的消息是没有持久化的,这是如果实现消息队列需要解决的问题

    1588153502396

    在第一个客户端发送几条消息

    1588158591832

    能看到第二个客户端接收到了消息

    1588169010979


    多说一点

    • Redis实例中的发布和订阅没有作用域的区分的,就算在不同的db间。比如你在db0中发布了一个消息,在db2中你同样能够收到,如果我们要区分不同的环境需要自己对channel命名来区分。
    • 这里需要注意的是,当一个客户端订阅成功一个通道之后,该客户端就不能执行除了订阅相关(SUBSCRIBE,UNSUBSCRIBE,PSUBSCRIBE,PUNSUBSCRIBE)的命令了,也就是相当于阻塞着一直等着消息。
    • 另外一点特别需要注意的是,我最开始的理解psubscribe只是支持模式匹配,最终的效果应该和subscribe是一样,也就是说当我执行psubscribe的时候,Redis实例会根据我写的模式去匹配channel,匹配上就订阅这个channel,比如"pubscribe a_*" 就应该订阅所有"a_"开头的channel,最后订阅的channel都是落到实际的channel上,比如"a_1,a_2"之类的channel。后来我有思考一个问题,当Redis实例中不存在a开头的channel,或者后面才有a开头的channel,我在最开始订阅 "a_"也是能接收到后面创建的channel中发送的信息
    • 其实Redis对于模式的订阅和普通的订阅是分开的,也就是同一个客户端订阅了模式a_,又订阅了a_1,那么你将会收到两条消息,就算你分别执行psubscribe a_1和subscribe a_1,这同样是订阅了两次,你会收到两次消息。
    • 我们可以做下测试,在上面的例子中我们已经通过subscribe a_1 订阅了a_1通道,并成功收到消息,我们再次执行psubscribe a_2 ,并在客户端1发送消息message5,可以看到我们收到两条相同的消息,具体原因会在下一节实现原理中。
    • 可以看见我把上面那句话给划掉了,是因为我在不同客户端测试的时候既然出现了不同的情况,具体原因不太清楚希望有人能解答下。

    不同客户端执行相同命令产生不同的结果?

    1. 首先我用Another RDM的Console来进行订阅,命令会返回当前客户端订阅的通道数量,多次订阅不会重复订阅

      1588170587238

    2. 接着在客户端1中发送消息,命令会返回订阅的客户端数量

      1588170664563

    3. 接着在客户端2中进行模式订阅,可以看到订阅的通道数量变成2了,在客户端1发送消息,数量也变成2,所以我觉得发送信息的命令应该返回的是发送消息的数量

      1588170748596

      1588170814087

    4. 看到这里就已经证明我上面的说的话,但是因为Another没法监听的消息,我用redis-cli测试了一遍,然后就发现同样的命令既然产生不同的效果了。如下图,能看到当我psubscribe的时候没有输出东西,当我在客户端1发送消息的时候也只收到一条,而且客户端1显示消息数量也是3。而不是预想中的4。具体原因我也想不出来了。。希望大神解答。

      1588171030388

    1588171114810

    后来在官网看到了说法

    Messages matching both a pattern and a channel subscription

    A client may receive a single message multiple times if it's subscribed to multiple patterns matching a published message, or if it is subscribed to both patterns and channels matching the message. Like in the following example:

    SUBSCRIBE foo
    PSUBSCRIBE f*
    

    In the above example, if a message is sent to channel foo, the client will receive two messages: one of type messageand one of type pmessage.

    也就是印证了我最开始的想法。

  • 相关阅读:
    Uva 10779 collector's problem
    poj 2728 最优比率树(最小生成树问题)
    LA 3126 二分图匹配 最小路径覆盖
    poj 1149 最大流构图
    Step By Step(Java XML篇)
    Step By Step(Java 输入输出篇)
    Step By Step(Java 集合篇)
    Step By Step(Java 线程篇)
    Step By Step(Java 反射篇)
    Step By Step(Java 国际化篇)
  • 原文地址:https://www.cnblogs.com/rstar/p/12844148.html
Copyright © 2011-2022 走看看