惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
T
Threat Research - Cisco Blogs
量子位
Last Week in AI
Last Week in AI
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
爱范儿
爱范儿
D
Docker
人人都是产品经理
人人都是产品经理
S
SegmentFault 最新的问题
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
A
About on SuperTechFans
P
Proofpoint News Feed
博客园 - 司徒正美
Recent Announcements
Recent Announcements
I
InfoQ
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
Webroot Blog
Webroot Blog
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
SecWiki News
SecWiki News
Attack and Defense Labs
Attack and Defense Labs
Hacker News: Ask HN
Hacker News: Ask HN
AI
AI
博客园_首页
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recorded Future
Recorded Future
T
Tailwind CSS Blog
MyScale Blog
MyScale Blog
T
Tenable Blog
宝玉的分享
宝玉的分享
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
C
Check Point Blog
S
Security Affairs
L
LINUX DO - 最新话题
大猫的无限游戏
大猫的无限游戏
Scott Helme
Scott Helme
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
月光博客
月光博客
Y
Y Combinator Blog

博客园 - MK2

cnpmcore 超大 JSON parse 性能优化 Graceful exit with cluster and pm Use Blanket.js instead of jscover 使用 connect-domain 捕获异步调用中出现的异常 Defense hash algorithm collision 防御hash算法冲突导致拒绝服务器 fibonacci(40) benchmark [nodejs]保证你的程序死了还能复活:forever and forever webui [nodejs]Buffer vs String Nodejs "Hello world" benchmark npm 资源库镜像 NodeBlog v0.2.0 更新说明 关于__proto__的链式记忆 NAE支持自定义域名了 Nodejs 离线文档下载 nodejs读写大文件 Nodejs HTTP请求的超时处理(Nodejs HTTP Client Request Timeout Handle) 在jQuery 1.5+ 的jqXHR上监听文件上传进度(xhr.upload) 关于Nodejs中Buffer释放的二三事 nodejs web开发入门: Simple-TODO Nodejs 实现版
基于 Postgres 实现一个 Job Queue
MK2 · 2025-06-20 · via 博客园 - MK2

今天看到一篇赞美 Postgres 的文章:Postgres is Too Good (And Why That's Actually a Problem) ,显然是非常吸引眼球的,作者用 PG 实现了需要用到的所有微服务。

做 AFFiNE 我们是用 Redis 的 pub/sub 实现的 Job Queue,所以想参考一下用 Postgres 实现对比看看。

直接问 ChatGPT 怎样实现

基于 Postgres 的 LISTEN/NOTIFY 实现任务队列服务

https://chatgpt.com/share/685527b8-724c-8010-9e5a-1aac521a7acc

表结构

init.sql

CREATE TABLE tasks (
  "id" SERIAL PRIMARY KEY,
  "type" TEXT NOT NULL,
  "payload" JSONB,
  "status" TEXT NOT NULL DEFAULT 'pending',
  "created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "updated_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "processed_at" TIMESTAMPTZ(3)
);

Job Queue 基本操作

添加任务并广播通知

INSERT INTO tasks (type, payload) VALUES ('send_email', '{"to": "test@example.com"}');

NOTIFY task_queue, 'new_task';

监听任务消息并拉取任务

监听任务消息

await jobListener.query('LISTEN task_queue');

jobListener.on('notification', async (msg) => {
  if (msg.channel === 'task_queue') {
    // 在这里拉取任务
  }
});

拉取任务 SQL

UPDATE tasks
SET status = 'processing', processed_at = NOW(), updated_at = NOW()
WHERE id = (
  SELECT id FROM tasks WHERE status = 'pending'
  ORDER BY created_at ASC LIMIT 1
  FOR UPDATE SKIP LOCKED
)
RETURNING *;

可运行的代码

先启动一个 Postgres 测试服务

docker run --name pg-container-job-queue-demo \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=test123123 \
  -e POSTGRES_DB=mydb \
  -v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql \
  -p 5432:5432 \
  -d postgres:16

启动 demo.ts 代码,每 5 秒触发一个任务,并打印结果

node demo.ts

完整代码

请移步 https://github.com/fengmk2/fengmk2.github.com/tree/master/blog/2025/job-queue-on-postgres

有爱

希望本文对你有用 _

原始文章地址:https://fengmk2.com/blog/2025/job-queue-on-postgres/README.html