Redis 发布订阅 (pub/sub) 是一种消息通信模式: 发送者 (pub) 发送消息, 订阅者 (sub) 接收消息.
Redis 客户端可以订阅任意数量的频道.
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 -- client2 , client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
实例
以下实例演示了发布订阅是如何工作的. 在我们实例中我们创建了订阅频道名为 redisChat:
- redis 127.0.0.1:6379> SUBSCRIBE redisChat
- Reading messages... (press Ctrl-C to quit)
- 1) "subscribe"
- 2) "redisChat"
- 3) (integer) 1
现在, 我们先重新开启个 redis 客户端, 然后在同一个频道 redisChat 发布两次消息, 订阅者就能接收到消息.
- redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"
- (integer) 1
- redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by w3cschool.cc"
- (integer) 1
- # 订阅者的客户端会显示如下消息
- 1) "message"
- 2) "redisChat"
- 3) "Redis is a great caching technique"
- 1) "message"
- 2) "redisChat"
- 3) "Learn redis by w3cschool.cc"
Redis 发布订阅命令
下表列出了 redis 发布订阅常用命令:
Redis 发布订阅与 ActiveMQ 的比较
(1)ActiveMQ 支持多种消息协议, 包括 AMQP,MQTT,Stomp 等, 并且支持 JMS 规范, 但 Redis 没有提供对这些协议的支持;
(2)ActiveMQ 提供持久化功能, 但 Redis 无法对消息持久化存储, 一旦消息被发送, 如果没有订阅者接收, 那么消息就会丢失;
(3)ActiveMQ 提供了消息传输保障, 当客户端连接超时或事务回滚等情况发生时, 消息会被重新发送给客户端, Redis 没有提供消息传输保障.
总之, ActiveMQ 所提供的功能远比 Redis 发布订阅要复杂, 毕竟 Redis 不是专门做发布订阅的, 但是如果系统中已经有了 Redis, 并且需要基本的发布订阅功能, 就没有必要再安装 ActiveMQ 了, 因为可能 ActiveMQ 提供的功能大部分都用不到, 而 Redis 的发布订阅机制就能满足需求.
Redis 实现任务队列
使用 Redis 实现任务队列首先想到的就是 Redis 的列表类型, 因为在 Redis 内部,== 列表类型是由双向链表实现 == 的.
实现任务队列, 只需让生产者将任务使用 LPUSH 加入到某个键中, 然后另一个消费者不断地使用 RPOP 命令从该键中取出任务即可.
- // 生产者只需将 task LPUSH 到队列中
- 127.0.0.1:6379> LPUSH queue task
- (integer) 1
- 127.0.0.1:6379> LRANGE queue 0 -1
- 1) "task"
- // 消费者只需从队列中 LPOP 任务, 如果为空则轮询.
- 127.0.0.1:6379> LPOP queue
- "task"
BLPOP 指令可以在队列为空时处于阻塞状态. 就不用处于轮询的状态.
- 127.0.0.1:6379> BLPOP queue 0 //0 表示无限制等待
- // 消费者当队列为空则处于阻塞状态.
- // 生产者将 task LPUSH 到队列中, 处于阻塞状态的消费者离开返回
- 127.0.0.1:6379> LPUSH queue task
- (integer) 1
- // 消费者立刻 "消费", 取出 task.
- 127.0.0.1:6379> BLPOP queue 0
- 1) "queue"
- 2) "task"
- (13.38s)
优先级队列
当一个队列中有许多任务仍然没有来得及被消费者及时消费时, 如果出现紧急的消息, 则不得不等待队列中的任务被一一取出, 因此, 需要实现一个优先级队列, 当优先级队列不为空时, 消费者优先取出优先级队列中的任务去执行.
BLPOP 命令可以同时接收多个键
BLPOP key [key ...] timeout
, 当所有键 (列表类型) 都为空时, 则阻塞, 当其中一个有元素则会从该键返回.== 如果多个键都有元素则按照从左到右的顺序取第一个键中的一个元素, 因此可以借此特性实现优先级队列.==
- 127.0.0.1:6379> LPUSH queue1 first
- (integer) 1
- 127.0.0.1:6379> LPUSH queue2 second
- (integer) 1
- // 当两个键都有元素时, 按照从左到右的顺序取第一个键中的一个元素
- 127.0.0.1:6379> BRPOP queue1 queue2 0
- 1) "queue1"
- 2) "first"
- 127.0.0.1:6379> BRPOP queue1 queue2 0
- 1) "queue2"
- 2) "second"
来源: http://www.bubuko.com/infodetail-2567411.html