想用队列?但我一个中间件都不想引入:PGMQ 超简单使用
你有没有这种精神洁癖:
想要“消息队列”的快乐,但不想再引入一个“队列中间件”来占内存、占运维、占你周末?
这时候,PGMQ 就像你家楼下那位“热心但不多话的快递柜”:
你把包裹(消息)放进去,它负责存着;你来取,它负责按规则给你。
不搞花活,不拉群,不开会——主打一个“我在 PostgreSQL 里把队列给你安排了”。
本文基于 PGMQ 的二开开源项目:
并且所有示例代码严格来自该项目 README:
你要的核心卖点:@PgMqListener 一把梭,两种消费模式
这套用法里,最爽的就是:你几乎不用写“队列消费框架代码”。
你只要用 @PgMqListener 标记方法,它就能让你在两种订阅模式里随便切换:
| 模式 | subscribeType | 一句话人话 |
|---|---|---|
| 广播模式 | BROADCASTING | 所有消费者都能收到同一条消息(像班级群发通知) |
| 集群模式 | CLUSTERING | 一条消息只会分配给一个消费者(像排队取号,谁叫到谁办) |
接下来我用“拟人比喻”给你讲清楚:
- 广播模式:消息像“八卦”,传出去后大家都得知道
- 集群模式:消息像“外卖订单”,只需要一个人去送,别来一堆骑手围观
广播模式:消息是“全员通知”,每个消费者都要读一遍
想象一下:你在公司群里发了一句“今晚团建自愿参加”。
然后两个同事(listener1、listener2)都看到了——这就是广播。
下面代码严格来自 README(原样照抄):
@Slf4j
@Component
@RequiredArgsConstructor
public class DemoBroadcastingHandler {
@PgMqListener(subscribeType = SubscribeType.BROADCASTING, bindMsgDto = DemoMsgDto.class)
public void listener1(DemoMsgDto msg) {
log.info("广播.listener1: {}", msg);
}
@PgMqListener(subscribeType = SubscribeType.BROADCASTING, bindMsgDto = DemoMsgDto.class)
public void listener2(DemoMsgDto msg) {
log.info("广播.listener2: {}", msg);
}
}
看点就三个字:都能收
- 同一个队列/同一类消息
- 两个方法都用
@PgMqListener订阅 subscribeType = SubscribeType.BROADCASTING
结果就是:两位“打工人消费者”都会处理到消息
集群模式:消息是“派单任务”,只要一个消费者处理就行
再想象一下:你点了份外卖。
平台派单时不会把同一单同时派给两个骑手,不然你会收到两份外卖,然后你钱包当场去世。
下面代码同样严格来自 README(原样照抄):
@Slf4j
@Component
@RequiredArgsConstructor
public class DemoClusteringHandler {
@PgMqListener(subscribeType = SubscribeType.CLUSTERING, bindMsgDto = DemoMsgDto.class)
public void listener1(DemoMsgDto msg) {
log.info("集群.listener1: {}", msg);
}
@PgMqListener(subscribeType = SubscribeType.CLUSTERING, bindMsgDto = DemoMsgDto.class)
public void listener2(DemoMsgDto msg) {
log.info("集群.listener2: {}", msg);
}
}
这段的精髓也很直白:只给一个人
- 两个消费者都在“候场”
- 但
subscribeType = SubscribeType.CLUSTERING会让消息只分配给其中一个
结果就是:不会重复消费(至少从模式设计上,就是奔着避免“群殴同一条消息”去的)
你可能会问:我到底该选哪个?
按“人类社会运作方式”来选就行:
-
选 BROADCASTING:像“发公告”
- 缓存更新通知
- 多系统都要同步处理的事件
- “大家都要知道”的消息
-
选 CLUSTERING:像“派工单”
- 发短信/发券这类“发一次就行”的任务
- 订单处理、异步任务
- “只要有人做完就行”的消息
(可选)配合 Postgres 镜像启用扩展:把“快递柜”先装上
如果你用的是 supernpc/pgsql:18 这种集成镜像,首次创建数据库需要手动启用扩展(同样来自 README):
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
CREATE EXTENSION IF NOT EXISTS postgis CASCADE;
CREATE EXTENSION IF NOT EXISTS postgis_topology CASCADE;
CREATE EXTENSION IF NOT EXISTS pg_cron;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS plpython3u;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pgmq;
总结:这套玩法为什么很适合懒人(我)
因为你想要的核心其实是:我能不能用最少的心智,把消息消费跑起来?
而这里的答案是:可以。
你只要记住一件事:@PgMqListener + subscribeType
BROADCASTING:消息像八卦,大家都要听到CLUSTERING:消息像派单,只给一个人干活
剩下的,就交给 PostgreSQL 和这套二开生态去忙。