发布订阅简介

除了使用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. SVM | 支持向量机原理讲解(二)

    一.线性可分的支持向量机存在的问题 在支持向量机一中,我们介绍了当数据集是线性可分的时候,我们可以使用线性可分的支持向量机将数据进行分类(由于隔了很长时间才更新,因此忘记了支持向量机一的读者可以回看支 ...

  2. 【Pytest02】全网最全最新的Pytest框架快速进阶篇(pytest前置和后置以及忽略测试用例)

    一.Pytest的前置和后置方法 1.Pytest可以集成unittest实现前置和后置 import unittest import pytest class TestCase(unittest.T ...

  3. Jmeter 注册用户获取登录token值

    1. 打开jemeter,新建一个测试计划,>线程组 >新建一个 登录的 Http 请求. 2.填上相应的值 3.新建一个消息头管理器> content-Type  applicat ...

  4. Java是未来的第一编程语言吗?

    目录 一.前言 二.Java帝国的今天 2.1 依然霸占TIOBE热门编程语言的榜首 2.2 曾经想扼杀Java的微软宣布加入OpenJDK 2.3 Oracle发布开源全栈虚拟机GraalVM 三. ...

  5. yum-程序包管理器前端工具

    一.要想使用yum先要指定yum源 /etc/yum.com /etc/yum.repos.d/*repo 一.yum的使用 yum [option] command  包名 option -y: c ...

  6. 实验四 数据查询3-group by等

    实验四 数据库查询 一.  实验内容: 1. Group by语句 2. Having 语句 3. Order by语句 4. Limit语句 5. Union语句 6. Handler语句 二.  ...

  7. Java 运行时数据区

    写在前面 本文描述的有关于 JVM 的运行时数据区是基于 HotSpot 虚拟机. 概述 JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以 ...

  8. C++ memset函数用法

    #include<stdio.h>#include<string.h>int main(){ char buffer[] = "I love you!"; ...

  9. C语言 文件操作(一)

    #include<stdio.h> int main(){          FILE *fp = fopen("f:\\lanyue.txt","r&quo ...

  10. 第二章 IBM

    1.不要招惹IBM,这可是一家做过军火的公司,一家参与了曼哈顿计划的公司. 同时也是世界上最大的服务公司.第二大软件公司.第二大数据库公司.拥有工业界最大的实验室.第一专利申请大户.最大的开源linu ...