一、技术背景
实现发布订阅的中间件有许多,包括时下最热的Kafka
、RabbitMQ
、ActiveMQ
,不太常见的Guava
下的EventBus
,以及Redis
等。关于MQ
之流的分析已经够多了,今天详细介绍下Redis
的发布订阅机制及其实现。事实上,Redis
的发布订阅机制在具体项目中的应用非常少,主要有两方面原因:其一,Redis
的可靠性比较差,一旦出现断网等情况,则发布的消息便全部丢失;其二,Redis
的消息处理方式是通过单线程循环遍历实现的,若存在大量的消息发布,则可能导致输出缓冲区膨胀,甚至服务崩溃。但对数据安全性和稳定性要求不高的场景来说,Redis
不失为最佳的选择。
二、基本操作
Redis
的发布订阅模式包括普通订阅,普通订阅取消,模式订阅,模式订阅取消这四个场景。用命令实现如下:
启动
Redis
服务(以Windows
平台为例)1
2
3C:\Tools\Redis>redis-server.exe redis.windows.conf
...
The server is now ready to accept connections on port 6379创建客户端
client1
,并以普通订阅渠道channel1
1
2
3
4
5
6redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> SUBSCRIBE channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1创建客户端
client2
,并普通订阅渠道channel2
1
2
3
4
5
6redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> SUBSCRIBE channel2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel2"
3) (integer) 1创建客户端
client3
,并模式订阅渠道channel*
1
2
3
4
5
6redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> PSUBSCRIBE channel*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel*"
3) (integer) 1向渠道
channel2
发布一条消息1
2
3
4redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> PUBLISH channel2 "msg from channel2"
(integer) 2
127.0.0.1:6379>client2
、client3
接收到消息1
2
3
4
5
6
7
8
9
10# ----------client2---------
1) "message"
2) "channel2"
3) "msg from channel2"
# ----------client3---------
1) "pmessage"
2) "channel*"
3) "channel2"
4) "msg from channel2"
因此,我们可以猜测,消息发布者与消息订阅者之间是通过渠道连接的,包括精准匹配(普通订阅)和模糊匹配(模式订阅)。经过分析其结构设计,可表示为用例:
三、原理分析
Redis
发布订阅的核心实现在pubsub.c
文件。从头文件server.h
中可以读取相关函数声明:
1 | void subscribeCommand(client *c); /* 普通订阅 */ |
- 普通订阅模式:
1 |
|
普通订阅模式主要做了两件事:将订阅渠道添加至客户端pubsub_channels
哈希表中;将订阅客户端添加至服务端的pubsub_channels
哈希表中。可如下表示: