Redis中的发布订阅模式

列表的局限

前面我们说通过队列的rpush 和lpop 可以实现消息队列(队尾进队头出),但是消费者需要不停地调用lpop 查看List 中是否有等待处理的消息(比如写一个while 循环)。为了减少通信的消耗,可以sleep()一段时间再消费,但是会有两个问题:

1、如果生产者生产消息的速度远大于消费者消费消息的速度,List 会占用大量的内存。

2、消息的实时性降低。

list 还提供了一个阻塞的命令:blpop,没有任何元素可以弹出的时候,连接会被阻塞。

blpop queue 5

基于list 实现的消息队列,不支持一对多的消息分发。

发布订阅模式

除了通过list 实现消息队列之外,Redis 还提供了一组命令实现发布/订阅模式。

这种方式,发送者和接收者没有直接关联(实现了解耦),接收者也不需要持续尝试获取消息。

 

订阅频道

首先,我们有很多的频道(channel),我们也可以把这个频道理解成queue。订阅者可以订阅一个或者多个频道。消息的发布者(生产者)可以给指定的频道发布消息。

只要有消息到达了频道,所有订阅了这个频道的订阅者都会收到这条消息。

需要注意的注意是,发出去的消息不会被持久化,因为它已经从队列里面移除了,所以消费者只能收到它开始订阅这个频道之后发布的消息。

下面我们来看一下发布订阅命令的使用方法。

订阅者订阅频道:可以一次订阅多个,比如这个客户端订阅了3 个频道。

subscribe channel-1 channel-2 channel-3

发布者可以向指定频道发布消息(并不支持一次向多个频道发送消息):

publish channel-1 2673

取消订阅(不能在订阅状态下使用):

unsubscribe channel-1

按规则(Pattern)订阅频道

支持?和*占位符。?代表一个字符,*代表0 个或者多个字符。

消费端1,关注运动信息:

psubscribe *sport

消费端2,关注所有新闻:

psubscribe news*

消费端3,关注天气新闻:

psubscribe news-weather

生产者,发布3 条信息

publish news-sport yaoming
publish news-music jaychou
publish news-weather rain
public class MyListener extends JedisPubSub {
    // 取得订阅的消息后的处理
    public void onMessage(String channel, String message) {
        System.out.println(channel + "=" + message);
    }

    // 初始化订阅时候的处理
    public void onSubscribe(String channel, int subscribedChannels) {
        // System.out.println(channel + "=" + subscribedChannels);
    }

    // 取消订阅时候的处理
    public void onUnsubscribe(String channel, int subscribedChannels) {
        // System.out.println(channel + "=" + subscribedChannels);
    }

    // 初始化按表达式的方式订阅时候的处理
    public void onPSubscribe(String pattern, int subscribedChannels) {
        // System.out.println(pattern + "=" + subscribedChannels);
    }

    // 取消按表达式的方式订阅时候的处理
    public void onPUnsubscribe(String pattern, int subscribedChannels) {
        // System.out.println(pattern + "=" + subscribedChannels);
    }

    // 取得按表达式的方式订阅的消息后的处理
    public void onPMessage(String pattern, String channel, String message) {
        System.out.println(pattern + "=" + channel + "=" + message);
    }
}
public class ListenTest {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        final MyListener listener = new MyListener();
        // 使用模式匹配的方式设置频道
        // 会阻塞
        jedis.psubscribe(listener, new String[]{"qingshan-*"});
    }
}
public class PublishTest {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.publish("qingshan-123", "666");
        jedis.publish("qingshan-abc", "pengyuyan");
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值