PGMQ 是一个基于 PostgreSQL 实现的轻量级消息队列工具,可以实现类似 AWS SQS 或者 RSMQ(Redis Simple Message Queue)的接口和功能。

PGMQ 完全使用 SQL 语句实现,遵循 PostgreSQL 开源协议,代码托管在 GitHub:
功能特性
- 轻量级:PGMQ 不需要后台工作进程或者外部组件依赖,只需要安装一个 PostgreSQL 扩展插件,支持 PostgreSQL 14+。
- 可靠性:PGMQ 能够确保在可见性超时之内精确传递一次消息到消费者。
- API:兼容 AWS SQS 以及 RSMQ 消息队列 API。
- FIFO:遵循 FIFO 原则(First-In-First-Out),支持消息分组和顺序处理。
- 分区队列:通过集成 pg_partman 插件按照时间或者 ID 自动分表存储消息,冷数据可以自动淘汰。
- 性能提升:通过创建非日志表(create_unlogged)可以极大地提高消息队列处理时间,但是可能在系统崩溃时丢失队列数据。
- 显式删除:消息可以一直存储在队列中,直到明确删除为止。
- 消息重放:消息可以被归档,用于长期保留和重放。
- 客户端驱动:官方提供 Rust、Python 驱动,社区提供 Dart、Go、Elixir、Java、Kotlin、JavaScript、.NET、Ruby、PHP 等语言驱动。
下载安装
推荐使用 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
# Connect to Postgres
psql postgres://postgres:postgres@0.0.0.0:5432/postgres
-- create the extension in the "pgmq" schema
CREATE EXTENSION pgmq;
使用示例
创建消息队列
PGMQ 对于消息队列的所有操作都使用 SQL 语句完成,以下语句可以创建一个名为 my_queue 的消息队列:
sql
-- creates the queue
SELECT pgmq.create('my_queue');
create
-------------
(1 row)
每个消息队列都对应 pgmq 模式下的一个表,表的命名规则为 q_ 前缀加上消息队列名。以上语句创建的消息队列表名为 pgmq.q_my_queue。
发送消息
接下来我们给这个消息队列发送一个消息:
sql
-- messages are sent as JSON
SELECT * from pgmq.send(
queue_name => 'my_queue',
msg => '{"foo": "bar1"}'
);
send
-----------
1
(1 row)
消息内容使用 JSON 格式,查询返回的是消息编号。
发送消息时还可以指定一个延迟时间(秒数或者时间戳),在此之前该消息对消费者不可见。
sql
-- Optionally provide a delay
-- this message will be on the queue but unable to be consumed for 5 seconds
SELECT * from pgmq.send(
queue_name => 'my_queue',
msg => '{"foo": "bar2"}',
delay => 5
);
send
-----------
2
(1 row)
读取消息
消费者可以读取队列中的消息:
sql
SELECT * FROM pgmq.read(
queue_name => 'my_queue',
vt => 30,
qty => 2
);
msg_id | read_ct | enqueued_at | last_read_at | vt | message | headers
--------+---------+-------------------------------+-------------------------------+-------------------------------+-----------------+---------
1 | 1 | 2026-01-23 20:27:21.7741-06 | 2026-01-23 20:27:31.605236-06 | 2026-01-23 20:28:01.605236-06 | {"foo": "bar1"} |
2 | 1 | 2026-01-23 20:27:26.505063-06 | 2026-01-23 20:27:31.605252-06 | 2026-01-23 20:28:01.605252-06 | {"foo": "bar2"} |
以上查询读取了 2 条消息,并且使其在接下来的 30 秒内不可见。如果这些消息在 30 秒内不被删除或者归档,将会重新可见并且可以被其他消费者读取。
弹出消息
弹出(POP)表示消费者读取消息之后立即从队列中删除相应的消息:
sql
-- Read a message and immediately delete it from the queue. Returns an empty record if the queue is empty or all messages are invisible.
SELECT * FROM pgmq.pop('my_queue');
msg_id | read_ct | enqueued_at | last_read_at | vt | message | headers
--------+---------+-----------------------------+-------------------------------+-------------------------------+-----------------+---------
1 | 1 | 2026-01-23 20:27:21.7741-06 | 2026-01-23 20:27:31.605236-06 | 2026-01-23 20:28:01.605236-06 | {"foo": "bar1"} |
归档消息
归档消息意味着从队列中删除消息,并且将其插入归档表中:
sql
-- Archive message with msg_id=2.
SELECT pgmq.archive(
queue_name => 'my_queue',
msg_id => 2
);
archive
--------------
t
(1 row)
消息队列 my_queue 对应的归档表为 pgmq.a_my_queue。
删除消息
使用 pgmq.delete 函数从队列中删除消息:
sql
SELECT pgmq.delete('my_queue', 2);
delete
-------------
t
(1 row)
删除消息队列
使用以下语句删除消息队列 my_queue:
sql
SELECT pgmq.drop_queue('my_queue');
drop_queue
-----------------
t
(1 row)
更多接口可以参考文档:https://pgmq.github.io/pgmq/latest/