Postgres ListenNotify如何构建轻量级发布订阅系统?
摘要:概述 原先设计一个内部系统的消息模块和缓存模块时,只有一个Postgres依赖。想着没多大用户量,没必要额外安装Redis,徒增运维工夫。缓存好解决,配个UNLOGGED表即可。吭吭哧哧琢磨怎么用数据表实现消息的时候,发现PostgreSQ
概述
原先设计一个内部系统的消息模块和缓存模块时,只有一个Postgres依赖。想着没多大用户量,没必要额外安装Redis,徒增运维工夫。缓存好解决,配个UNLOGGED表即可。吭吭哧哧琢磨怎么用数据表实现消息的时候,发现PostgreSQL 提供了内置命令 LISTEN 和 NOTIFY,用于在数据库服务器和连接的客户端之间实现异步通信。这个 PostgreSQL 特有的扩展功能使得数据库可以作为一个轻量级的消息队列(MQ)系统使用,允许应用程序从数据库中生成事件,并由其他客户端实时响应。于是一拍即合,上手体验一下。
核心特性
轻量级实现:无需额外的消息中间件,直接利用 PostgreSQL 内置功能
异步通信:支持发布-订阅模式,实现解耦的组件通信
内存高效:通道(Channel)是纯内存对象,不占用磁盘空间
零配置:无需预先创建或管理通道,随用随建
适用场景
实时仪表盘:数据变更时实时推送更新
缓存失效:数据更新时通知缓存层刷新
数据审计:跟踪重要数据变更事件
任务调度:构建简单的分布式任务队列
事件驱动架构:实现微服务间的事件通信
通道(Channel)机制
重要特性:
Channel 是纯内存对象,随 LISTEN 命令隐式创建
当所有监听会话断开或执行 UNLISTEN 时自动回收
无需手动创建或删除通道,也不支持此操作
消息传递模型
PostgreSQL 的 NOTIFY 采用典型的 "无监听即丢弃" 机制:
没有监听者时,消息不会入队
不占用磁盘空间
不消耗持久化内存
消息仅在存在活跃监听者时传递
基础使用
psql 命令行示例
-- 监听指定通道
LISTEN task_channel;
-- 向通道发送消息
NOTIFY task_channel, '123456';
-- 取消监听所有通道
UNLISTEN *;
-- 查看当前监听的通道
SELECT pg_listening_channels();
-- 查看系统通知状态
SELECT * FROM pg_stat_activity WHERE backend_type = 'client backend';
动态消息生成
标准的 NOTIFY 命令要求消息内容必须明确指定,不支持动态字符串拼接。
