一文搞懂Redis的发布订阅

来自文章集合:一文带你搞懂redis使用过程(持续更新中)

Redis发布订阅

什么是发布/订阅

当你去订阅一份电子报,当有新的新闻发生时,报社会将新闻推送给你。使用redis可以像订阅一份电子报一样订阅redis频道,然后当有新消息发布到该频道时,你就会收到通知。

发布者就像是报社,它发送消息到特定频道,而订阅者就像是订阅者,他们可以从频道中接受信息。

当redis频道无人订阅时,频道会自动删除。

如何订阅频道和接受频道消息

redis可以使用SUBSCRIBE命令来订阅一个或多个频道,然后使用PUBLISH命令向频道发布消息

下面我新建一个redis客户端1,先订阅3个频道

json 复制代码
127.0.0.1:6379> SUBSCRIBE rediChat1 redisChat2 redisChat3
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediChat1"
3) (integer) 1
1) "subscribe"
2) "redisChat2"
3) (integer) 2
1) "subscribe"
2) "redisChat3"
3) (integer) 3

新建一个redis客户端2,订阅redisChat3频道

json 复制代码
127.0.0.1:6379> SUBSCRIBE redisChat3
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat3"
3) (integer) 1

新建一个redis客户端3,进行消息推送

json 复制代码
127.0.0.1:6379> publish redisChat3 "Hello World"
(integer) 2
127.0.0.1:6379> publish redisChat2 "I Want to go home"
(integer) 1

监听客户端的显示

json 复制代码
//	redis客户端1
27.0.0.1:6379> SUBSCRIBE rediChat1 redisChat2 redisChat3
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "rediChat1"
3) (integer) 1
1) "subscribe"
2) "redisChat2"
3) (integer) 2
1) "subscribe"
2) "redisChat3"
3) (integer) 3
1) "message"
2) "redisChat3"
3) "Hello World"
1) "message"
2) "redisChat2"
3) "I Want to go home"


//	redis客户端2
127.0.0.1:6379> SUBSCRIBE redisChat3
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat3"
3) (integer) 1
1) "message"
2) "redisChat3"
3) "Hello World"

命令介绍

查看当前已创建的频道

PUBSUB channels

订阅给定的一个或多个频道,频道不存在则创建频道

SUBCRIBE <channel> [channel]

例子如下:

json 复制代码
127.0.0.1:6379> pubsub channels
(empty list or set)
127.0.0.1:6379> SUBSCRIBE redis_chat1 redis_chat2 redis_chat3 redis_chat4
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redis_chat1"
3) (integer) 1
1) "subscribe"
2) "redis_chat2"
3) (integer) 2
1) "subscribe"
2) "redis_chat3"
3) (integer) 3
1) "subscribe"
2) "redis_chat4"
3) (integer) 4
1) "message"
2) "redis_chat1"
3) "hello world"

订阅一个或多个符合给定模式的频道

PSUBSCRIBE <pattern> [pattern]

例子如下:

json 复制代码
127.0.0.1:6379> PSUBSCRIBE redis_chat*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "redis_chat*"
3) (integer) 1
1) "pmessage"
2) "redis_chat*"
3) "redis_chat1"
4) "hello world"

发送消息到指定的频道

PUBLISH <channel> <message>

json 复制代码
127.0.0.1:6379> PUBLISH redis_chat1 "hello world"
(integer) 2

返回的参数是2,是指消息成功发送到两个订阅者消息中。上面两个订阅者频道,会收到如上述例子中的消息。


频道退订

在windows打开的cmd中,订阅频道之后回阻塞,只能通过<ctrl + c>来取消频道的订阅,但是在代码的使用中,不会一直阻塞在,需要通过命令来取消频道的订阅,命令如下:

退订所有给定模式的频道:

PUNSUBSCRIBE <pattern> [pattern...]

退订指定的频道:

UNSUBSCRIBE <channel> [channel...]

下面例子是使用java的jedis操作,这里大概知道就好,有兴趣可以了解:java中redis的使用

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;

public class UnsubscribeExample {
    public static void main(String[] args) {
		//	创建一个jedis,用于操作redis
        Jedis jedis = new Jedis("localhost");
		//	创建一个订阅者,用来处理事件:消息、订阅、取消订阅
        JedisPubSub jedisPubSub = new JedisPubSub() {
            @Override
            public void onMessage(String channel, String message) {
                System.out.println("Received message: " + message + " from channel: " + channel);
            }

            @Override
            public void onSubscribe(String channel, int subscribedChannels) {
                System.out.println("Subscribed to channel: " + channel);
            }

            @Override
            public void onUnsubscribe(String channel, int subscribedChannels) {
                System.out.println("Unsubscribed from channel: " + channel);
            }
        };
		//	订阅`channel1`频道
        jedis.subscribe(jedisPubSub, "channel1");
		      
        // 业务操作

        // 退订`channel1`频道
        jedisPubSub.unsubscribe("channel1");
    }
}

使用场景和需要注意的问题

使用场景

Redis 发布/订阅模式常常被用于实现消息的广播和实时通知。以下是一些使用场景:

  • 实时通讯:在聊天应用中,可以使用发布/订阅模式向所有在线用户广播消息。
  • 数据更新通知:在分布式系统中,当数据更新时,可以使用发布/订阅模式通知其他节点更新其缓存。
  • 实时消息传递:用于实时更新例如股票市场行情、实时新闻等。
  • 订阅服务:允许用户订阅特定主题或内容类型的服务。
  • 多播消息:在需要将同一消息发送给多个消费者时,可以使用发布/订阅模式。

这些使用场景都可以利用 Redis 的发布/订阅功能来实现实时的消息传递和广播。

需要注意的问题

  • 消息丢失: Redis 的发布/订阅模式不会保证消息的持久性,如果有订阅者处于离线状态,它将无法接收到在其离线期间发布的消息。可以通过实现消息确认机制、持久化存储或使用消息队列等方法来避免消息丢失。
  • 消息订阅和取消: 订阅者需要明确知道何时订阅消息以及何时取消订阅,否则可能会导致消息堆积或无法接收到最新的消息。
  • 消息传递保证: Redis 的发布/订阅模式不保证每个订阅者都能接收到消息,因为这取决于网络的状况以及订阅者自身的处理速度。
  • 订阅者的处理能力: 如果订阅者的处理能力不足以处理高频率的消息传递,可能会导致消息堆积和处理延迟。处理延迟可能会导致其处于离线状态,无法在接收消息。使用时 需要评估订阅者的处理能力和负载情况,确保其能够处理和消化所接收到的消息,避免消息堆积导致的性能问题或故障。
  • 消息格式和解析: 发布者和订阅者之间需要对消息的格式达成共识,以便正确解析和处理消息内容。

在使用 Redis 的发布/订阅功能时,需要考虑这些问题,并设计相应的应对方案以确保消息的可靠传递和处理。

引申

频道名可以与已有字段的键(key)名相同?

是的,频道名可以与已有的键(key)名相同。在 Redis 中,频道名和键名是不同的命名空间,它们之间没有冲突。

相关推荐
m0_571957581 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
Chrikk5 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*5 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue5 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man5 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
测开小菜鸟5 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity6 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq