当前位置:首页 > 问答 > 正文

用Redis订阅消息来搞数据通信,顺带说说那些订阅命令怎么用

整理自Redis官方文档、博客文章《Redis Pub/Sub入门》以及技术社区讨论帖《Redis消息传递实战》)

Redis的订阅消息功能,就像在一个热闹的广场上设立了许多个“公告板”(频道),有人负责往特定的公告板上贴消息(发布者),而对此公告板内容感兴趣的人则可以站在前面看(订阅者),这种方式非常适合用来在不同的应用程序或服务之间进行简单的、实时的数据通信,比如在线聊天室、实时通知系统、或者服务器之间传递状态变化信号。

核心概念:频道(Channel)与模式(Pattern)

在Redis里,最基本的通信单位是“频道”,你可以把它想象成那个公告板的名字,新闻快报”或“天气预警”,订阅者需要明确指定自己关心哪个频道的消息。

但有时候,订阅者可能想同时关注多个有相似名字的频道,比如所有以“log:”开头的频道,用来接收不同级别的日志信息,这时就需要用到“模式订阅”,模式订阅允许使用通配符来批量订阅频道,非常灵活。

主要命令怎么用

  1. 发布消息:PUBLISH 这是发布者使用的唯一命令,非常简单。 格式: PUBLISH channel message 例子: 假设我们有一个聊天室叫“room:chat”,用户A说了一句“大家好!”,那么发布这条消息的命令就是: PUBLISH room:chat "用户A:大家好!" 执行后,Redis会返回一个数字,表示收到这条消息的订阅者数量。

  2. 订阅频道:SUBSCRIBE 这是订阅者用来开始监听一个或多个频道的命令。 格式: SUBSCRIBE channel1 channel2 ... 例子: 用户B想加入“room:chat”聊天室,他就在自己的客户端输入: SUBSCRIBE room:chat 一旦执行这个命令,客户端的连接就会进入“订阅模式”,在这个模式下,它不能再执行像GETSET这样的普通Redis命令了,只能专心接收消息或者使用其他订阅相关的命令,当有消息发布到“room:chat”时,Redis服务器会主动推送一条信息给用户B的客户端,推送的信息是一个数组,包含三个部分:

    • 消息类型(这里是"message")
    • 来源频道("room:chat")
    • ("用户A:大家好!") 应用程序需要编写代码来解析这个数组,并做出相应处理。
  3. 退订频道:UNSUBSCRIBE 当订阅者不想再听某个频道的消息时,使用这个命令。 格式: UNSUBSCRIBE channel1 channel2 ... 如果不指定任何频道,就会退订所有当前已订阅的频道。

  4. 模式订阅:PSUBSCRIBE 这是SUBSCRIBE的增强版,支持通配符。 格式: PSUBSCRIBE pattern1 pattern2 ... 支持的通配符:

    • :匹配任意数量的字符(包括零个),比如news.*可以匹配news.sportsnews
    • :匹配一个字符,比如log:war?可以匹配log:warn,但不能匹配log:warning
    • [ae]:匹配括号内的某个字符,比如chan[12]可以匹配chan1chan2例子: 一个日志监控服务想订阅所有错误和警告级别的日志,它可以这样写: PSUBSCRIBE log:error log:warning 或者更简洁地使用通配符: PSUBSCRIBE log:* (这会订阅所有以log:开头的频道)
  5. 模式退订:PUNSUBSCRIBE 用法和UNSUBSCRIBE类似,用于退订之前通过模式订阅的频道。 格式: PUNSUBSCRIBE pattern1 pattern2 ...

  6. 查看订阅情况:PUBSUB 这是一个管理命令,可以帮助你了解当前的订阅状态。 常用子命令:

    • PUBSUB CHANNELS [pattern]:列出当前活跃的频道(即至少有一个订阅者),可以提供一个模式来过滤。
    • PUBSUB NUMSUB channel1 channel2 ...:查询指定频道当前的订阅者数量。
    • PUBSUB NUMPAT:查询当前被订阅的模式数量(注意不是频道数量)。

实战中的一些要点

  • 消息是“即发即忘”的: Redis的Pub/Sub非常快,但它不保证消息可靠性,如果某个订阅者在发布消息的那一刻没有连接到服务器(比如网络闪断),它就永远收不到那条消息,消息不会被持久化存储。
  • 适合实时场景: 正因为上述特性,它最适合用于对消息丢失不敏感、但要求低延迟的实时通信场景,如果需要保证每条消息都不丢失,应该考虑更专业的消息队列(如RabbitMQ、Kafka),或者使用Redis的Streams数据结构,它提供了更强大的持久化和消息确认机制。
  • 连接管理: 订阅者需要维持一个长连接来监听消息,在实际编程中(比如用Python、Java等语言),通常会使用Redis客户端库的异步或线程安全特性来专门处理订阅连接,避免阻塞主程序。

Redis的订阅发布机制提供了一种轻量级、快速的进程间通信手段,它的命令简单直观,上手容易,但在使用时一定要清楚其“非持久化”的特点,把它用在正确的业务场景里。

用Redis订阅消息来搞数据通信,顺带说说那些订阅命令怎么用