15分钟搭建Postgres实时CDC同步管道
告别轮询与沉重CDC框架,本文教你用纯SQL和PeerDB,快速搭建Postgres到ClickHouse的实时数据同步管道。从零部署、配置Peer/Mirror到状态监控与排障,完整掌握实战流程。

上个月帮同行排查数据中台问题,他们用 Python 写了定时脚本,每分钟轮询 Postgres 的 updated_at 字段,把变更拉到 ClickHouse。网络抖动后,脚本直接拉了一百万条重复数据,下游报表全花了。
「Postgres 同步到外部系统」的场景很常见。传统做法通常有两类痛点:
- 定时轮询 SELECT:延迟高、给源库带来查询压力、需手动处理漏数据与重复数据边界。
- 基于 WAL/Binlog 的 CDC 框架:Debezium、Canal 等能力强大,但组件繁多、配置重、运维成本高。搭一套 Kafka Connect + Zookeeper + Debezium 的门槛不低。
如果仅需要同步 Postgres,PeerDB 提供了更轻量的解法:专注于把 Postgres 的 WAL 变更实时推送到各类目标端。最大亮点在于,全程使用 SQL 完成 ETL 配置与监控,无需学习新 DSL 或维护复杂 YAML。
本文将带你从零部署 PeerDB,用纯 SQL 跑通一条 Postgres → ClickHouse 的实时同步链路。你只需要 Docker 和 psql 客户端。
前置条件
- Docker + Docker Compose:本地部署依赖容器栈(Catalog、Temporal 调度引擎、PeerDB 服务、UI 等)。
- psql >= 14.0:通过标准 Postgres 协议连接 PeerDB 执行指令。
- 熟悉 Postgres 基础 SQL,了解 WAL / Logical Replication 概念即可。
为什么用 psql? PeerDB 暴露了兼容 Postgres Wire Protocol 的接口(默认 9900 端口)。你可以把它当作普通 Postgres 数据库连接,pgAdmin、DBeaver、JDBC 均可。本文使用 psql 保持轻量。
快速上手:启动 PeerDB 服务
官方提供了一键启动脚本,拉取仓库执行即可拉起全部容器。
bash
git clone git@github.com:PeerDB-io/peerdb.git
cd peerdb
bash ./run-peerdb.sh
启动后 docker-compose 会拉起多个容器,核心组件职责如下:
- Postgres (catalog):存储 PeerDB 元数据,如 Mirror 定义、Peer 连接配置等。
- Temporal:工作流引擎,负责任务调度、状态流转与重试管理。
- PeerDB server & workers:同步核心,读取源端 WAL 并写入目标端。
- PeerDB UI:可选的可视化管理面板。
等待 1-2 分钟容器就绪后,使用 psql 连接:
bash
psql "port=9900 host=localhost password=peerdb"
出现 peerdb=> 提示符即连接成功。注意:连接的是 PeerDB 控制面,而非业务数据库。后续所有数据源注册与同步任务创建都在这里执行。
实战:搭建 Postgres→ClickHouse 实时同步
假设你有一个订单库 orders_db,需实时同步到 ClickHouse 供分析查询。完整流程分为三步:注册源端 Peer、注册目标端 Peer、创建 Mirror 启动同步。
1. 注册 Postgres 数据源
PeerDB 使用 CREATE PEER 语句抽象所有外部连接。
sql
CREATE PEER my_source_pg FROM postgres (
host = 'host.docker.internal',
port = '5432',
user = 'postgres',
password = 'your_password',
database = 'orders_db'
);
Peer 抽象层让连接管理解耦。后续切换目标端(如 ClickHouse 换 Snowflake),只需修改目标 Peer 定义,Mirror 配置基本无需改动。
创建成功后,可用以下 SQL 验证连通性:
sql
SELECT peerdb_catalog.list_tables('my_source_pg', 'public');
该命令会列出源库 public schema 下的全部表名。
2. 注册 ClickHouse 目标端
假设 ClickHouse 已就绪,创建目标 Peer:
sql
CREATE PEER my_ch_clickhouse FROM clickhouse (
host = 'host.docker.internal',
port = '8123',
user = 'default',
password = ''
);
踩坑提醒:若 ClickHouse 部署在宿主机而非 Docker 网络内,PeerDB 内部依赖 MinIO 做临时文件中转。务必确保 ClickHouse 能访问 MinIO 地址。在
docker-compose.yml中将AWS_ENDPOINT_URL_S3改为两端可达的 IP。同步报连接超时通常源于此配置错误。
3. 创建并启动 Mirror
Mirror 即「同步任务」定义。指定源表、目标端及同步策略。
sql
CREATE MIRROR my_order_mirror FROM my_source_pg TO my_ch_clickhouse
FOR TABLES (
public.orders,
public.order_items
)
WITH (
mode = 'cdc',
initial_load = true,
resync = false
);
关键参数说明:
mode = 'cdc':基于 WAL 的日志同步,延迟最低,适合实时场景。PeerDB 同时支持 cursor-based 与 XMIN 模式。initial_load = true:首次同步执行全量历史数据加载。若目标端已有存量数据仅需追增量,改为false。resync = false:是否重置并重新同步。历史任务失败需重来时可开启。
执行后,PeerDB 自动开始全量加载,完成后无缝切换至 CDC 增量模式,实时消费 WAL 变更推送至目标端。
4. 监控同步状态
无需翻找容器日志,直接通过 SQL 查询运行状态:
sql
-- 查看所有 Mirror 概要
SELECT name, status, source_peer, destination_peer FROM peerdb_catalog.mirrors;
-- 查看具体 Mirror 进度(全量阶段显示百分比)
SELECT * FROM peerdb_catalog.mirror_status('my_order_mirror');
-- 排查异常
SELECT * FROM peerdb_catalog.mirror_errors('my_order_mirror') ORDER BY created_at DESC LIMIT 10;
status 显示 active 代表同步正常运行。在源库执行 INSERT / UPDATE 后,查询 ClickHouse 验证数据实时到达即可。
常见问题与排障
- psql 连接失败:执行
docker ps确认所有容器处于healthy状态。PeerDB 启动需 1-2 分钟,请耐心等待。 - 同步延迟飙升:CDC 延迟通常在几十秒内。若持续恶化,检查源库复制槽堆积情况(
SELECT * FROM pg_replication_slots)。Slot 堆积说明消费端处理速度跟不上 WAL 产出速度。 - 大字段(TOAST)同步慢:PeerDB 针对 TOAST 列有内部优化。若单行包含数十 MB 的 JSONB/TEXT,建议评估同步必要性。Mirror 支持列级过滤,可排除大字段。
- 网络隔离 MinIO 报错:前文已说明,确保
AWS_ENDPOINT_URL_S3配置为容器外部可访问的地址,避免目标端无法拉取 staging 数据。
小结
本文完成了 PeerDB 环境部署,并用纯 SQL 跑通 Postgres → ClickHouse 实时 CDC 管道。核心链路就三步:CREATE PEER 注册连接、CREATE MIRROR 定义任务、SQL 查询监控。无需额外配置文件或复杂框架 API,对 Postgres-first 团队非常友好。
后续可探索方向:
- 无 WAL 权限场景下的 cursor-based 同步模式
- Schema evolution 自动适配源表结构变更
- 结合 Airflow 或 cron 自动化 Mirror 生命周期管理
- 官方文档中关于初始加载性能调优的参数配置
花 15 分钟跑通一次,亲身体验用 SQL 管理 ETL 的流畅度。遇到问题可前往 PeerDB 官方 Slack 社区,社区响应较为活跃。