PGMQ:基于PostgreSQL的轻量级消息队列
1. 概述
PGMQ是一个基于PostgreSQL实现的轻量级消息队列工具,提供类似AWS SQS或RSMQ(Redis Simple Message Queue)的接口和功能。它完全使用SQL语句实现,作为一个PostgreSQL扩展插件运行。
项目地址:https://github.com/pgmq/pgmq
2. 核心特性
| 特性 | 描述 |
|---|---|
| 轻量级 | 无需后台工作进程或外部组件依赖,仅需安装PostgreSQL扩展插件,支持PostgreSQL 14+ |
| 可靠性 | 确保在可见性超时之内精确传递一次消息到消费者 |
| API兼容 | 兼容AWS SQS及RSMQ消息队列API |
| FIFO原则 | 遵循先进先出原则,支持消息分组和顺序处理 |
| 分区队列 | 通过集成pg_partman插件按时间或ID自动分表存储消息,支持冷数据自动淘汰 |
| 性能优化 | 支持创建非日志表(create_unlogged)提升处理速度,但系统崩溃时可能丢失数据 |
| 消息持久化 | 消息可一直存储在队列中,直到明确删除 |
| 消息重放 | 支持消息归档,用于长期保留和重放 |
3. 安装部署
Docker快速体验
bash
docker run -d --name pgmq-postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
ghcr.io/pgmq/pg18-pgmq:v1.10.0
连接PostgreSQL
bash
psql postgres://postgres:postgres@0.0.0.0:5432/postgres
创建扩展
sql
-- 在pgmq模式中创建扩展
CREATE EXTENSION pgmq;
4. 使用示例
4.1 创建消息队列
sql
-- 创建名为my_queue的消息队列
SELECT pgmq.create('my_queue');
每个消息队列对应pgmq模式下的一个表,命名规则:pgmq.q_ + 队列名。上述命令会创建表 pgmq.q_my_queue。
4.2 发送消息
普通发送
sql
-- 消息内容使用JSON格式
SELECT * from pgmq.send(
queue_name => 'my_queue',
msg => '{"foo": "bar1"}'
);
-- 返回消息编号
延迟发送
sql
-- 延迟5秒后消息才对消费者可见
SELECT * from pgmq.send(
queue_name => 'my_queue',
msg => '{"foo": "bar2"}',
delay => 5 -- 延迟秒数
);
4.3 读取消息
sql
SELECT * FROM pgmq.read(
queue_name => 'my_queue',
vt => 30, -- 可见性超时(秒)
qty => 2 -- 读取数量
);
返回字段说明:
msg_id: 消息IDread_ct: 已读取次数enqueued_at: 入队时间last_read_at: 最后读取时间vt: 可见性超时时间message: 消息内容(JSON)headers: 消息头
可见性超时机制:读取的消息在vt秒内对其他消费者不可见,若未被删除或归档,超时后重新可见。
4.4 弹出消息
sql
-- 读取并立即删除消息
SELECT * FROM pgmq.pop('my_queue');
-- 队列为空或所有消息不可见时返回空记录
4.5 归档消息
sql
-- 归档消息(从队列删除并存入归档表)
SELECT pgmq.archive(
queue_name => 'my_queue',
msg_id => 2
);
归档表命名规则:pgmq.a_ + 队列名(如 pgmq.a_my_queue)
4.6 删除消息
sql
-- 直接从队列删除消息
SELECT pgmq.delete('my_queue', 2);
4.7 删除消息队列
sql
-- 删除整个队列
SELECT pgmq.drop_queue('my_queue');
5. 客户端驱动支持
官方驱动
- Rust
- Python
社区驱动
- Dart
- Go
- Elixir
- Java
- Kotlin
- JavaScript
- .NET
- Ruby
- PHP
6. 适用场景
- 微服务通信:轻量级服务间异步消息传递
- 任务队列:后台任务处理
- 事件驱动架构:事件发布与订阅
- 数据管道:可靠的数据传输通道
- 日志处理:消息归档与重放
7. 注意事项
- 性能优化 :使用
create_unlogged可提升性能,但系统崩溃时可能丢失数据 - 消息清理:消息不会自动删除,需要显式调用delete/archive
- 可见性管理:合理设置vt值避免消息处理超时导致重复消费
- 分区管理:大数据量场景建议启用pg_partman分区