文档下载建议反馈入口

  • 功能概述
  • 基础概念
  • 环境要求
  • 配置集群复制
  • 场景配置示例
  • 故障排查

KaiwuDB 集群复制

功能概述

KaiwuDB 集群复制是一种异步数据同步机制,支持将表或库的数据(包括时序数据和关系数据)从主库(源端)集群实时复制到备库(目标端)集群,实现主备部署和灾备能力。用户可通过启动/停止复制任务来管理数据同步,并基于复制状态监控实现主备切换和灾备恢复。

核心特性

  • 灵活的复制粒度:支持表级别和库级别的数据复制。库级别复制定义后,表内数据、新增表及对应 DDL 操作均自动复制。
  • 断点续传:支持从指定时间点开始历史数据复制和断点续传。复制中断后,系统会基于上次 checkpoint 恢复复制,无需从头开始。
  • 高可用性:在多副本架构下,故障节点数小于副本数的一半时,复制仍可正常进行。主库节点故障时,RangeFeed 会自动切换到新的 leader 节点继续推送数据;备库节点故障时,复制协程会重新选举并从上次 checkpoint 恢复。网络中断时,系统会自动重试连接,通过 HAProxy 代理切换到可用节点,并基于断点继续复制。

应用场景

  • 集群主备部署:在同一数据中心内部署主备集群,主库承担业务读写负载,备库实时同步数据。当主库发生故障时,可以快速将业务切换到备库,保障业务连续性。
  • 跨数据中心灾备:在不同地理位置的数据中心间建立主备复制关系,实现异地容灾。当主数据中心发生重大故障、自然灾害或网络中断时,可将业务快速切换到备用数据中心,保障数据安全和业务连续性。
  • 一主多备:一个主库同时向多个备库复制数据,实现多份数据备份。不同备库可服务于不同场景:生产环境备份、测试环境数据同步、报表查询负载分离等,提高资源利用率。
  • 云边端协同:在云端、边缘节点和终端设备之间建立数据复制关系,支持边缘计算场景。边缘节点采集的数据可实时同步到云端进行集中分析,实现云边数据协同。

使用限制

  • 复制约束
    • 已有复制存在时,不支持删表/库操作。如需删除表或库,需先停止相关复制任务
    • 已有复制存在时,不支持跨库或跨表事务。单个事务中的所有操作必须全部在复制范围内或全部在复制范围外,不允许部分数据复制、部分数据非复制的情况
    • 不支持同步复制(同步复制在复制中断时会阻塞主库业务)
    • 对同一个表,库级复制和表级复制不能同时存在
    • 目前暂不支持对权限、存储过程、触发器、发布订阅、数据推送、流计算、序列、视图(包括普通视图、物化视图和临时视图)、索引、数据分区、区域和注释操作的复制
    • 库级复制限制:在开启库级别复制情况下,不支持删除库内最后一张表。在库内无表的情况下,不支持开启库级复制,需要先进行库内表创建后才能开启库级复制。
  • 一致性约束:关系数据保证最终一致性,但不保证主库事务在备库的完整性。复制以已提交事务为单位进行,但不保证事务内多条记录的原子可见性。例如,主库执行 BEGIN; INSERT t1 VALUES (1), (2), (3); COMMIT; 后,备库在复制过程中可能出现 (1)(1), (2)(1), (3) 等部分数据可见的中间状态,但最终保证 (1), (2), (3) 全部可见。

基础概念

术语英文说明
主库(源端)Primary/Source数据复制的源头集群,提供数据给备库
备库(目标端)Standby/Target数据复制的接收端集群,从主库接收数据
复制任务 IDReplication Job ID系统分配的任务标识符,包括 replication_producer_id(主库任务 ID)和 replication_consumer_id(备库任务 ID)
检查点Checkpoint记录复制进度的时间点,last_checkpoint 保证该时间点前的数据已复制完成,但因数据入库存在延迟,备库中可能存在入库时间晚于该时间点的数据
断点续传Resume from Checkpoint从中断点继续复制,避免从头开始,基于 last_checkpoint 恢复复制
复制状态Replication Status复制任务的执行状态,包括 running(运行中)、paused(已暂停)、succeeded(成功完成)、failed(失败)
RangeFeedRangeFeedKaiwuDB 的数据变更推送机制,用于实时推送数据变更到备库。集群复制功能依赖此机制,使用前必须在主库通过 SET CLUSTER SETTING kv.rangefeed.enabled = true 启用
HAProxyHAProxy高可用代理服务,用于负载均衡和故障切换,建议将复制连接配置为 HAProxy 地址
GCGarbage Collection垃圾回收,清理历史版本数据
RTORecovery Time Objective系统从停机恢复到可提供服务的时间。例如,RTO = 0 表示业务不受影响;RTO = 1 分钟表示最长中断 1 分钟。
RPORecovery Point Objective停机期间可能丢失的数据量(以秒为单位)。例如,RPO = 0 表示无数据丢失;RPO = 1 秒表示最多丢失 1 秒数据。

