发布订阅简介

除了使用List实现简单的消息队列功能以外,Redis还提供了发布订阅的消息机制。在这种机制下,消息发布者向指定频道(channel)发布消息,消息订阅者可以收到指定频道的消息,同一个频道可以有多个消息订阅者,如下图:

Redis也提供了一些命令支持这个机制,接下来我们详细介绍一下这些命令。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

发布订阅相关命令

在Redis中,发布订阅相关命令有:

  1. 发布消息
  2. 订阅频道
  3. 取消订阅
  4. 按照模式订阅
  5. 按照模式取消订阅
  6. 查询订阅信息

发布消息

发布消息的命令是publish,语法是:

publish 频道名称 消息

比如,要向channel:one-more-study:demo频道发布一条消息“I am One More Study.”,命令如下:

> publish channel:one-more-study:demo "I am One More Study."
(integer) 0

返回的结果是订阅者的个数,上例中没有订阅者,所以返回结果为0。

订阅消息

订阅消息的命令是subscribe,订阅者可以订阅一个或者多个频道,语法是:

subscribe 频道名称 [频道名称 ...]

比如,订阅一个channel:one-more-study:demo频道,命令如下:

> subscribe channel:one-more-study:demo
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel:one-more-study:demo"
3) (integer) 1

返回结果中有3条,分别表示:返回值的类型(订阅成功)、订阅的频道名称、目前已订阅的频道数量。当订阅者接受到消息时,就会显示:

1) "message"
2) "channel:one-more-study:demo"
3) "I am One More Study."

同样也是3条结果,分别表示:返回值的类型(信息)、消息来源的频道名称、消息内容。

新开启的订阅者,是无法收到该频道之前的历史消息的,因为Redis没有对发布的消息做持久化。

取消订阅

取消订阅的命令是unsubscribe,可以取消一个或者多个频道的订阅,语法是:

unsubscribe [频道名称 [频道名称 ...]]

比如,取消订阅channel:one-more-study:demo频道,命令如下:

> unsubscribe channel:one-more-study:demo
1) "unsubscribe"
2) "channel:one-more-study:demo"
3) (integer) 0

返回结果中有3条,分别表示:返回值的类型(取消订阅成功)、取消订阅的频道名称、目前已订阅的频道数量。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

按模式订阅消息

按模式订阅消息的命令是psubscribe,订阅一个或多个符合给定模式的频道,语法是:

psubscribe 模式 [模式 ...]

每个模式以 * 作为匹配符,比如 channel* 匹配所有以 channel 开头的频道,命令如下:

> psubscribe channel:*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel*"
3) (integer) 1

返回结果中有3条,分别表示:返回值的类型(按模式订阅成功)、订阅的模式、目前已订阅的模式数量。当订阅者接受到消息时,就会显示:

1) "pmessage"
2) "channel*"
3) "channel:one-more-study:demo"
4) "I am One More Study."

返回结果中有4条,分别表示:返回值的类型(信息)、消息匹配的模式、消息来源的频道名称、消息内容。

按模式取消订阅

按模式取消订阅的命令是punsubscribe,可以取消一个或者多个模式的订阅,语法是:

punsubscribe [模式 [模式 ...]]

每个模式以 * 作为匹配符,比如 channel:* 匹配所有以 channel 开头的频道,命令如下:

1> punsubscribe channel:*
1) "punsubscribe"
2) "channel:*"
3) (integer) 0

返回结果中有3条,分别表示:返回值的类型(按模式取消订阅成功)、取消订阅的模式、目前已订阅的模式数量。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

查询订阅信息

查看活跃频道

活跃频道指的是至少有一个订阅者的频道,语法是:

pubsub channels [模式]

比如:

> pubsub channels
1) "channel:one-more-study:test"
2) "channel:one-more-study:demo"
3) "channel:demo"
> pubsub channels *demo
1) "channel:one-more-study:demo"
2) "channel:demo"
> pubsub channels *one-more-study*
1) "channel:one-more-study:test"
2) "channel:one-more-study:demo"
查看频道订阅数
pubsub numsub [频道名称 ...]

比如:

> pubsub numsub channel:one-more-study:demo
1) "channel:one-more-study:demo"
2) (integer) 1
查看模式订阅数
> pubsub numpat
(integer) 1

代码实战

光说不练假把式,我们使用Java语言写一个简单的发布订阅示例。

Jedis集群示例

Jedis是Redis官方推荐的Java连接开发工具,我们使用Jedis写一个简单的集群示例。

