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.

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

  • 相关阅读:
    装饰器实例
    生成器、迭代器脚本实例
    魔法方法和属性
    随机生成验证码
    认证客户端的链接合法性
    将socket通信实现多进程
    线程锁模拟抢票系统
    ntp时间服务器
    蛇形串---------
    两年内计划
  • 原文地址:https://www.cnblogs.com/rstar/p/12844148.html
Copyright © 2011-2022 走看看