环境要求

硬件和网络要求

  • 硬件资源:备库硬件资源建议和主库保持同等配置,硬件环境不一致可能影响高可用的正常运行以及 RTO、RPO 时间
  • 网络延迟:建议网络延迟不超过 100ms
  • 时钟同步:为保证主备复制的可用性需要对主备物理机进行时钟校时,要求主备物理机时间差不大于 500ms

配置要求

  • 配置一致性:主备库启动命令及配置文件应保持一致,例如 --max-sql-cache--cache 等参数,以及压缩配置、GC 频率等设置应保持相同,配置不一致可能存在未知风险
  • 权限要求:设置主备数据复制的用户必须拥有 admin 权限。
  • 证书认证:安全模式下需要主备库共享证书。提示:使用脚本部署时,在主库配置文件 [additional] 中指定备库所有节点 IP,生成证书后拷贝到备库相同目录,然后用 ./deploy.sh install --multi-replica --use-certs <cert-path> 命令安装备库即可实现证书共享。
  • 用户名密码要求:主库和备库必须使用同名用户及密码。
  • 历史数据保留:如需从指定时间点开始复制历史数据,需要在启动复制前配置 GC 时间以保留足够的历史版本。建议根据复制窗口设置 gc.ttlseconds,默认 25 小时可能不足以支持长时间的历史数据复制。
    ALTER RANGE default CONFIGURE ZONE USING gc.ttlseconds = 180000;
    

说明

  • 当历史数据被 GC 回收后,可能会导致增量复制的主库和备库数据不一致
  • 保留过多的历史版本数据会占用额外的存储空间,并在一定程度上影响查询性能,建议根据实际复制窗口合理设置 GC 时间

配置集群复制

启动数据复制

REPLICATE [DATABASE <database_name>| TABLE <table_name>] 
FROM <source_url> 
WITH <options>;

参数说明

  • database_name:要复制的库名。注意:库内无表的情况下,不支持开启库级复制,需要先进行库内表创建后才能开启库级复制。
  • table_name:要复制的表名,格式为 database_name.schema_name.table_name,未指定数据库和模式时,表示复制当前数据库默认模式下的表。
  • source_url:主库集群地址,格式为 PostgreSQL 连接字符串。支持安全和非安全两种模式。建议配置为 HAProxy 地址而非直连节点 IP,以便在主库节点故障时自动切换。
    • 非安全模式:格式为 postgresql://user@host:port?sslmode=disable,例如:postgresql://root@192.168.111.128:26257?sslmode=disable
    • 安全模式:支持两种认证方式:
      • 用户名密码认证,需要在主库和备库创建同名用户及密码,格式为 postgresql://user:password@host:port
      • 证书认证:需要主备库共享证书,格式为:postgresql://user@host:port/database?sslmode=verify-ca&sslcert=<cert_path>&sslkey=<key_path>&sslrootcert=<ca_path>
  • options: 复制选项,支持以下参数组合:
    • init: 仅复制表结构和未来新增数据
    • data: 备库已有表结构,仅复制数据 (包括历史数据和未来新增数据)
    • init, data: 备库为空,需要完整复制表结构和数据
    • data, lastTime(<timestamp>): 备库已有表结构,仅复制指定时间点后的历史数据和未来新增数据
    • init, data, lastTime(<timestamp>):复制表结构以及指定时间点后的历史数据和未来新增数据

返回字段说明

  • replication_producer_id: 主库复制任务 ID,用于在主库管理复制任务
  • replication_consumer_id: 备库复制任务 ID,用于在备库管理复制任务
  • start_time:用户指定的数据复制时间点,未指定时返回 0