package onemore.study;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig; import java.util.HashSet;
import java.util.Set; /**
* Jedis集群
*
* @author 万猫学社
*/
public enum Cluster {
INSTANCE; //为了简单,把IP和端口直接写在这里,实际开发中写在配置文件会更好。
private final String hostAndPorts = "192.168.0.60:6379;192.168.0.61:6379;192.168.0.62:6379";
private JedisCluster jedisCluster; Cluster() {
JedisPoolConfig poolConfig = new JedisPoolConfig(); //最大连接数
poolConfig.setMaxTotal(20);
//最大空闲数
poolConfig.setMaxIdle(10);
//最小空闲数
poolConfig.setMinIdle(2); //从jedis连接池获取连接时,校验并返回可用的连接
poolConfig.setTestOnBorrow(true);
//把连接放回jedis连接池时,校验并返回可用的连接
poolConfig.setTestOnReturn(true); Set<HostAndPort> nodes = new HashSet<>();
String[] hosts = hostAndPorts.split(";");
for (String hostport : hosts) {
String[] ipport = hostport.split(":");
String ip = ipport[0];
int port = Integer.parseInt(ipport[1]);
nodes.add(new HostAndPort(ip, port));
}
jedisCluster = new JedisCluster(nodes, 1000, poolConfig);
} public JedisCluster getJedisCluster() {
return jedisCluster;
}
}

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

发布者示例

package onemore.study;

import redis.clients.jedis.JedisCluster;

/**
* 发布者
*
* @author 万猫学社
*/
public class Publisher implements Runnable {
private final String CHANNEL_NAME = "channel:one-more-study:demo";
private final String QUIT_COMMAND = "quit"; @Override
public void run() {
JedisCluster jedisCluster = Cluster.INSTANCE.getJedisCluster();
for (int i = 1; i <= 3; i++) {
String message = "第" + i + "消息";
System.out.println(Thread.currentThread().getName() + " 发布:" + message);
jedisCluster.publish(CHANNEL_NAME, message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("------------------");
}
jedisCluster.publish(CHANNEL_NAME, QUIT_COMMAND);
}
}

订阅者示例

package onemore.study;

import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPubSub; /**
* 订阅者
*
* @author 万猫学社
*/
public class Subscriber implements Runnable {
private final String CHANNEL_NAME = "channel:one-more-study:demo";
private final String QUIT_COMMAND = "quit"; private final JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println(Thread.currentThread().getName() + " 接收:" + message);
if (QUIT_COMMAND.equals(message)) {
unsubscribe(CHANNEL_NAME);
}
}
}; @Override
public void run() {
JedisCluster jedisCluster = Cluster.INSTANCE.getJedisCluster();
jedisCluster.subscribe(jedisPubSub, CHANNEL_NAME);
}
}

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

综合示例

package onemore.study;

public class App {
public static void main(String[] args) throws InterruptedException {
//创建3个订阅者
new Thread(new Subscriber()).start();
new Thread(new Subscriber()).start();
new Thread(new Subscriber()).start();
Thread.sleep(1000); //创建发布者
new Thread(new Publisher()).start();
}
}

运行结果如下:

Thread-6 发布:第1消息
Thread-0 接收:第1消息
Thread-1 接收:第1消息
Thread-2 接收:第1消息
------------------
Thread-6 发布:第2消息
Thread-0 接收:第2消息
Thread-1 接收:第2消息
Thread-2 接收:第2消息
------------------
Thread-6 发布:第3消息
Thread-0 接收:第3消息
Thread-2 接收:第3消息
Thread-1 接收:第3消息
------------------
Thread-0 接收:quit
Thread-1 接收:quit
Thread-2 接收:quit

微信公众号:万猫学社

微信扫描二维码

获得更多Java技术干货

