PostgreSQL:Citus 分布式拓展,水平分片,支持海量数据与高并发

文章目录

    • [一、Citus 是什么?](#一、Citus 是什么?)
      • [1.1 定位与核心能力](#1.1 定位与核心能力)
      • [1.2 适用场景](#1.2 适用场景)
    • [二、Citus 架构原理](#二、Citus 架构原理)
      • [2.1 节点角色](#2.1 节点角色)
      • [2.2 数据分片(Sharding)机制](#2.2 数据分片(Sharding)机制)
      • [2.3 查询执行流程](#2.3 查询执行流程)
    • 三、安装与集群部署
      • [3.1 安装方式(以 Ubuntu 为例)](#3.1 安装方式(以 Ubuntu 为例))
      • [3.2 初始化集群(3 节点示例)](#3.2 初始化集群(3 节点示例))
        • [步骤 1:在所有节点安装 Citus + PostgreSQL](#步骤 1:在所有节点安装 Citus + PostgreSQL)
        • [步骤 2:在 Coordinator 上启用 Citus](#步骤 2:在 Coordinator 上启用 Citus)
        • [步骤 3:将 Worker 加入集群](#步骤 3:将 Worker 加入集群)
        • [步骤 4:验证集群状态](#步骤 4:验证集群状态)
    • 四、创建分布式表
      • [4.1 分布式表类型](#4.1 分布式表类型)
      • [4.2 创建分片表(Distributed Table)](#4.2 创建分片表(Distributed Table))
      • [4.3 创建参考表(Reference Table)](#4.3 创建参考表(Reference Table))
      • [4.4 分片策略选择建议](#4.4 分片策略选择建议)
    • [五、SQL 兼容性与查询能力](#五、SQL 兼容性与查询能力)
      • [5.1 完全支持的标准 SQL](#5.1 完全支持的标准 SQL)
      • [5.2 分布式查询示例](#5.2 分布式查询示例)
      • [5.3 事务与一致性](#5.3 事务与一致性)
    • 六、性能优化与调优
      • [6.1 分片数量(Shard Count)](#6.1 分片数量(Shard Count))
      • [6.2 写入优化](#6.2 写入优化)
      • [6.3 查询优化](#6.3 查询优化)
      • [6.4 资源隔离(企业版)](#6.4 资源隔离(企业版))
    • 七、运维与高可用
      • [7.1 扩容(Adding Nodes)](#7.1 扩容(Adding Nodes))
      • [7.2 高可用方案](#7.2 高可用方案)
        • [(1)Coordinator 高可用](#(1)Coordinator 高可用)
        • [(2)Worker 高可用](#(2)Worker 高可用)
      • [7.3 监控关键指标](#7.3 监控关键指标)
    • 八、与生态工具集成
    • 九、限制与注意事项
      • [9.1 功能限制(截至 Citus 12)](#9.1 功能限制(截至 Citus 12))
      • [9.2 性能陷阱](#9.2 性能陷阱)
    • 十、典型应用场景详解
      • [10.1 多租户 SaaS 平台](#10.1 多租户 SaaS 平台)
      • [10.2 实时用户行为分析](#10.2 实时用户行为分析)
      • [10.3 IoT 设备监控(与 TimescaleDB 结合)](#10.3 IoT 设备监控(与 TimescaleDB 结合))
    • [十一、Citus vs 其他分布式方案](#十一、Citus vs 其他分布式方案)

PostgreSQL 本身是一个功能强大、稳定可靠的关系型数据库,但在面对 海量数据(TB/PB 级)高并发写入/查询 场景时,单机架构会遇到性能瓶颈。为解决这一问题,Citus 应运而生------它是一个开源的 PostgreSQL 扩展,可将 PostgreSQL 集群化,实现 透明的水平分片(Sharding)分布式并行查询弹性扩展高可用支持,从而构建高性能、可扩展的分布式数据库系统。

学习资源:


一、Citus 是什么?

1.1 定位与核心能力

Citus 是一个 PostgreSQL 的分布式数据库扩展 ,由微软(Microsoft)维护(原为独立公司,2019 年被收购)。它通过在多个 PostgreSQL 节点上 自动分片数据 ,并 并行执行查询,实现:

  • 水平扩展:通过增加节点线性提升吞吐量
  • 海量数据支持:轻松处理 TB 至 PB 级数据
  • 高并发处理:支持数千 QPS 的复杂分析或实时查询
  • 完全兼容 PostgreSQL:使用标准 SQL,支持 JSON、GIS、全文检索等所有 PG 特性

官网:https://www.citusdata.com/

开源协议:AGPLv3(核心引擎),企业版提供额外功能

1.2 适用场景

  • 多租户 SaaS 应用(按租户 ID 分片)
  • 实时分析平台(如用户行为日志、IoT 数据)
  • 高频交易系统(如支付、订单)
  • 需要强一致性与 ACID 的分布式 OLTP/HTAP 混合负载

不适合:强跨分片 JOIN、频繁全局聚合(虽支持但有代价)


二、Citus 架构原理

2.1 节点角色

角色 说明
Coordinator(协调器) 接收客户端请求,解析 SQL,生成分布式执行计划,路由到 Worker 节点,汇总结果。不存业务数据(可选存元数据)
Worker(工作节点) 存储实际分片数据(Shard),执行本地查询,返回结果给 Coordinator
(可选) HA 架构 Coordinator 可配主备(通过流复制 + PgBouncer),Worker 节点支持分片副本(Citus 11+ 原生支持)

注:Citus 11 起支持 无 Coordinator 模式(Direct Routing),应用可直连 Worker(需配合连接池),进一步降低延迟。

2.2 数据分片(Sharding)机制

  • 分片键(Distribution Column) :用户指定某一列(如 tenant_iduser_idevent_time)作为分片依据
  • 哈希分片 :对分片键值计算哈希,映射到固定数量的 Shard(分片)
  • Shard 分布:每个 Shard 是一个标准 PostgreSQL 表,分布在不同 Worker 上
  • 副本(Replication):每个 Shard 可配置多个副本(默认 1),实现高可用

示例:

sql 复制代码
-- 按 user_id 分片,共 32 个分片
SELECT create_distributed_table('events', 'user_id');

→ 自动在各 Worker 上创建 events_10001events_10002 ... 等分片表。

2.3 查询执行流程

  1. 客户端连接 Coordinator,发送 SQL
  2. Citus 解析 SQL,识别涉及的表是否为分布式表
  3. 若是:
    • 根据 WHERE 条件中的分片键,路由到特定 Shard(Router Planning)
    • 广播查询到所有 Shard(Broadcast)(如小表 JOIN)
    • 重分布数据(Repartition Join)(跨分片 JOIN)
  4. 各 Worker 并行执行本地查询
  5. Coordinator 汇总结果,返回客户端

关键优化:避免跨节点数据移动,尽可能在本地完成计算。


三、安装与集群部署

3.1 安装方式(以 Ubuntu 为例)

方法一:官方 APT 仓库(推荐)
bash 复制代码
# 添加仓库
curl https://install.citusdata.com/community/deb.sh | sudo bash

# 安装(匹配 PostgreSQL 版本)
sudo apt install postgresql-16-citus-12
方法二:Docker(开发测试)
bash 复制代码
docker run -d --name citus-coordinator -p 5432:5432 citusdata/citus:12
docker run -d --name citus-worker1 citusdata/citus:12
docker run -d --name citus-worker2 citusdata/citus:12
# 需手动加入集群(见下文)

支持 PostgreSQL 12--16,Citus 版本需与 PG 匹配。

3.2 初始化集群(3 节点示例)

假设有 3 台机器:

  • coord: 192.168.1.10(Coordinator)
  • worker1: 192.168.1.11
  • worker2: 192.168.1.12
步骤 1:在所有节点安装 Citus + PostgreSQL

(略,同上)

步骤 2:在 Coordinator 上启用 Citus
sql 复制代码
-- 连接 coord 节点
CREATE EXTENSION citus;
步骤 3:将 Worker 加入集群
sql 复制代码
-- 在 coord 上执行
SELECT * from master_add_node('192.168.1.11', 5432);
SELECT * from master_add_node('192.168.1.12', 5432);

新版本(Citus ≥ 10)使用 SELECT citus_add_node(...),旧版用 master_add_node

步骤 4:验证集群状态
sql 复制代码
SELECT * FROM citus_get_active_worker_nodes();
-- 应返回两个 worker 节点

四、创建分布式表

4.1 分布式表类型

类型 说明 适用场景
Distributed Table(分片表) 数据按分片键水平拆分 大事实表(events, orders)
Reference Table(参考表) 全量复制到所有 Worker 小维度表(users, products)
Local Table(本地表) 仅存在于 Coordinator 元数据、配置表

4.2 创建分片表(Distributed Table)

sql 复制代码
-- 1. 创建普通表
CREATE TABLE events (
    event_id BIGINT,
    user_id  INT,
    event_time TIMESTAMPTZ,
    payload  JSONB
);

-- 2. 转换为分布式表(按 user_id 分片)
SELECT create_distributed_table('events', 'user_id');

默认创建 32 个分片(可通过 shard_count 参数调整)。

4.3 创建参考表(Reference Table)

sql 复制代码
CREATE TABLE users (
    user_id INT PRIMARY KEY,
    name TEXT
);

-- 复制到所有 Worker
SELECT create_reference_table('users');

优势:与分片表 JOIN 时无需网络传输,直接本地关联。

4.4 分片策略选择建议

分片键选择 优点 风险
租户 ID(多租户) 数据隔离,查询高效 租户数据倾斜
用户 ID 用户行为分析快 热点用户导致单分片压力大
时间戳(需谨慎) 时间范围查询高效 写入集中到最新分片(热点)
复合键(如 (tenant_id, user_id)) 更均匀分布 查询需包含所有键才高效

最佳实践:选择高基数、查询高频、分布均匀的列作为分片键


五、SQL 兼容性与查询能力

5.1 完全支持的标准 SQL

  • SELECT / INSERT / UPDATE / DELETE
  • JOIN(包括分片表与参考表、分片表与分片表)
  • GROUP BY, ORDER BY, LIMIT, WINDOW
  • CTE、子查询、事务(单分片事务强一致,跨分片最终一致)

5.2 分布式查询示例

(1)单分片查询(高效)
sql 复制代码
-- user_id = 123 的数据只在一个分片
SELECT * FROM events WHERE user_id = 123;
(2)多分片聚合(并行)
sql 复制代码
-- 所有分片并行计算 COUNT,Coordinator 汇总
SELECT COUNT(*) FROM events;
(3)分片表 JOIN 参考表(高效)
sql 复制代码
SELECT e.event_time, u.name
FROM events e
JOIN users u ON e.user_id = u.user_id
WHERE e.user_id = 123;  -- 可下推到单分片
(4)跨分片 JOIN(需重分布,性能较低)
sql 复制代码
-- events 按 user_id 分片,logs 按 device_id 分片
SELECT * FROM events e JOIN logs l ON e.user_id = l.user_id;
-- Citus 会将 logs 数据按 user_id 重分布到 events 所在节点

优化建议:尽量让 JOIN 条件包含分片键,或使用参考表。

5.3 事务与一致性

  • 单分片事务:完全 ACID,与 PostgreSQL 一致
  • 跨分片事务 :通过 2PC(两阶段提交) 实现原子性,但:
    • 性能开销大
    • 不支持 SAVEPOINT
    • 建议避免,或使用应用层补偿

六、性能优化与调优

6.1 分片数量(Shard Count)

  • 默认 32,适用于中小集群
  • 建议 :初始设为 Worker 节点数 × 2~4,未来可扩容
  • 调整 :创建后不可直接修改,需通过 undistribute_table + 重建

6.2 写入优化

  • 批量插入 :使用 COPYINSERT INTO ... VALUES (...), (...)(每批 1000~10000 行)
  • 避免随机分片键:导致写入分散,无法利用本地缓存
  • 预分区(Pre-sharding):提前创建足够分片,避免后期 rebalance 压力

6.3 查询优化

  • 强制路由查询:确保 WHERE 包含分片键
  • 使用参考表代替小分片表
  • 限制结果集LIMIT 尽早下推
  • 监控慢查询citus_stat_statements 扩展(需启用)

6.4 资源隔离(企业版)

  • 多租户资源组(Resource Groups):限制 CPU/内存/IOPS
  • 查询优先级队列

七、运维与高可用

7.1 扩容(Adding Nodes)

sql 复制代码
-- 添加新 Worker
SELECT citus_add_node('192.168.1.13', 5432);

-- 重新均衡分片(在线)
SELECT rebalance_table_shards('events');

rebalance_table_shards 会自动迁移分片,保持负载均衡。

7.2 高可用方案

(1)Coordinator 高可用
  • 使用 PgBouncer + 流复制主备 + VIP 切换
  • 或应用直连 Worker(Citus 11+ Direct Routing)
(2)Worker 高可用
  • Citus 原生副本(Citus 11+)

    sql 复制代码
    SELECT alter_distributed_table('events', replication_factor => 2);
  • 或依赖 底层存储高可用(如云盘、ZFS、RAID)

7.3 监控关键指标

  • citus_shards:分片分布
  • citus_lock_waits:分布式死锁
  • pg_stat_statements:查询性能
  • Prometheus Exporter(社区提供)

八、与生态工具集成

工具 集成方式
ORM(如 Django, SQLAlchemy) 直接连接 Coordinator,像普通 PG 一样使用
ETL 工具(如 Airflow, Talend) 通过 psycopg2 驱动写入
BI 工具(如 Metabase, Superset) 连接 Coordinator 执行 SQL
Kafka Connect 使用 JDBC Sink 写入
TimescaleDB 可在 Citus 分片表上启用 TimescaleDB(混合时序+分布式)

注意:部分工具若依赖 information_schema,需确认兼容性。


九、限制与注意事项

9.1 功能限制(截至 Citus 12)

  • 不支持 临时表
  • 不支持 触发器(Triggers)(除部分简单场景)
  • 不支持 外键跨分片引用
  • 不支持 物化视图(但可建在本地表)
  • 序列(SERIAL) 不保证全局唯一(建议用 UUID 或分布式 ID)

9.2 性能陷阱

  • 跨分片 ORDER BY + LIMIT:需拉取所有分片 Top-N,再全局排序
  • 大 OFFSET 分页:低效,建议用游标(cursor)或时间戳分页
  • 全表扫描:即使有索引,若未带分片键,仍需扫描所有分片

十、典型应用场景详解

10.1 多租户 SaaS 平台

  • 分片键tenant_id

  • 优势

    • 租户数据物理隔离
    • 查询天然路由到单分片
    • 扩容时按租户迁移
  • 示例

    sql 复制代码
    SELECT * FROM invoices WHERE tenant_id = 'acme' AND created_at > '2025-01-01';

10.2 实时用户行为分析

  • 分片键user_id

  • 结合events(分片表) + users(参考表)

  • 查询

    sql 复制代码
    SELECT u.name, COUNT(*) 
    FROM events e JOIN users u ON e.user_id = u.user_id
    WHERE e.event_time > NOW() - INTERVAL '1 hour'
    GROUP BY u.name;

10.3 IoT 设备监控(与 TimescaleDB 结合)

  • 在每个 Worker 上启用 TimescaleDB
  • 分片键:device_id
  • 每个分片是一个 Hypertable
  • 实现 分布式时序数据库

十一、Citus vs 其他分布式方案

方案 优点 缺点
Citus 完全兼容 PG,SQL 丰富,易运维 跨分片事务弱,复杂 JOIN 性能差
Vitess(MySQL) 成熟于 YouTube,强分片 仅支持 MySQL,SQL 限制多
TiDB 强一致性,HTAP 运维复杂,资源消耗大
Greenplum MPP 架构,分析强 写入弱,非 HTAP

Citus 最适合 已有 PostgreSQL 技术栈 且需 平滑扩展 的团队。


总结:Citus 通过 扩展而非替换 的方式,将 PostgreSQL 升级为一个强大的分布式数据库。它保留了 PostgreSQL 的全部优势(SQL、JSON、GIS、可靠性),同时解决了单机扩展性瓶颈。

其核心价值在于:

  • 透明分片:应用几乎无需改造
  • 弹性伸缩:在线增删节点,自动 rebalance
  • HTAP 能力:同时支持高并发 OLTP 与复杂分析
  • 开源免费:核心功能完全开放

对于需要处理 海量数据、高并发、多租户或实时分析 的系统,Citus 是 PostgreSQL 生态中最成熟、最实用的分布式解决方案。

相关推荐
洛豳枭薰14 小时前
分布式事务进阶
分布式
无心水15 小时前
5、微服务快速启航:基于Pig与BladeX构建高可用分布式系统实战
服务器·分布式·后端·spring·微服务·云原生·架构
闲人编程17 小时前
Redis分布式锁实现
redis·分布式·wpf·进程··死锁·readlock
yangyanping2010820 小时前
系统监控Prometheus之监控原理和配置
分布式·架构·prometheus
之歆20 小时前
ZooKeeper 分布式协调服务完全指南
分布式·zookeeper·wpf
逻辑君20 小时前
如何在PostgreSQL里删除和增加数据库
数据库·postgresql
数据知道1 天前
PostgreSQL:详解 PostGIS 地理信息数据处理
数据库·postgresql
之歆1 天前
DRBD 分布式复制块设备指南
分布式
时艰.1 天前
分布式 ID 服务实战
java·分布式