# ha/citus

> 13 节点 Citus 分布式 PostgreSQL 集群，1 协调组 + 5 工作组高可用配置，提供水平扩展与分片能力

---

LLMS 索引： [llms.txt](/zh/llms.txt)

---

`ha/citus` 配置模板部署一套完整的 **Citus 分布式 PostgreSQL 集群**，包含 1 个基础设施节点、1 组协调节点和 5 组工作节点（共 12 个 Citus 节点），提供透明的水平扩展与数据分片能力。


--------

## 配置概览

- 配置名称： `ha/citus`
- 节点数量： 13 节点（1 基础设施 + 1 协调组 × 2 + 5 工作组 × 2）
- 配置说明：Citus 分布式 PostgreSQL 高可用集群
- 适用系统：`el8`, `el9`, `el10`, `d12`, `d13`, `u22`, `u24`, `u26`
- 适用架构：`x86_64`
- 相关配置：[`meta`](/docs/conf/meta/)，[`ha/trio`](/docs/conf/trio/)

启用方式：

```bash
./configure -c ha/citus
```

> 备注：这是一个 13 节点模板，您需要在生成配置后修改各节点的 IP 地址


--------

## 配置内容

源文件地址：[`pigsty/conf/ha/citus.yml`](https://github.com/pgsty/pigsty/blob/main/conf/ha/citus.yml)

```yaml
---
#==============================================================#
# File      :   citus.yml
# Desc      :   13-node Citus (6-group Distributive) Config Template
# Ctime     :   2020-05-22
# Mtime     :   2025-01-20
# Docs      :   https://pigsty.io/docs/conf/citus
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng (rh@vonng.com)
#==============================================================#

# This is the config template for Citus Distributive Cluster
# tutorial: https://pigsty.io/docs/pgsql/kernel/citus
# we will use the local repo for cluster bootstrapping
#
# Topology:
#   - pg-citus0: coordinator (10.10.10.10)         VIP: 10.10.10.19
#   - pg-citus1: worker group 1 (10.10.10.21, 22)  VIP: 10.10.10.29
#   - pg-citus2: worker group 2 (10.10.10.31, 32)  VIP: 10.10.10.39
#   - pg-citus3: worker group 3 (10.10.10.41, 42)  VIP: 10.10.10.49
#   - pg-citus4: worker group 4 (10.10.10.51, 52)  VIP: 10.10.10.59
#   - pg-citus5: worker group 5 (10.10.10.61, 62)  VIP: 10.10.10.69
#   - pg-citus6: worker group 6 (10.10.10.71, 72)  VIP: 10.10.10.79
#
# Usage:
#   curl https://repo.pigsty.io/get | bash
#   ./configure -c citus
#   ./deploy.yml

all:
  children:
    infra: { hosts: { 10.10.10.10: { infra_seq: 1 }}}
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1  }}, vars: { etcd_cluster: etcd }}
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_users:
          - { name: dbuser_meta ,password: DBUser.Meta   ,pgbouncer: true ,roles: [dbrole_admin   ] ,comment: pigsty admin user }
        pg_databases:
          - name: meta
            baseline: cmdb.sql
            comment: "pigsty meta database"
            schemas: [pigsty]
            extensions: [ postgis, vector ]
        pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # make a full backup every day 1am

    #----------------------------------------------------------#
    # pg-citus: 6 cluster groups, 12 nodes total
    #----------------------------------------------------------#
    pg-citus:
      hosts:

        # coordinator (group 0) on infra node
        10.10.10.21: { pg_group: 0, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.29/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.22: { pg_group: 0, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.29/24 ,pg_seq: 2, pg_role: replica }

        # worker group 2
        10.10.10.31: { pg_group: 1, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.39/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.32: { pg_group: 1, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.39/24 ,pg_seq: 2, pg_role: replica }

        # worker group 3
        10.10.10.41: { pg_group: 2, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.49/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.42: { pg_group: 2, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.49/24 ,pg_seq: 2, pg_role: replica }

        # worker group 4
        10.10.10.51: { pg_group: 3, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.59/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.52: { pg_group: 3, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.59/24 ,pg_seq: 2, pg_role: replica }

        # worker group 5
        10.10.10.61: { pg_group: 4, pg_cluster: pg-citus5 ,pg_vip_address: 10.10.10.69/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.62: { pg_group: 4, pg_cluster: pg-citus5 ,pg_vip_address: 10.10.10.69/24 ,pg_seq: 2, pg_role: replica }

        # worker group 6
        10.10.10.71: { pg_group: 5, pg_cluster: pg-citus6 ,pg_vip_address: 10.10.10.79/24 ,pg_seq: 1, pg_role: primary }
        10.10.10.72: { pg_group: 5, pg_cluster: pg-citus6 ,pg_vip_address: 10.10.10.79/24 ,pg_seq: 2, pg_role: replica }

      vars:
        pg_mode: citus                            # pgsql cluster mode: citus
        pg_shard: pg-citus                        # citus shard name: pg-citus
        pg_primary_db: citus                      # primary database used by citus
        pg_dbsu_password: DBUser.Postgres         # enable dbsu password access for citus
        pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]
        pg_libs: 'citus, pg_cron, pg_stat_statements'
        pg_users: [{ name: dbuser_citus ,password: DBUser.Citus ,pgbouncer: true ,roles: [ dbrole_admin ] }]
        pg_databases: [{ name: citus ,owner: dbuser_citus ,extensions: [ citus, vector, topn, pg_cron, hll ] }]
        pg_parameters:
          cron.database_name: citus
          citus.node_conninfo: 'sslrootcert=/pg/cert/ca.crt sslmode=verify-full'
        pg_hba_rules:
          - { user: 'all' ,db: all  ,addr: 127.0.0.1/32  ,auth: ssl ,title: 'all user ssl access from localhost' }
          - { user: 'all' ,db: all  ,addr: intra         ,auth: ssl ,title: 'all user ssl access from intranet'  }
        pg_vip_enabled: true
        pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ] # make a full backup every day 1am

  vars:
    #----------------------------------------------#
    # INFRA : https://pigsty.io/docs/infra/param
    #----------------------------------------------#
    version: v4.5.0
    admin_ip: 10.10.10.10
    region: default
    infra_portal:
      home : { domain: i.pigsty }

    #----------------------------------------------#
    # NODE : https://pigsty.io/docs/node/param
    #----------------------------------------------#
    nodename_overwrite: true
    node_repo_modules: node,infra,pgsql
    node_tune: oltp

    #----------------------------------------------#
    # PGSQL : https://pigsty.io/docs/pgsql/param
    #----------------------------------------------#
    pg_version: 18  # PostgreSQL 14-18
    pg_conf: oltp.yml
    pg_packages: [ pgsql-main, pgsql-common ]

    #----------------------------------------------#
    # PASSWORD : https://pigsty.io/docs/setup/security/
    #----------------------------------------------#
    grafana_admin_password: pigsty
    grafana_view_password: DBUser.Viewer
    pg_admin_password: DBUser.DBA
    pg_monitor_password: DBUser.Monitor
    pg_replication_password: DBUser.Replicator
    patroni_password: Patroni.API
    haproxy_admin_password: pigsty
    minio_secret_key: S3User.MinIO
    etcd_root_password: Etcd.Root
...
```


--------

## 集群拓扑

此配置部署一套完整的 Citus 分布式集群，拓扑结构如下：

| 集群            | 节点 | IP 地址           | VIP         | 角色            |
|---------------|----|-----------------|-------------|---------------|
| **pg-meta**   | 1  | 10.10.10.10     | -           | 基础设施 + CMDB   |
| **pg-citus1** | 2  | 10.10.10.21, 22 | 10.10.10.29 | 协调节点（group 0） |
| **pg-citus2** | 2  | 10.10.10.31, 32 | 10.10.10.39 | 工作节点（group 1） |
| **pg-citus3** | 2  | 10.10.10.41, 42 | 10.10.10.49 | 工作节点（group 2） |
| **pg-citus4** | 2  | 10.10.10.51, 52 | 10.10.10.59 | 工作节点（group 3） |
| **pg-citus5** | 2  | 10.10.10.61, 62 | 10.10.10.69 | 工作节点（group 4） |
| **pg-citus6** | 2  | 10.10.10.71, 72 | 10.10.10.79 | 工作节点（group 5） |

**架构说明**：

- **pg-meta**：基础设施节点，运行 Grafana、VictoriaMetrics、etcd 等组件，同时部署一个独立的 CMDB 数据库
- **pg-citus1**：Citus 协调节点（group 0），负责接收客户端查询并路由到工作节点，1 主 1 从高可用配置
- **pg-citus2~6**：Citus 工作节点（group 1~5），存储分片数据，每组 1 主 1 从，通过 Patroni 实现自动故障转移
- **VIP**：每个节点组配置 L2 VIP，由 `vip-manager` 管理，确保故障转移时客户端连接自动切换


--------

## 配置解读

`ha/citus` 模板部署生产级 Citus 分布式集群，适合需要水平扩展的大规模数据场景。

**关键特性**：

- **水平扩展**：5 个工作组可线性扩展存储和计算能力
- **高可用**：每个工作组 1 主 1 从，支持自动故障转移
- **L2 VIP**：每组配置虚拟 IP，故障切换对应用透明
- **SSL 加密**：节点间通信使用 SSL 证书加密
- **透明分片**：数据自动分布到多个工作节点

**预装扩展**：

```yaml
pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]
pg_libs: 'citus, pg_cron, pg_stat_statements'
```

**安全配置**：

- 启用 `pg_dbsu_password`，允许超级用户密码访问（Citus 节点间通信需要）
- HBA 规则要求所有连接使用 SSL 认证
- 节点间使用证书验证：`sslmode=verify-full`


--------

## 部署步骤

```bash
# 1. 下载 Pigsty
curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty

# 2. 使用 ha/citus 配置模板
./configure -c ha/citus

# 3. 修改 IP 地址和密码
vi pigsty.yml

# 4. 部署完整集群
./deploy.yml
```

部署完成后，Citus 会自动注册所有工作节点。可通过以下命令验证：

```sql
-- 连接到任意协调节点
psql -h 10.10.10.29 -U dbuser_citus -d citus

-- 查看工作节点状态
SELECT * FROM citus_get_active_worker_nodes();

-- 查看分片分布
SELECT * FROM citus_shards;
```


--------

## 使用示例

**创建分布式表**：

```sql
-- 创建表
CREATE TABLE events (
    tenant_id INT,
    event_id BIGSERIAL,
    event_time TIMESTAMPTZ DEFAULT now(),
    payload JSONB,
    PRIMARY KEY (tenant_id, event_id)
);

-- 按 tenant_id 分片
SELECT create_distributed_table('events', 'tenant_id');

-- 插入数据（自动路由到对应分片）
INSERT INTO events (tenant_id, payload)
VALUES (1, '{"type": "click"}');

-- 查询（自动并行执行）
SELECT tenant_id, count(*)
FROM events
GROUP BY tenant_id;
```

**创建引用表**（小表复制到所有节点）：

```sql
CREATE TABLE tenants (
    tenant_id INT PRIMARY KEY,
    name TEXT
);

SELECT create_reference_table('tenants');
```


--------

## 适用场景

- **多租户 SaaS**：按租户 ID 分片，实现租户数据隔离和并行查询
- **实时分析**：大规模事件数据的实时聚合分析
- **时序数据**：结合 TimescaleDB 处理海量时序数据
- **水平扩展**：单表数据量超过单机容量时的扩展方案


--------

## 注意事项

- **PostgreSQL 版本**：Citus 支持 PostgreSQL 14~18，此模板默认使用 PG18
- **分布列选择**：合理选择分布列（通常是租户 ID 或时间戳）对性能至关重要
- **跨分片限制**：外键约束必须包含分布列，部分 DDL 操作有限制
- **网络要求**：`pg_vip_interface` 默认为 `auto`，特殊网络环境可显式指定网卡
- **架构限制**：Citus 扩展不支持 ARM64 架构