示例

  • 非安全模式下,复制库结构和未来增量数据

    REPLICATE DATABASE e1primary 
    FROM 'postgresql://root@192.168.111.128:26260?sslmode=disable' 
    WITH init;
    
  • 证书认证的安全模式下,复制库结构和所有数据

    REPLICATE DATABASE e1primary 
    FROM 'postgresql://root@localhost:26267/defaultdb?sslmode=verify-ca&sslcert=./certs/client.root.crt&sslkey=./certs/client.root.key&sslrootcert=./certs/ca.crt' 
    WITH init, data;
    
  • 非安全模式下,目标表已存在,仅复制数据

    REPLICATE TABLE defaultdb.public.t1 
    FROM 'postgresql://root@192.168.111.128:26257?sslmode=disable' 
    WITH data;
    
  • 非安全模式下,复制表结构和指定时间点后的数据

    REPLICATE TABLE defaultdb.public.t3
    FROM 'postgresql://root@192.168.111.128:26257?sslmode=disable' 
    WITH init, data, lastTime('2025-09-18 03:36:19.665970998+00:00');
    

停止数据复制

优雅停止

在备库执行以下命令:

REPLICATE STOP <replication_consumer_id> WITH TIMEOUT <duration>

参数说明

  • replication_consumer_id: 启动复制时返回的备库任务 ID
  • duration: 超时时间,在指定时间内无新数据写入后停止复制

返回字段说明

  • replication_consumer_id: 启动复制时返回的备库任务 ID
  • last_checkpoint:最后一次检查点时间,该时间点之前的数据已全部复制完成。注意:数据入库时间可能晚于此时间点,在备库执行超过该时间点的操作可能因冲突而失败。
  • status: 复制状态

示例

REPLICATE STOP 845690899499384833 WITH TIMEOUT 100ms;
replication_consumer_id |      last_checkpoint                 |   status
--------------------------+--------------------------------------+--------------
   845689849649332225    | 2025-09-18 03:36:19.665970998+00:00  |   succeeded
(1 row)

强制终止

说明:

强制终止方式会立即终止复制,不保证主库和备库数据一致性,因此建议仅在紧急情况下使用,推荐使用 REPLICATE STOP 优雅停止复制。

-- 在主库终止复制任务
CANCEL JOB <replication_producer_id>;

-- 在备库终止复制任务
CANCEL JOB <replication_consumer_id>;

验证复制状态

SELECT * FROM [SHOW JOBS] WHERE job_type = 'REPLICATION';

返回状态说明

  • running:复制任务正在运行
  • paused:复制任务已暂停
  • succeeded:复制任务成功完成
  • failed:复制任务失败

场景配置示例

正常运维场景

主备初始化

主备初始化适用于建立新的主备集群复制关系,实现数据的异步备份。

步骤:

  1. 登录主库任一节点,启用 RangeFeed 功能:

    SET CLUSTER SETTING kv.rangefeed.enabled = true;
    
  2. 登录备库任一节点,设置为只读模式:

    SET CLUSTER SETTING default_transaction_read_only = true;
    
  3. 在备库以数据库为单位启动数据复制:

    REPLICATE DATABASE e1primary 
    FROM 'postgresql://root@192.168.111.128:26260?sslmode=disable' 
    WITH init, data;
    
  4. 验证复制状态,状态变为 running 后表示复制任务正常运行。

    SELECT * FROM [SHOW JOBS] WHERE job_type = 'REPLICATION';
    

计划性停机和恢复

计划性停机即用户需要对集群进行硬件维护或软件升级,需要暂停复制并在完成后恢复。

步骤:

  1. 登录主库任一节点,设置为只读模式,保证数据一致性:

    SET CLUSTER SETTING default_transaction_read_only = true;
    
  2. 登录备库任一节点,5 秒内无写入后停止所有复制:

    REPLICATE STOP <replication_consumer_id> WITH TIMEOUT 5s;
    
  3. 登录主库任一节点,取消只读模式:

    SET CLUSTER SETTING default_transaction_read_only = false;
    
  4. 在主库/备库进行停机/重启等计划性操作。

  5. 登录备库任一节点,启动所有复制,指定 last_checkpoint 时间节点。说明last_checkpoint 可从 REPLICATE STOP 命令的返回结果中获取,也可通过查询系统表中已停止的 job 获取。

    REPLICATE TABLE defaultdb.public.b 
    FROM 'postgresql://root@192.168.111.128:26257?sslmode=disable' 
    WITH init, data, lastTime('2025-09-18T03:36:19.665970998Z');
    

