Redis 发布订阅

1.何为Redis发布订阅?

是一种消息通信模式,允许发布者直接把消息发布到某个频道上面,而不是直接发给接受者,然后订阅了这个频道的订阅者都可以接受消息

2.如何使用

先建立一个send.py文件(发布者)代码如下

import redis  # 安装

def publish_message(channel, message):
    r = redis.Redis(host='localhost', port=6379, db=0)  实例化
    r.publish(channel, message) 发布信息到频道
    print(f"Message '{message}' published to channel '{channel}'")

if __name__ == "__main__":
    channel = "test_channel"
    message = "Hello, Redis!"
    publish_message(channel, message)

在建立一个recv的文件(订阅者)

import redis

def message_handler(message):
    print(f"Received message: {message['data'].decode('utf-8')}")

def subscribe_to_channel(channel):
    r = redis.Redis(host='localhost', port=6379, db=0)  # 创建 Redis 客户端连接
    pubsub = r.pubsub()  # 创建 Pub/Sub 对象
    pubsub.subscribe(**{channel: message_handler})  # 订阅频道,并指定消息处理函数
    print(f"Subscribed to channel '{channel}'")
    
    # 无限循环监听订阅的频道
    for message in pubsub.listen():
        if message['type'] == 'message':  # 检查消息类型是否为 'message'
            message_handler(message)  # 调用消息处理函数处理收到的消息

if __name__ == "__main__":
    channel = "test_channel"
    subscribe_to_channel(channel)

注意点

  • pubsub.listen() 是一个生成器方法,会持续等待和接收新消息,因此需要使用无限循环来处理这些消息。
  • 使用无限循环可以确保订阅者持续监听频道,并处理所有收到的消息。
  • 处理可能的连接中断可以提高系统的可靠性,确保订阅者在连接中断后能够重新连接并继续接收消息。
  • 当发送方的代码send.py运行之后关闭,发布者不再发布消息,订阅者的 for message in pubsub.listen() 循环将不会退出。pubsub.listen() 会持续运行并等待新消息,即使没有新的消息发布。这个循环只有在连接出现问题(如网络连接断开)或程序显式终止时才会退出。如果你想显示的退出循环,你可以自己加条件判断退出循环
  • 那请问这个发布信息到频道,这个频道在Redis数据库中可见吗? 在 Redis 中,频道并不像键值对那样存储在数据库中,因此它们在 Redis 的键空间中不可见。当你发布消息到一个频道时,Redis 不会在数据库中持久化存储这些频道或消息。相反,发布/订阅机制是一个内存中的消息传递系统,频道和消息在内存中暂时存在。

  • 那会不会存在发布者发布信息的时候,数据丢失的情况?在 Redis 发布/订阅(Pub/Sub)模式下,如果没有订阅者,发布者发布的信息会被丢弃。这是因为 Redis 的 Pub/Sub 是一种即时消息传递机制,不会对消息进行持久化存储。因此,如果在消息发布时没有订阅者接收,消息将无法传递到任何客户端并且会丢失。

  • 那怎么解决这种丢失的情况呢?

  • 使用 Redis 列表:将消息存储在 Redis 列表中,订阅者可以从列表中消费消息。这种方法可以确保消息不会丢失,因为消息被存储在 Redis 中,订阅者可以随时读取。
  • 使用 Redis 流(Streams):Redis Streams 提供了一种持久化消息的机制,支持发布/订阅和消息队列的功能。消息会存储在流中,消费者可以读取和确认消息。
  • 使用消息队列:使用专门的消息队列系统,如 RabbitMQ、Apache Kafka 等,这些系统设计用于高可靠性消息传递,支持消息持久化和确认机制。

示例:使用 Redis 列表

发布者
import redis

def publish_message(channel, message):
    r = redis.Redis(host='localhost', port=6379, db=0)
    r.rpush(channel, message)  # 将消息推送到列表中
    print(f"Message '{message}' added to channel '{channel}'")

if __name__ == "__main__":
    channel = "test_channel"
    message = "Hello, Redis!"
    publish_message(channel, message)
订阅者
import redis
import time

def consume_messages(channel):
    r = redis.Redis(host='localhost', port=6379, db=0)
    
    while True:
        message = r.blpop(channel, timeout=0)  # 阻塞等待消息
        if message:
            print(f"Received message: {message[1].decode('utf-8')}")

if __name__ == "__main__":
    channel = "test_channel"
    consume_messages(channel)

示例:使用 Redis Streams

发布者
import redis

def publish_message(stream, message):
    r = redis.Redis(host='localhost', port=6379, db=0)
    r.xadd(stream, {"message": message})  # 将消息添加到流中
    print(f"Message '{message}' added to stream '{stream}'")

if __name__ == "__main__":
    stream = "test_stream"
    message = "Hello, Redis Streams!"
    publish_message(stream, message)
订阅者
import redis
import time

def consume_messages(stream):
    r = redis.Redis(host='localhost', port=6379, db=0)
    last_id = '0'  # 从最早的消息开始读取
    
    while True:
        messages = r.xread({stream: last_id}, count=1, block=0)
        if messages:
            for stream_name, message_list in messages:
                for message_id, message in message_list:
                    print(f"Received message: {message[b'message'].decode('utf-8')}")
                    last_id = message_id  # 更新最后读取的消息ID

if __name__ == "__main__":
    stream = "test_stream"
    consume_messages(stream)
  • Redis 通过维护一个内部数据结构来跟踪每个频道的订阅者数量。这个具体是在哪维护的呢

Redis 内部数据结构

在 Redis 的内部,使用了一些哈希表来跟踪订阅者和频道。这些数据结构定义在 Redis 源代码中,具体来说,它们主要包括以下几个:

  1. pubsub_channels:这是一个哈希表,键是频道名,值是订阅该频道的客户端列表。
  2. pubsub_patterns:这是一个链表,存储了所有的模式订阅信息。
  • 常用场景
  • 实时聊天应用 实时通知系(系统事件通知、警报通知) 金融市场数据、物联网(IoT)数据处理。微服务间的事件通知和通信 商品上新,实时游戏状态同步 直播弹幕 等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值