最通俗易懂的Redis发布订阅及代码实战的更多相关文章

  1. redis发布订阅Java代码实现

    Redis除了可以用作缓存数据外,另一个重要用途是它实现了发布订阅(pub/sub)消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. 为了实现redis的发布订阅机制,首先要打开re ...

  2. 我在生产项目里是如何使用Redis发布订阅的?(二)Java版代码实现(含源码)

    上篇文章讲了在实际项目里的哪些业务场景用到Redis发布订阅,这篇文章就讲一下,在Java中如何实现的. 图解代码结构 发布订阅的理论以及使用场景大家都已经有了大致了解了,但是怎么用代码实现发布订阅呢 ...

  3. RedisRepository封装—Redis发布订阅以及StackExchange.Redis中的使用

    本文版权归博客园和作者本人吴双共同所有,转载请注明本Redis系列分享地址.http://www.cnblogs.com/tdws/tag/NoSql/ Redis Pub/Sub模式 基本介绍 Re ...

  4. Redis发布订阅机制

    1. 什么是Redis Redis是一个开源的内存数据库,它以键值对的形式存储数据.由于数据存储在内存中,因此Redis的速度很快,但是每次重启Redis服务时,其中的数据也会丢失,因此,Redis也 ...

  5. Linux(6)- redis发布订阅/持久化/主从复制/redis-sentinel/redis-cluster、nginx入门

    一.redis发布订阅 Redis 通过 PUBLISH .SUBSCRIBE 等命令实现了订阅与发布模式. 其实从Pub/Sub的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个 ...

  6. 使用EventBus + Redis发布订阅模式提升业务执行性能

    前言 最近一直奔波于面试,面了几家公司的研发.有让我受益颇多的面试经验,也有让我感觉浪费时间的面试经历~因为疫情原因,最近宅在家里也没事,就想着使用Redis配合事件总线去实现下具体的业务. 需求 一 ...

  7. Redis 发布订阅,小功能大用处,真没那么废材!

    今天小黑哥来跟大家介绍一下 Redis 发布/订阅功能. 也许有的小伙伴对这个功能比较陌生,不太清楚这个功能是干什么的,没关系小黑哥先来举个例子. 假设我们有这么一个业务场景,在网站下单支付以后,需要 ...

  8. redis发布订阅客户端报错

    转自简书[https://www.jianshu.com/p/a85ec38245da] 最近遇到一个问题,springBoot程序中有一个监听器,监听redis中发来的消息(其实是监听一个key的消 ...

  9. Python 操作 Redis 发布订阅

    Python 操作 Redis 发布订阅 介绍 Redis可以通过多个客户机订阅相同的频道,一个服务机在相应频道进行发布,从而实现在客户机收听服务机发布相应信息,可以利用这个机制实现多个客户机之间的信 ...

随机推荐

  1. .Net Core2.2 使用 AutoMapper进行实体转换

    一.遇到的问题 在. Core Api 的编写中,我们经常会对一些功能点进行新增编辑操作,同时我们有时也会进行查询,但是我们查询的表的数据与我们返回的数据相差甚大,这是我们有需要自己手动进行类型的转换 ...

  2. 深入理解Java AIO(三)—— Linux中的AIO实现

    我们调用的Java AIO底层也是要调用OS的AIO实现,而OS主要也就Windows和Linux这两大类,当然还有Solaris和mac这些小众的. 在 Windows 操作系统中,提供了一个叫做 ...

  3. Ubuntu添加新用户并给普通用户赋予root新权限

    添加新用户 首先用adduser命令添加普通用户: #adduser newusername 只有在root权限才可以添加新用户 修改密码: #passwd username 赋予root权限 方法1 ...

  4. [ASP.NET Core MVC] 如何实现运行时动态定义Controller类型?

    昨天有个朋友在微信上问我一个问题:他希望通过动态脚本的形式实现对ASP.NET Core MVC应用的扩展,比如在程序运行过程中上传一段C#脚本将其中定义的Controller类型注册到应用中,问我是 ...

  5. tensorflow编程学习路线及笔记

    话不多说,直接上图! 关于人工智能算法学习思路,欢迎浏览我的另一篇随笔:如果你想开始学习算法,不妨先了解人工智能有哪些方向? 关于python编程学习路线及笔记,欢迎浏览我的另一篇随笔:python编 ...

  6. 普通企业的规划类项目中,OptaPlanner更适合作为APS的规划优化引擎

    在企业的规划.优化场景中,均需要开发规划类的项目,实现从从种可能方案中找出相对最优方案.如排班.生产计划(包括高层次的供应链优化,到细粒度的车间甚至机台作业指令).车辆调度等.因为这类场景需要解决的问 ...

  7. Jenkins中管道案例脚本(生命式语法)

    pipeline { agent any parameters { choice( choices: 'feature\nmaster\npercent10', description: '选择要发布 ...

  8. 从一个慢查询到MySQL字符集编码

    从一个慢查询到MySQL字符集编码 目录 从一个慢查询到MySQL字符集编码 1. 问题起源 2. MySQL字符集和字符集排序规则 2.1 字符集相关概念 2.2 MySQL中的字符集和字符集排序规 ...

  9. win10无法使用VMwareWorkstation的解决办法

    最近(2019-10)国庆期间,微软更新了一次win10. 此次更新导致很多同学的Workstation pro不能用了. 主要的解决办法有一下几种: 卸载最新的系统更新包 在控制面板>> ...

  10. Linux学习,账号管理与权限管理

    linux系统本来不认识账号,只是通过UID(用户ID)和GID(所属组ID)来区分账号属性的.而这对应的目录如下: UID ===> /etc/passwd GID ===> /etc/ ...