当前位置: 首页 > news >正文

Redis Pub/Sub 与阻塞机制学习笔记

一、Redis Pub/Sub 基本概念

Redis Pub/Sub(Publish / Subscribe)是一种发布订阅消息模型

角色:

Publisher (发布者) | v Redis | v Subscriber (订阅者)

流程:

  1. 订阅者订阅频道
  2. 发布者向频道发布消息
  3. Redis 将消息推送给所有订阅者

示例代码:

import redis r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True) pubsub = r.pubsub() pubsub.subscribe("channel1") for msg in pubsub.listen(): if msg["type"] == "message": print(msg["data"])

发布消息:

r.publish("channel1", "hello")

二、Redis Pub/Sub 在 Redis 中的存储形式

一个非常重要的点:

Pub/Sub 频道不是 Redis Key。

它不会存储在 Redis 数据库中:

不是 key 不是 value 不会持久化 不会进入 db=0

Redis 内部只维护内存中的订阅关系表

内部结构可以理解为:

dict<channel, subscribers>

示例:

channel1 | +--- client1 +--- client2

发布消息时:

publish(channel1, hello) Redis查找 channel1 | +-- client1 +-- client2 发送消息

如果没有订阅者:消息直接丢弃

三、查看 Pub/Sub 状态

Redis 提供命令查看当前频道。

查看频道:

PUBSUB CHANNELS

示例:

127.0.0.1:6379> PUBSUB CHANNELS 1) "channel1"

查看订阅数量:

PUBSUB NUMSUB channel1

示例:

channel1 1

四、listen() 的工作原理

for msg in pubsub.listen():

这里的listen()阻塞迭代器

本质逻辑类似:

while True: msg = socket.recv() yield msg

流程:

等待 socket 数据 | v Redis publish | v socket 收到消息 | v 返回给 for 循环

五、什么是阻塞迭代器

1 迭代器

Python 迭代器是可以被for循环遍历的对象:

for x in iterator:

底层相当于:

iterator = iter(obj) while True: x = next(iterator)

2 阻塞

阻塞指:

没有数据时 程序暂停等待

例如:input() 程序会等待输入。

Redis 的listen()也是类似:

没有消息 → 等待 有消息 → 返回

六、listen() 返回的数据结构

收到消息时返回:

{ 'type': 'message', 'pattern': None, 'channel': 'channel1', 'data': 'hello' }

字段说明:

字段

含义

type

消息类型

channel

频道

data

消息内容

pattern

模式订阅

七、为什么阻塞不会导致整个系统卡死

问题核心:

部分代码阻塞,为什么整个系统不阻塞?

解决方法是并发模型

常见三种方式:

多线程 多进程 异步IO

八、多线程模型

将阻塞任务放入子线程:

import threading threading.Thread(target=listen).start()

结构:

进程 │ ├─ 主线程 │ └─ 子线程(阻塞等待)

特点:

子线程阻塞 不会影响主线程

九、多进程模型

uvicorn.run(..., workers=4)

结构:

主进程 │ ├─ worker1 ├─ worker2 ├─ worker3 └─ worker4

即使某个 worker 阻塞:

其他 worker 仍然可以处理请求

十、异步 IO(asyncio)

现代系统大量使用事件循环模型

示例:

async def task(): await asyncio.sleep(5)

await表示:

当前任务等待IO 先去执行其他任务

结构:

一个线程 | 事件循环 | ├─ task1 ├─ task2 └─ task3

十一、IO 多路复用

异步 IO 的底层依赖操作系统机制:

epoll (Linux) kqueue (Mac) IOCP (Windows)

逻辑:

线程询问内核: 哪些 socket 有数据?

流程:

无数据 → 继续处理其他任务 有数据 → 再处理该任务

这样线程不会被 IO 阻塞。

十二、Redis 为什么性能很高

Redis 是单线程模型,但能达到:

10万+ QPS

原因:

IO 多路复用 epoll 内存数据库

执行模型:

事件循环 | v 处理 socket 事件

十三、Pub/Sub 的生产环境用途

适合:

实时广播 消息通知 聊天系统 配置更新

示例:

用户注册 | publish user_register | +--- 邮件服务 +--- 优惠券服务 +--- 统计服务

十四、Pub/Sub 的缺点

Pub/Sub不适合做任务队列

原因:

问题

说明

消息丢失

没人订阅就丢

不可重试

没有 ack

无持久化

不存储消息

http://www.jsqmd.com/news/497780/

相关文章:

  • WPF Command 设计思想与实现剖析
  • 企业考勤系统场景适配能力深度解析:2号人事部的考勤适配多场景吗?
  • 全平台 Docker 部署 CPA(CLIProxyAPI Plus) 灵活定制指南 (Linux/Windows)——接入Codex
  • LeetCodeHot100|链表总结
  • baijiacms-master 审计实验
  • java毕业设计基于java+springboot的宠物管理系统
  • 学习Multipath多路径
  • Windows10如何更改Microsoft Store默认存储路径?如何把已安装的应用迁移到其他磁盘?(安装路径、安装目录)
  • 工业AI的十字路口:适应场景应用的小模型将胜出
  • 817169-73-6,Fmoc-Glu (biotinyl-PEG)-OH:生物素 PEG 化氨基酸试剂说明
  • Nano Banana2 最新国内直发入口
  • AIoT器件小型化:福尔蒂微米级荧光母粒实现0.3mm壁厚精准识别|项目实战
  • 基于springboot+Java的在线学习平台15827286
  • AI应用架构师实战:如何设计支持百万级用户的企业虚拟办公AI平台?
  • HyperView 基于Python Tcl二次开发之 模型分组并配色
  • 登月者杨植麟:90后清华学霸,如何用200万字上下文撬动AI版图?
  • 3月17日笔记
  • OmniLottie - 一键生成高质量Lottie矢量动画 支持文字、图片或视频生成 支持50系显卡 一键整合包下载
  • Vue3 vant4 解决引入的Toast和dialog样式丢失的bug
  • Java毕业设计基于SpringBoot的公寓出租系统的设计与实现7ogi87rn_213
  • 搜索 会员中心 创作中心 web安全学习路线(非常详细),零基础入门到精通,看这一篇就够了
  • 2026高压设备局放检测设备优质推荐榜:绝缘靴手套预防性试验装置、绝缘靴绝缘手套耐压试验装置、绝缘靴绝缘手套试验装置选择指南 - 优质品牌商家
  • OpenClaw如何命令Cursor做事,利用Cursor会员模型
  • JUnit单元测试框架
  • 从零起步学习MySQL 第十六章:MySQL 分库分表的考量策略
  • GBase 8a数据库运维管理系统GDOM解析
  • 全网都在抢的「AI龙虾」大乱斗!4家神仙打架,普通人只能看馋
  • 用了三周ArkClaw,我说说真实感受
  • 校园小卖部web开发项目-1(SpringBoot3+Vue3)
  • 外卖跑腿系统如果没有调度算法,本质只是个下单工具