来自文章集合:
一文带你搞懂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 中,频道名和键名是不同的命名空间,它们之间没有冲突。