[Golang 修仙之路] Redis:发布订阅 & Redis Stream

44 阅读2分钟

参考

  1. java全栈知识体系:pdai.tech/md/db/nosql…
  2. 《Redis设计与实现》黄健宏 著

发布订阅

命令使用

  • SUBSCRIBE channel [channel ...]:订阅一个或多个频道。
  • UNSUBSCRIBE [channel [channel ...]]:取消订阅频道。
  • PSUBSCRIBE pattern [pattern ...]:使用模式匹配订阅频道(例如news.*)。
  • PUNSUBSCRIBE [pattern [pattern ...]]:取消通过模式匹配进行的订阅。
  • PUBLISH channel message:向指定频道发布消息

特点

  1. 消息不持久化。
  2. 无消息确认机制。发布者无法知道订阅者是否成功消费了消息。
  3. 订阅者阻塞。消息订阅者(Subscribe客户端)在等待消息期间需要独占连接并以阻塞的方式等待消息,在此期间无法使用同一连接进行其他操作。

(1)使用psubscribe命令可以重复订阅同一个频道,如客户端执行了psubscribe c? c?*。这时向c1发布消息客户端会接受到两条消息,而同时publish命令的返回值是2而不是1。

(2)punsubscribe命令可以退订指定的规则,用法是: punsubscribe [pattern [pattern ...]],如果没有参数则会退订所有规则。

(3)使用punsubscribe只能退订通过psubscribe命令订阅的规则,不会影响直接通过subscribe命令订阅的频道;同样unsubscribe命令也不会影响通过psubscribe命令订阅的规则。

(4)另外需要注意punsubscribe命令退订某个规则时不会将其中的通配符展开,而是进行严格的字符串匹配,所以punsubscribe * 无法退订c*规则,而是必须使用punsubscribe c*才可以退订。(它们是相互独立的,后文可以看到数据结构上看也是两种实现)

底层实现

订阅

客户端订阅指定的频道(subscribe),通过redis-server的一个属性pubsub_channels,这个pubsub_channels是一个字典。key是string类型的频道名称,value是客户端组成的链表。如下图:

image.png

当一个新的客户端订阅了指定频道时,将客户端加入到指定频道的末尾即可。

image.png

客户端订阅模式频道(psubscribe),通过redis-server的另一个字段pubsub_patterns,该字段是一个链表,通过在该链表下添加一个pubsubPattern实现订阅。

image.png

发布

  • “PUBLISH命令要做的就是在pubsub_channels字典里找到频道channel的订阅者名单(一个链表),然后将消息发送给名单上的所有客户端。”

  • “PUBLISH命令要做的就是遍历整个pubsub_patterns链表,查找那些与channel频道相匹配的模式,并将消息发送给订阅了这些模式的客户端。”

Stream

命令使用

特点

底层实现

应用场景