1. Citus 分布式架构概述
Citus 是 PostgreSQL 的一个开源扩展,它将 PostgreSQL 转变为分布式数据库系统。这个架构特别适合处理大规模数据集和高并发查询场景,通过将数据分片(sharding)存储在多个节点上,实现了水平扩展能力。
我在实际生产环境中部署 Citus 集群时发现,与传统单机 PostgreSQL 相比,它在处理以下场景时表现尤为突出:
- 需要存储和处理 TB 级甚至 PB 级数据的应用
- 高写入吞吐量的时序数据场景
- 需要实时分析的大型数据集
- 多租户 SaaS 应用的数据隔离需求
Citus 的核心原理是通过扩展 PostgreSQL 的查询规划器和执行器,使其能够协调多个工作节点并行处理查询。数据根据分片键(distribution column)被自动分布到不同节点,而查询会被重写为可以在各个节点上并行执行的子查询。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与安装
2.1 系统要求
在安装 Citus 之前,需要确保系统满足以下要求:
- PostgreSQL 9.5-15(建议使用 PostgreSQL 12 或更高版本)
- Linux 系统(推荐 Ubuntu 20.04+ 或 CentOS 7+)
- 至少 4GB 内存(生产环境建议 16GB 以上)
- 足够的磁盘空间(根据数据量预估)
注意:Citus 10 开始不再支持 Windows 系统,如果必须在 Windows 下使用,可以考虑 Docker 方式运行。
2.2 安装方法
方法一:使用官方仓库安装(推荐)
对于 Ubuntu/Debian 系统:
bash复制# 添加 Citus 仓库
curl https://install.citusdata.com/community/deb.sh | sudo bash
# 安装 Citus 扩展
sudo apt-get -y install postgresql-15-citus
对于 CentOS/RHEL 系统:
bash复制# 添加 Citus 仓库
curl https://install.citusdata.com/community/rpm.sh | sudo bash
# 安装 Citus 扩展
sudo yum install -y citus_15
方法二:源码编译安装
如果需要特定版本的 Citus 或进行自定义编译:
bash复制git clone https://github.com/citusdata/citus.git
cd citus
./configure
make
sudo make install
安装完成后,需要在 PostgreSQL 配置文件中添加以下内容:
code复制shared_preload_libraries = 'citus'
然后重启 PostgreSQL 服务使更改生效。
3. 集群配置与管理
3.1 初始化协调节点和工作节点
首先在协调节点(coordinator)上创建 Citus 扩展:
sql复制CREATE EXTENSION citus;
然后添加工作节点(worker)。假设我们有两个工作节点,IP 分别为 192.168.1.101 和 192.168.1.102:
sql复制SELECT * from master_add_node('192.168.1.101', 5432);
SELECT * from master_add_node('192.168.1.102', 5432);
可以通过以下命令查看节点状态:
sql复制SELECT * FROM master_get_active_worker_nodes();
3.2 分片策略配置
Citus 支持多种分片策略,最常用的是哈希分片和范围分片。创建分布式表时需要指定分片列(distribution column):
sql复制-- 创建普通表
CREATE TABLE events (
id bigserial,
event_time timestamptz,
user_id bigint,
data jsonb
);
-- 转换为分布式表,按 user_id 分片
SELECT create_distributed_table('events', 'user_id');
对于时序数据,可以采用范围分片:
sql复制SELECT create_distributed_table('events', 'event_time', 'range');
4. 基础操作与查询
4.1 数据写入
数据写入与普通 PostgreSQL 表操作相同,Citus 会自动将数据路由到正确的分片:
sql复制-- 单条插入
INSERT INTO events (event_time, user_id, data)
VALUES (now(), 123, '{"action": "login"}');
-- 批量插入
INSERT INTO events (event_time, user_id, data)
SELECT
now() - (random() * 365)::int * '1 day'::interval,
(random() * 10000)::int,
jsonb_build_object('action', CASE WHEN random() > 0.5 THEN 'login' ELSE 'logout' END)
FROM generate_series(1, 1000);
4.2 分布式查询
Citus 会自动将查询分发到各个分片并行执行:
sql复制-- 简单查询
SELECT user_id, count(*)
FROM events
WHERE event_time > now() - interval '7 days'
GROUP BY user_id
ORDER BY count(*) DESC
LIMIT 10;
-- 带 JOIN 的查询
SELECT u.user_name, count(*) as event_count
FROM events e
JOIN users u ON e.user_id = u.id
GROUP BY u.user_name
ORDER BY event_count DESC;
注意:JOIN 操作效率取决于 JOIN 条件是否包含分片列。最佳实践是尽量在分片列上 JOIN。
5. 性能优化技巧
5.1 分片数量选择
分片数量直接影响集群的扩展性和并行度。一般建议:
- 初始阶段:每个工作节点 2-4 个分片
- 生产环境:CPU 核心数的 2-4 倍
可以通过以下命令调整分片数量:
sql复制-- 将表重新分片为 64 个分片
SELECT alter_distributed_table('events', shard_count := 64);
5.2 共置(Colocation)
将关联频繁的表按相同分片列和分片数量分布,可以显著提高 JOIN 性能:
sql复制-- 创建用户表并分布
CREATE TABLE users (
id bigint PRIMARY KEY,
name text,
email text
);
SELECT create_distributed_table('users', 'id');
-- 确保 events 表与 users 表共置
SELECT alter_distributed_table('events', 'id', colocate_with => 'users');
5.3 参考表(Reference Table)
对于小表(如配置表、维度表),可以设置为参考表,在所有节点上保存完整副本:
sql复制CREATE TABLE countries (
code char(2) PRIMARY KEY,
name text
);
-- 转换为参考表
SELECT create_reference_table('countries');
6. 常见问题排查
6.1 连接问题
如果遇到节点间通信问题,检查:
- 防火墙设置(确保 5432 端口互通)
- PostgreSQL 的 pg_hba.conf 文件配置
- 各节点的 postgresql.conf 中 listen_addresses 设置
6.2 查询性能问题
慢查询可能的原因:
- 缺少分片列上的条件(导致全分片扫描)
- 跨分片 JOIN 操作
- 分片分布不均匀(数据倾斜)
可以使用 EXPLAIN 分析查询计划:
sql复制EXPLAIN ANALYZE
SELECT * FROM events WHERE user_id = 123;
6.3 分片再平衡
当添加新节点后,需要手动触发分片再平衡:
sql复制SELECT rebalance_table_shards();
可以通过以下命令监控再平衡进度:
sql复制SELECT * FROM get_rebalance_progress();
7. 监控与维护
7.1 关键指标监控
建议监控以下指标:
- 节点 CPU/内存/磁盘使用率
- 分片数据分布均匀性
- 长运行查询
- 复制延迟
Citus 提供了多个监控视图:
sql复制-- 查看分片分布
SELECT * FROM citus_shards;
-- 查看查询统计
SELECT * FROM citus_stat_statements;
7.2 备份与恢复
Citus 集群的备份策略:
- 协调节点:使用 pg_dump 备份元数据
- 工作节点:每个节点单独备份
示例备份命令:
bash复制# 备份协调节点元数据
pg_dump -h coordinator -U postgres -d mydb -Fc -f coordinator_backup.dump
# 备份工作节点数据
pg_dump -h worker1 -U postgres -d mydb -Fc -f worker1_backup.dump
恢复时需要先恢复协调节点,再恢复工作节点。
8. 生产环境最佳实践
根据我在多个生产环境部署的经验,总结以下建议:
-
分片键选择:
- 选择基数高、查询频繁的列
- 避免选择可能产生热点(如自增ID)
- 时序数据推荐使用时间范围分片
-
硬件配置:
- 协调节点:更高CPU和内存
- 工作节点:均衡配置,建议SSD存储
-
连接池:
- 使用 PgBouncer 或 Odyssey 管理连接
- 避免每个应用直接连接数据库
-
扩展策略:
- 先垂直扩展(提升节点配置)
- 后水平扩展(增加节点数量)
-
多租户实现:
sql复制-- 按租户ID分片 SELECT create_distributed_table('tenant_data', 'tenant_id'); -- 确保查询总是包含租户ID条件 SET citus.enable_router_execution = ON;
在实际部署中,我发现合理设置 maintenance_work_mem 和 work_mem 参数对大规模查询性能影响很大。对于32GB内存的工作节点,我通常会设置:
code复制maintenance_work_mem = 2GB
work_mem = 128MB
另外,定期执行 ANALYZE 更新统计信息对查询优化器非常重要,可以设置自动 ANALYZE:
code复制autovacuum_analyze_scale_factor = 0.05
autovacuum_analyze_threshold = 5000
