Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。

redis的发布订阅类似于消息队列的主题模式。

client1,client2和client5订阅了channel1
Redis高级用法之发布订阅 - 图1
那么当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
Redis高级用法之发布订阅 - 图2

订阅(根据规则)

规则支持通配符
通配符中?表示1个占位符,表示任意个占位符(包括0),?表示1个以上占位符。
不会收到订阅之前就发布到该频道的消息

  1. PSUBSCRIBE pattern [pattern ...]

返回值
为1表示被订阅者所接受
为0表示没有被订阅者接收

client1订阅

  1. 127.0.0.1:6379> psubscribe c? b* d?*
  2. Reading messages... (press Ctrl-C to quit)
  3. 1) "psubscribe"
  4. 2) "c?"
  5. 3) (integer) 1
  6. 1) "psubscribe"
  7. 2) "b*"
  8. 3) (integer) 2
  9. 1) "psubscribe"
  10. 2) "d?*"
  11. 3) (integer) 3

client2发布

  1. 127.0.0.1:6379> PUBLISH c1 hello
  2. (integer) 1
  3. 127.0.0.1:6379> PUBLISH c11 hello
  4. (integer) 0
  5. 127.0.0.1:6379> PUBLISH b11 hello
  6. (integer) 1
  7. 127.0.0.1:6379> PUBLISH d hello
  8. (integer) 0
  9. 127.0.0.1:6379> PUBLISH d1 hello
  10. (integer) 1
  11. 127.0.0.1:6379> PUBLISH d2 hello
  12. (integer) 1

client1消费消息

  1. 127.0.0.1:6379> psubscribe c? b* d?*
  2. Reading messages... (press Ctrl-C to quit)
  3. 1) "psubscribe"
  4. 2) "c?"
  5. 3) (integer) 1
  6. 1) "psubscribe"
  7. 2) "b*"
  8. 3) (integer) 2
  9. 1) "psubscribe"
  10. 2) "d?*"
  11. 3) (integer) 3
  12. 1) "pmessage"
  13. 2) "c?"
  14. 3) "c1"
  15. 4) "hello"
  16. 1) "pmessage"
  17. 2) "b*"
  18. 3) "b11"
  19. 4) "hello"
  20. 1) "pmessage"
  21. 2) "d?*"
  22. 3) "d1"
  23. 4) "hello"
  24. 1) "pmessage"
  25. 2) "d?*"
  26. 3) "d2"
  27. 4) "hello"

订阅(指定名字)

不会收到订阅之前就发布到该频道的消息

  1. SUBSCRIBE channel [channel ...]

查看订阅与发布系统状态。

  1. PUBSUB subcommand [argument [argument ...]]

发布消息

  1. PUBLISH channel message

退订(根据规则)

  1. PUNSUBSCRIBE [pattern [pattern ...]]

退订(指定名字)

  1. UNSUBSCRIBE [channel [channel ...]]

示例

我们开两个会话窗口,开启两个redis-cli连接一个redis-server。

订阅

client1订阅anin-chat这个channel

  1. 127.0.0.1:6379> SUBSCRIBE anin-chat
  2. Reading messages... (press Ctrl-C to quit)
  3. 1) "subscribe"
  4. 2) "anin-chat"
  5. 3) (integer) 1

发布

client2往anin-chat发布两条消息。

  1. 127.0.0.1:6379> PUBLISH anin-chat hello~anin
  2. (integer) 1
  3. 127.0.0.1:6379> PUBLISH anin-chat yes!
  4. (integer) 1
  5. 127.0.0.1:6379>

消费

我们发现client1收到了client2发的消息。

  1. 1) "message"
  2. 2) "anin-chat"
  3. 3) "hello~anin"
  4. 1) "message"
  5. 2) "anin-chat"
  6. 3) "yes!"

注意

  • 使用psubscribe命令可以重复订阅同一个频道,如客户端执行了psubscribe c? c?。这时向c1发布消息客户端会接受到两条消息,而同时publish命令的返回值是2而不是1。同样的,如果有另一个客户端执行了subscribe c1 和psubscribe c?的话,向c1发送一条消息该客户顿也会受到两条消息(但是是两种类型:message和pmessage),同时publish命令也返回2.
  • punsubscribe命令可以退订指定的规则,用法是: punsubscribe [pattern [pattern …]],如果没有参数则会退订所有规则。
  • 使用punsubscribe只能退订通过psubscribe命令订阅的规则,不会影响直接通过subscribe命令订阅的频道;同样unsubscribe命令也不会影响通过psubscribe命令订阅的规则。另外需要注意punsubscribe命令退订某个规则时不会将其中的通配符展开,而是进行严格的字符串匹配,所以punsubscribe 无法退订c规则,而是必须使用punsubscribe c*才可以退订。

**

  1. 127.0.0.1:6379> PSUBSCRIBE c? c?*
  2. Reading messages... (press Ctrl-C to quit)
  3. 1) "psubscribe"
  4. 2) "c?"
  5. 3) (integer) 1
  6. 1) "psubscribe"
  7. 2) "c?*"
  8. 3) (integer) 2
  9. 1) "pmessage"
  10. 2) "c?*"
  11. 3) "c1"
  12. 4) "hello"
  13. 1) "pmessage"
  14. 2) "c?"
  15. 3) "c1"
  16. 4) "hello"
  1. 127.0.0.1:6379> PUBLISH c1 hello
  2. (integer) 2

缺点

  • PubSub 的生产者来一个消息会直接传递给消费者。如果没有消费者,消息会直接丢弃。如果有多个消费者,一个消费者突然挂掉,生产者会继续发送消息,另外的消费者可以持续收到消息。但是挂掉的消费者重新连上后,断连期间的消息会彻底丢失;
  • 如果 Redis 停机重启,PubSub 的消息是不会持久化