【免费下载链接】PgQue
PgQue – Zero-bloat Postgres queue built on top of on battle-proven Skype's PgQ. One SQL file to install, pg_cron to tick https://pgque.dev
PgQue 是一个零膨胀(zero-bloat)的 Postgres 事件队列:单个 SQL 文件安装,用pg_cron驱动 tick 心跳。膨胀问题被架构设计消除了,但队列监控一点都不能省——ticker 停摆、消费者卡死、死信堆积,都会让队列"静默失速"。本文带你接入 5 个必须告警的队列健康指标,并用 3 条只读 SQL 揪出卡住的消费者。
一、为什么 PgQue 仍需要监控:真正的风险点不是膨胀
大多数 Postgres 队列靠SKIP LOCKED+ 删行取任务,长跑之后死元组越堆越多、VACUUM 越追越累。PgQue 的热路径从不删行,而是靠TRUNCATE 轮转回收空间,所以事件表天然不膨胀——上图来自仓库的 xmin-horizon 基准实验(benchmark/xmin-horizon/),即使在长事务钉死 xmin 的极端场景下,PgQue 的死元组依然是 0。
但轮转有一个前提:只有所有消费者都读过去之后,那张子表才能被 TRUNCATE。一个停掉的消费者会把最旧的 tick 钉死,轮转被无限跳过,事件表从此无限增长。换句话说:
保护磁盘的不是磁盘告警,而是消费者健康告警。
还有一条铁律:ticker 停摆 = 没有 tick = 没有批次 = 永远收不到消息(receive永远返回 0 行)。这也是监控的第一优先级。名词解释见 docs/concepts.md。
二、只读监控角色 + 4 个观察函数
PgQue 内置了一组只读观察函数,全部授权给pgque_reader角色——监控账号不需要任何写权限:
-- 给监控账号只读角色即可,安全无副作用 grant pgque_reader to metrics;| 函数 | 回答的问题 |
|---|---|
pgque.get_queue_info() | 队列还在流动吗?ticker 停了吗? |
pgque.get_consumer_info() | 每个消费者跟得上吗?谁卡住了? |
pgque.get_batch_info(batch_id) | 某个"在途"批次卡在哪一步? |
pgque.status() | ticker / 维护任务调度好了吗?(仅 admin) |
完整的列说明与全部只读查询见官方文档 docs/monitoring.md。
三、5 个必须告警的队列健康指标
| # | 指标 | 来源 | 告警条件 | 后果 |
|---|---|---|---|---|
| 1 | Ticker 心跳 | get_queue_info().ticker_lag | 持续超过ticker_idle_period(默认 1 分钟) | 不产生批次,消息永不投递 |
| 2 | 消费者延迟 | get_consumer_info().lag/pending_events | 多个采样周期持续增长 | 追不上实时流量,积压扩大 |
| 3 | 卡住的消费者 | last_seen增长 +last_tick冻结 | 队列last_tick_id在推进而它不动 | 钉死最旧 tick,阻塞 TRUNCATE,磁盘无限增长 |
| 4 | 死信队列深度 | pgque.dead_letter行数 | 持续增长,或"期望为 0"时非零 | 下游反复失败,重试耗尽 |
| 5 | 表轮转健康 | queue_switch_time | 长期不推进 | 旧子表无法 TRUNCATE,存储只增不减 |
指标 1:Ticker 心跳(ticker_lag)
PgQue 默认每 100 ms 打一个 tick;空闲队列至少每ticker_idle_period(默认 1 分钟)也会打一个。所以ticker_lag 持续爬过 1 分钟,基本就是 ticker 死了。第一步先查pgque.status(),确认 ticker 与 maintenance 任务是否还在调度——这是所有故障排查的第一问。
指标 2:消费者延迟(lag 与 pending_events)
健康系统里lag和last_seen都保持低位、pending_events接近 0。一旦持续上涨,先问一个问题:是"太慢",还是"死了"?
如果是"太慢"(消费者还活着、只是并行度不够),加消费者即可把积压排空:
指标 3:卡住的消费者(最危险)
它的签名很明确:last_seen持续增长,但last_tick纹丝不动,而队列的last_tick_id在正常推进,通常还伴随pending_events上涨。崩溃、死锁、部署事故都会造成这种状态——而且它不会自愈,必须人工介入。下一节专门讲怎么揪出来。
指标 4:死信队列深度(DLQ depth)
消息重试耗尽(默认 5 次)后会落进pgque.dead_letter。死信堆积 = 下游在反复失败:
select dl_queue_id, count(*) as dlq_depth from pgque.dead_letter group by dl_queue_id order by dlq_depth desc;非零本身不一定是故障(可能只是偶发),但增长趋势必须告警。定位原因用pgque.dlq_inspect('orders', 20)看最近 20 条的dl_reason即可。
指标 5:表轮转健康(queue_switch_time)
get_queue_info()里的queue_switch_time是上次轮转的时间。它长期不推进(尤其是指标 3 触发时),说明旧子表还被某个慢消费者钉着——存储只增不减,这是磁盘告警的真正前兆。
四、实战:三步揪出卡住的消费者
第 1 步:全局扫描,按"落后 tick 数"排序。把消费者位置和队列最新 tick 连起来看,冻结的last_tick会立刻暴露:
select c.queue_name, c.consumer_name, c.last_seen, c.last_tick, q.last_tick_id, q.last_tick_id - c.last_tick as ticks_behind, c.pending_events from pgque.get_consumer_info() c join pgque.get_queue_info() q using (queue_name) order by ticks_behind desc nulls last;ticks_behind持续上涨的那一行,就是嫌疑人。
第 2 步:检查"在途"批次。若嫌疑消费者的current_batch长期非 NULL(有批次一直没 ack),用pgque.get_batch_info(batch_id)看它的lag和seq_end - seq_start——批次活了多久、覆盖多大事件跨度。
第 3 步:处置。能救就修复消费者进程、观察last_tick恢复推进;救不活就退订,让轮转恢复:
select pgque.unsubscribe('orders', 'dead_consumer');注意:不打算重启的死消费者必须退订,否则它会永远钉住这个队列的存储。
进阶玩法:实验性的 devel/sql/experimental/observability.sql 提供了stuck_consumers(threshold)(按阈值直接列出卡住的消费者)、queue_health()(一键体检表)和otel_metrics()(OTel 指标导出),接 Prometheus/Grafana 前建议先通读一遍源码。
五、监控接入清单
- 建一个只读
metrics角色,grant pgque_reader——零写权限; - 把上面 5 个指标接进采样器(10~30 秒一次),按趋势告警,不按单点——PgQue 不内置 SLA,绝对阈值按自己的 tick 速率和流量调;
- 第一优先级永远是
pgque.status():ticker 没跑,其他指标全归零; - 想深入调 tick 周期与延迟的关系,看 docs/latency-and-tuning.md;全部函数签名查 docs/reference.md。
一句话总结:PgQue 让膨胀不再是你的问题,但"消费者活着吗、ticker 在跳吗"这两件事,必须靠你的告警来回答。
【免费下载链接】PgQue
PgQue – Zero-bloat Postgres queue built on top of on battle-proven Skype's PgQ. One SQL file to install, pg_cron to tick https://pgque.dev
相关推荐
5分钟掌握Apache Kafka 3.1消费者健康监控:从Lag指标到活跃度告警全方案
5分钟掌握Apache Kafka 3.1消费者健康监控:从Lag指标到活跃度告警全方案 Apache Kafka 3.1作为高性能分布式消息系统,消费者健康监
消息队列流处理数据集成存储igel社区贡献指南:如何参与开源机器学习项目开发
igel社区贡献指南:如何参与开源机器学习项目开发 igel是一款令人愉悦的机器学习工具,无需编写代码即可训练、测试和使用模型。作为开源项目,igel欢迎所有开
终极Flow监控告警指南:10个必备的类型检查服务健康监控方案
终极Flow监控告警指南:10个必备的类型检查服务健康监控方案 Flow作为JavaScript的静态类型检查工具,能显著提升开发效率和代码质量。本文将分享10
开发工具静态分析代码质量
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考