计划性主备切换

步骤:

  1. 登录主库任一节点,设置为只读模式,保证数据一致性:

    SET CLUSTER SETTING default_transaction_read_only = true;
    
  2. 登录备库任一节点,5 秒内无写入后停止所有复制:

    REPLICATE STOP <replication_consumer_id> WITH TIMEOUT 5s;
    
  3. 在备库任一节点,启用 RangeFeed 功能:

    SET CLUSTER SETTING kv.rangefeed.enabled = true;
    
  4. 登录主库任一节点,启动到原备库(新主库)的复制,使用 REPLICATE STOP 命令的返回结果中获取的 last_checkpoint 点:

    REPLICATE TABLE defaultdb.public.b 
    FROM 'postgresql://root@备库地址:26257?sslmode=disable' 
    WITH init, data, lastTime('2025-09-18T03:36:19.665970998Z');
    
  5. 在原主库任一节点,取消只读模式:

    SET CLUSTER SETTING default_transaction_read_only = false;
    
  6. 登录新主库任一节点,取消只读模式,允许用户进行读写:

    SET CLUSTER SETTING default_transaction_read_only = false;
    

故障处理场景

自动恢复场景

以下场景系统会自动处理,无需用户干预,用户可通过 KaiwuDB 监控平台或系统表确认复制状态:

  • 主库部分节点故障:主库故障节点数少于副本数的一半时,RangeFeed 自动切换到新的主节点继续数据复制。
  • 备库部分节点故障:备库故障节点数少于副本数的一半时,复制协程自动重新选举,并基于 last_checkpoint 进行断点续传。
  • 网络中断或波动:网络临时中断或波动时,系统自动重试连接,通过 HAProxy 代理切换到可用节点,并基于断点继续复制。

备库不可用

备库故障节点数等于或超过副本数的一半导致集群不可用时,用户可根据业务需求选择以下任一方式:

  • 等待备库恢复:备库集群恢复后会自动基于断点进行复制,无需用户操作。
  • 重建新备库:搭建新的备库,重建复制,

重建新备库的具体步骤如下:

  1. 登录主库任一节点,取消现有复制任务:

    CANCEL JOB <replication_producer_id>;
    
  2. 在新备库重建复制,具体步骤参考主备初始化

主库不可用

主库故障节点数等于或超过副本数的一半导致集群不可用时,需要将备库提升为主库。

步骤:

  1. 修改 HAProxy 配置,将备库开放给应用访问。

  2. 登录备库任一节点,5 秒内无写入后停止复制:

    REPLICATE STOP <replication_consumer_id> WITH TIMEOUT 5s;
    
  3. 在备库任一节点,取消只读模式:

    SET CLUSTER SETTING default_transaction_read_only = false;
    
  4. (可选)如果后续主库恢复正常,可通过以下步骤,恢复数据复制:

    1. 登录原备库(新主库)任一节点,启用 RangeFeed 功能:

      SET CLUSTER SETTING kv.rangefeed.enabled = true;
      
    2. 登录原主库任一节点,设置为只读模式:

      SET CLUSTER SETTING default_transaction_read_only = true;
      
    3. 在原主库任一节点,取消旧的复制任务:

      CANCEL JOB <replication_producer_id>;
      
    4. 在原主库任一节点,重建到原备库(新主库)的复制,使用 REPLICATE STOP 命令返回的 last_checkpoint 点:

      REPLICATE TABLE defaultdb.public.b 
      FROM 'postgresql://root@新主库地址:26257?sslmode=disable' 
      WITH init, data, lastTime('2025-09-18T03:36:19.665970998Z');
      

故障排查

错误信息

错误信息原因解决方法
ERROR: database missing数据库不存在检查主库数据库名称拼写,确认数据库已创建
ERROR: table missing表不存在检查表名拼写,确认表已创建
ERROR: dial tcp ... connection refused无法连接主库检查网络连通性和主库服务状态
ERROR: replication_consumer_id missing复制 ID 不存在检查复制 ID 是否正确