在现代分布式系统中,消息队列(Message Queue)扮演着至关重要的角色。作为一名经验丰富的开发者,我在工作中深度使用过 RabbitMQ、Kafka 等主流消息中间件,它们各自有着独特的优势和适用场景。然而,对于许多中小型项目来说,引入这些重量级中间件可能带来额外的复杂性和运维成本。
最近,我发现了一个基于 PostgreSQL 的消息队列插件——pgmq,以及围绕它构建的 Spring Boot 集成项目 pgsql-ext-spring。这个组合为小规模、轻量级的消息队列需求提供了一个优雅的解决方案。
一、pgmq 与其他 MQ 的对比分析
1.1 传统消息中间件的优势与不足
RabbitMQ:
- 优势:成熟的 AMQP 协议支持,丰富的 Exchange 类型,强大的路由能力
- 不足:需要单独的 Erlang 运行时环境,集群配置相对复杂
Kafka:
- 优势:极高的吞吐量,支持海量数据流处理,完善的生态
- 不足:配置复杂,资源消耗较大,延迟相对较高
1.2 Kafka 与 pgmq 对比表格
| 特性 | Kafka | pgmq |
|---|---|---|
| 架构类型 | 独立的分布式消息系统 | PostgreSQL 扩展插件 |
| 性能 | 极高吞吐量(百万级/秒) | 中等吞吐量(万级/秒) |
| 延迟 | 毫秒级 | 毫秒到秒级 |
| 消息持久化 | 基于磁盘,可配置保留时间 | 基于数据库表,可长期存储 |
| 事务支持 | 有限的事务支持 | 完整的 PostgreSQL ACID 事务 |
| 适用场景 | 大数据流处理,高吞吐量场景 | 中小型应用,强一致性要求场景 |
1.2 pgmq 的定位与特点
pgmq 是 PostgreSQL 的一个扩展插件,它将队列功能直接集成到数据库中:
优势:
- 零中间件依赖:无需部署额外的消息中间件服务
- 强一致性保证:利用 PostgreSQL 的 ACID 特性,确保消息的可靠性
- 简化架构:对于已经使用 PostgreSQL 的项目,无需引入新的技术栈
- 运维简单:队列数据与业务数据统一管理,监控方便
不足与适用场景:
- 性能限制:相比 Kafka、RocketMQ 等专用消息中间件,吞吐量有限
- 功能相对基础:缺少复杂路由、消息追踪等高级特性
- 最佳适用场景:
- 中小型项目,日处理消息量在百万级以下
- 对消息可靠性要求较高的场景
- 希望简化技术栈,减少运维成本的团队
- 已在使用 PostgreSQL,希望避免引入新中间件的项目
二、为什么选择 pgmq?
2.1 原子性优势
pgmq 最大的优势在于其与 PostgreSQL 的深度集成带来的原子性保证:
-- pgmq 操作与业务操作可以在同一个事务中
BEGIN;
-- 业务操作
INSERT INTO orders (id, amount) VALUES (1, 100.00);
-- 发送消息
SELECT pgmq.send('order_created', jsonb_build_object('order_id', 1, 'amount', 100.00));
COMMIT;
这种原子性保证了业务操作与消息发送要么同时成功,要么同时失败,避免了分布式事务的复杂性。
2.2 轻量化部署
对于小项目来说,pgmq 的轻量化特性极具吸引力:
- 零额外部署:无需安装和配置额外的消息中间件
- 学习成本低:开发者只需了解基本的 SQL 操作
- 资源消耗小:共享 PostgreSQL 的资源,无需为消息队列单独分配资源
- 监控统一:队列指标可以通过 PostgreSQL 的监控系统统一采集
三、pgsql-ext-spring 项目的优势
pgsql-ext-spring 是一个基于 Spring Boot 4 和 JDK 21+ 的 pgmq 集成框架,它让使用 pgmq 变得更加简单和高效。
3.1 注解式开发,类似 RabbitMQ/Kafka
与 RabbitMQ 的 @RabbitListener 和 Kafka 的 @KafkaListener 类似,pgsql-ext-spring 提供了简洁的 @PgmqListener 注解来声明消息处理器。开发者只需在方法上添加相应注解,即可实现消息的自动监听和处理。具体的使用方法和代码示例请参考项目 README:github.com/super-npc/p…
3.2 虚拟线程支持
项目采用 JDK 21+ 的虚拟线程(Virtual Threads)技术,大幅提升了并发处理能力。以下是使用虚拟线程实现的监听逻辑:
3.3 自动表管理
项目会自动创建和管理 pgmq 所需的表结构,无需手动执行 SQL 脚本。
四、UI 管理界面
pgsql-ext-spring 提供了一个简洁的 Web UI 界面,方便开发者管理队列:
4.1 队列查看与管理
- 查看已有队列:通过动态表名技术展示所有已创建的队列
- 队列状态监控:
- 待处理消息数量
- 已处理消息数量
- 处理失败消息数量
- 消息处理延迟统计
4.2 队列操作
-
创建队列:
- 普通队列:基础的消息队列
- 延迟队列:支持延迟投递的消息队列
- 日志队列:专门用于日志收集的队列
- 死信队列:处理失败消息的队列
-
队列归档:
- 自动归档已处理的消息
- 可配置的归档策略(按时间、按数量)
- 归档数据查询和导出
-
消息操作:
- 查看队列中的消息内容
- 手动重试失败的消息
- 删除无效消息
- 批量操作支持
五、监听模式与使用示例
pgsql-ext-spring 目前支持两种监听模式:
5.1 轮询模式(Polling Mode)
这是最基础的监听模式,通过定时轮询数据库表来获取新消息。适用于对实时性要求不高的场景。
5.2 通知模式(Notify Mode)
利用 PostgreSQL 的 LISTEN/NOTIFY 机制,实现实时消息推送。当有新消息到达时,PostgreSQL 会主动通知应用程序,减少轮询开销。
5.3 使用说明
项目采用 JDK 21+ 的虚拟线程(Virtual Threads)技术,大幅提升了并发处理能力。具体的使用方法和代码示例请参考项目 README:github.com/super-npc/p…
六、一键 Docker 部署
pgsql-ext-spring 提供了完整的 Docker Compose 配置,可以快速搭建开发环境:
services:
redis:
restart: always
image: redis
ports:
- 6379:6379
networks:
- npc_net
postgres:
image: supernpc/pgsql:18
networks:
- npc_net
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: root
ports:
- 5432:5432
pgsql-ext-admin:
image: supernpc/pgsql-ext-admin:latest
container_name: pgsql-ext-admin
networks:
- npc_net
environment:
- TZ=Asia/Shanghai
- spring.profiles.active=prd
- feign.secret=123456 # 如果未使用微服务调用,固定默认值123456即可
- password=123456 # 有使用加密功能,参考Jasypt实现
ports:
- 9019:9019
networks:
npc_net:
external: true
部署步骤:
- 克隆项目:
git clone https://github.com/super-npc/pgsql-ext-spring.git
cd pgsql-ext-spring
- 启动服务:
docker-compose up -d
-
访问服务:
-
查看日志:
docker-compose logs -f pgmq-ext-spring
七、总结
pgmq 结合 pgsql-ext-spring 项目,为中小型项目提供了一个简单、可靠、易用的消息队列解决方案。它特别适合以下场景:
- 技术栈简化:对于已经使用 PostgreSQL 的项目,避免引入新的中间件
- 强一致性要求:需要保证业务操作与消息发送原子性的场景
- 运维成本敏感:希望降低系统复杂性和运维负担的团队
- 快速原型开发:需要快速搭建消息队列功能的开发阶段
虽然 pgmq 在性能上无法与 Kafka、RocketMQ 等专用中间件相比,但对于大多数中小型应用来说,它的性能已经完全足够。更重要的是,它带来的架构简化和运维便利是其他方案难以比拟的。
pgsql-ext-spring 项目的注解式开发模式和虚拟线程支持,让开发者能够以极低的成本享受到类似 RabbitMQ/Kafka 的开发体验。对于追求简洁、高效的团队来说,这无疑是一个值得尝试的选择。
适用建议:
- 日消息量 < 100 万:pgmq 是最佳选择
- 100 万 < 日消息量 < 1000 万:可以尝试 pgmq,根据实际性能测试决定
- 日消息量 > 1000 万:建议使用专业消息中间件
在技术选型时,我们应该避免"为了用而用"的思维,选择最适合当前业务规模和技术团队能力的方案。pgmq 正是这种务实思维的产物,它为消息队列领域提供了一个新的、有价值的选项。