写点什么

Kubernetes 场景下的 StarRocks 灾备体系:Cluster Snapshot 实践解析

作者:StarRocks
  • 2025-10-22
    北京
  • 本文字数:10047 字

    阅读完需:约 33 分钟

Kubernetes 场景下的 StarRocks 灾备体系:Cluster Snapshot 实践解析

在存算一体架构下,StarRocks 通过 Failover Group、Backup & Restore 以及 Insert Into Files 等机制,实现了集群级的灾备与数据的备份和恢复能力。伴随性能优化与功能演进的持续推进,StarRocks 不断强化系统的稳定性与可用性,以满足企业日益增长的实时分析与高可用需求。

在 3.5 版本 中,StarRocks 推出了全新的 Cluster Snapshot 快照恢复机制,进一步完善了数据安全与灾备体系。

Snapshot 提供了一种高效、低成本、自动化的数据保护方式,显著提升系统的可用性与容灾能力,弥补了此前存算分离架构在备份与恢复方面的空缺。

当系统发生故障、误操作或区域性宕机时,Snapshot 可在分钟级完成快速恢复,最大限度减少数据丢失与业务中断风险。通过将完整集群状态进行快照化并备份至对象存储,Snapshot 简化了传统灾备方案的复杂流程,使灾难恢复更加高效与便捷。这一机制尤其适用于 金融、零售、SaaS 等对系统稳定性要求极高的关键业务场景。

在此基础上,本文结合 StarRocks 在 Kubernetes 环境中的实际部署实践,进一步介绍了存算分离架构下的灾备机制、恢复流程及快照策略,帮助用户在集群异常或故障场景中快速恢复系统状态,保障业务连续性与数据安全。

名词解释

Cluster Snapshot:

在存算分离架构下,StarRocks 3.5 新增支持集群级别的 Snapshot 功能,提供完整的集群快照能力。Snapshot 可自动创建,记录集群在某一时间点的完整状态(包括 catalog、database、table、user 等元数据),并存储于对象存储中,实现快速的原地或异地恢复。Snapshot 不包含外部依赖对象,比如 catalog 依赖的外部配置文件、本地 UDF jar 包等。

Cluster Snapshot 包含两部分内容:Metadata Snapshot 和 Data Snapshot。

  • Metadata Snapshot

FE 定期通过 checkpoint 的方式生成的 image 文件为 Metadata Snapshot。image 文件中包含了集群的元数据信息,包括库表,用户,权限等相关内容。

  • Data Snapshot

在存算分离的架构中,数据会存储在对象存储上。而对象存储具有高可靠,接近无限容量等特性。所以在 Snapshot 产生的过程中,我们并不需要对数据进行拷贝,只需要保留 Metadata Snapshot 对应的那些数据版本即可。在恢复时可以将元数据与对应的数据版本进行映射。

在启用集群自动快照功能后,系统会按照设定周期(默认每 10 分钟)生成一份完整快照,并将 FE 的元数据 image 文件写入指定的对象存储路径。因为原始数据文件本身就已经保存在对象存储中,因此数据层面不会发生额外的数据搬迁,系统默认保留最近一次快照及其所依赖的数据版本。

如上图所示,针对每个 tablet 的数据导入都会产生一个对应版本的 rowset。对于已经包含在未删除的 metadata snapshot 的 tablets,涉及到因为 drop table/partition、delete、Compaction 等操作需要后期 GC 删除无用文件的 GC 任务会在下一个 metadata snapshot 生成之前被阻塞,从而确保当前快照所需的数据版本不会被清理。

Automated cluster snapshot:系统会根据设置的快照保留周期,自动创建和保存最新的集群状态快照,且只会保留一个最新可用快照。

Cluster Restore: 当需要恢复时,用户只需在新集群或原集群中指定快照在对象存储上的路径与存储卷配置,即可将系统恢复至指定时间点状态。恢复过程将自动加载元数据并清理冗余数据,确保数据一致性和可用性。


设计目标

StarRocks 存算分离架构支持自动化快照功能,通过快照实现集群的本地或远程恢复。快照的存储位置与数据目录保持一致。利用快照保存最新 checkpoint 版本中的数据信息,支持恢复集群到最近一次快照状态;

在每次生成新的快照文件时,系统会自动创建对应的快照,并删除历史快照文件,仅保留最新版本。因此,每个集群中自动化快照始终只有一个。

自动化快照由系统自动触发,用户可以通过 SQL 命令修改参数,以控制快照生成的周期。

限制:当前仅支持存算分离架构。


具体操作

由于篇幅所限,关于自动化集群快照的开启、关闭,以及集群快照与任务信息的查看等具体操作步骤,请参见官方文档,此处不再展开。

🔗:https://docs.mirrorship.cn/zh/docs/administration/cluster_snapshot/


Kubernetes 部署环境下的恢复流程

在 Kubernetes 部署环境中,为了能够让 operator 在 "disasterRecovery" 模式下优雅地完成调谐,引入了 disasterRecovery 和 disasterRecoveryStatus 配置项;

spec:  disasterRecovery:    generation: 1    enabled: true
status: disasterRecoveryStatus: phase: todo/doing/done reason: "" observedGeneration: 1 startTimestamp: xxx endTimestamp: yyy
复制代码

配置项 "disasterRecovery" 的 "enabled" 必须为 true;

disasterRecoveryStatus.phase 表示灾难恢复的阶段,包括:todo 待执行、doing 执行中、done 已完成,disasterRecoveryStatus 的更新逻辑如下:

  1. 当 Operator 检测到首次进入灾备模式(disasterRecoveryStatus 为空)或 observedGeneration < generation 时,灾备模式进入 TODO 阶段。

  2. 在下发修改后的 StatefulSet 后,将 disasterRecoveryStatus.phase 更新为 doing 状态。该状态的持续时间取决于灾备操作的完成时间。

a. Operator 会定期检查 FE Pod 的状态:首先确认其所属的 generation;其次确认 Pod 是否处于 Ready 状态。

  1. 当 FE Pod 处于 Ready 状态后,将 disasterRecoveryStatus.phase 更新为 done 阶段。

  2. 随后,Operator 会根据 StarRocksCluster 的配置,正常启动集群。


如何在已运行的集群上执行灾备恢复

推荐在一个空的 StarRocks 集群上启用灾备。如果使用的是已有的 StarRocks 集群,在启用灾备之前需要清理 FE 组件的元数据 和 CN 组件的数据。

  1. 清理旧的元数据

a. 手动将 FE StatefulSet 的副本数设置为 0;

b. 删除对应的 FE 元数据 PVC。

  1. 清理旧的数据

a. 手动将 CN StatefulSet 的副本数设置为 0;

b. 删除对应的 CN Cache 存储 PVC。

  1. 启动灾难恢复

  2. 异常情况处理

a. CN 本地缓存清理

1). 在就地恢复(inplace recovery) 的场景下,本地 CN 节点可能仍然保留旧的缓存数据。由于 ID 生成器被重置,相同的文件名可能对应不同的内容,从而导致缓存损坏。

2). 需要手动清理缓存:可以通过登录 Pod 清理缓存,或者强制删除 PV/PVC 卷,让 StatefulSet 为 CN 节点重新创建新的卷。

b. FE 节点就地恢复

1). 在某些情况下,现有 FE 节点可能已经形成一个高可用(HA)集群。在恢复后,fe-0 节点会使 用新的元数据完成恢复,但 fe-1、fe-2 节点可能仍然保留旧的元数据,并继续形成一个 HA 集 群(其中可能有一个是 leader)。

2). 恢复完成后,可能会出现 fe-0 成为 leader(正确状态),而 fe-1/fe-2 形成另一个集群的情 况。

3). 需要手动检查,并清理 fe-1、fe-2 的元数据目录,以确保能够从这种状态下恢复。

c. generation 字段可用于多次执行灾备。例如,如果上一次的灾备结果不符合预期,可以手动修改相 关配置并提升 generation 的值,从而重新执行一次灾备。

d. 如果 FE 在生成快照时异常退出,S3 上可能会出现两个快照,此时需要使用较旧的快照进行恢复。

➜  disaster-recovery git:(master) ✗ s3cmd ls s3://ydx-starrocks-cluster-bucket/data/5b0125af-7ff6-45df-9b60-c896797458ba/meta/image/DIR  s3://ydx-starrocks-cluster-bucket/data/5b0125af-7ff6-45df-9b60-c896797458ba/meta/image/automated_cluster_snapshot_1739446285344/DIR  s3://ydx-starrocks-cluster-bucket/data/5b0125af-7ff6-45df-9b60-c896797458ba/meta/image/automated_cluster_snapshot_1739446405766/
复制代码

Kubernetes 部署环境下的灾备恢复实践

为了让用户更简单方便地参考本文档,我们使用 kube-starrocks Helm Chart 来部署集群。请注意:

  1. 必须使用 v1.10.0 以上版本的 Operator 和 YAML Manifest;

  2. 我们在文档中使用 xxx 来替代敏感信息,请根据实际情况设置为合理的值。

创建可用的集群

首先,准备 ./starrocks-values.yaml 配置文件。

operator:  starrocksOperator:    image:      repository: starrocks/operator      tag: v1.10.0    imagePullPolicy: IfNotPresent    replicaCount: 1    resources:      requests:        cpu: 1m        memory: 20Mistarrocks:  starrocksCluster:    enabledBe: false    enabledCn: true  starrocksCnSpec:    config: |      sys_log_level = INFO      # ports for admin, web, heartbeat service      thrift_port = 9060      webserver_port = 8040      heartbeat_service_port = 9050      brpc_port = 8060    image:      repository: starrocks/cn-ubuntu      tag: 3.4.1    replicas: 3    resources:      limits:        cpu: 8        memory: 8Gi      requests:        cpu: 1m        memory: 10Mi    storageSpec:      name: cn      logStorageSize: 1Gi      storageSize: 10Gi  starrocksFESpec:    feEnvVars:    - name: LOG_CONSOLE      value: "1"    config: |      LOG_DIR = ${STARROCKS_HOME}/log      DATE = "$(date +%Y%m%d-%H%M%S)"      JAVA_OPTS="-Dlog4j2.formatMsgNoLookups=true -Xmx8192m -XX:+UseG1GC -Xlog:gc*:${LOG_DIR}/fe.gc.log.$DATE:time -XX:ErrorFile=${LOG_DIR}/hs_err_pid%p.log -Djava.security.policy=${STARROCKS_HOME}/conf/udf_security.policy"      http_port = 8030      rpc_port = 9020      query_port = 9030      edit_log_port = 9010      mysql_service_nio_enabled = true      sys_log_level = INFO      run_mode = shared_data      cloud_native_meta_port = 6090      enable_load_volume_from_conf = true      cloud_native_storage_type = S3      aws_s3_path = xxx      aws_s3_region = xxx      aws_s3_endpoint = xxx      aws_s3_access_key = xxx      aws_s3_secret_key = xxx      # we add this configuration because we want to get cluster snapshot quickly      automated_cluster_snapshot_interval_seconds = 60    replicas: 3    image:      repository: starrocks/fe-ubuntu      tag: 3.4.1    resources:      limits:        cpu: 2        memory: 4Gi      requests:        cpu: 1m        memory: 20Mi    storageSpec:      logStorageSize: 1Gi      name: fe-storage      storageSize: 10Gi
复制代码

注意:我们将 automated_cluster_snapshot_interval_seconds 设置为按每分钟触发。

接下来,使用 Helm 创建集群。

helm install -f ./starrocks-values.yaml starrocks starrocks-community/kube-starrocks --version 1.10.0
# make sure the cluster has been successfully deployedkubectl get podsNAME READY STATUS RESTARTS AGEkube-starrocks-cn-0 1/1 Running 0 23skube-starrocks-fe-0 1/1 Running 0 79skube-starrocks-fe-1 1/1 Running 0 79skube-starrocks-fe-2 1/1 Running 0 79s
复制代码

建表与写入数据

连接 FE

# enter FE podkubectl exec -it kube-starrocks-fe-0 bash
# use mysql client to loginmysql -h 127.0.0.1 -P9030 -uroot...mysql>
复制代码

执行以下 SQL 语句:

# create database and tableCREATE DATABASE IF NOT EXISTS quickstart;
USE quickstart;
-- create tableCREATE TABLE source_wiki_edit( event_time DATETIME, channel VARCHAR(32) DEFAULT '', user VARCHAR(128) DEFAULT '', is_anonymous TINYINT DEFAULT '0', is_minor TINYINT DEFAULT '0', is_new TINYINT DEFAULT '0', is_robot TINYINT DEFAULT '0', is_unpatrolled TINYINT DEFAULT '0', delta INT DEFAULT '0', added INT DEFAULT '0', deleted INT DEFAULT '0')DUPLICATE KEY( event_time, channel,user, is_anonymous, is_minor, is_new, is_robot, is_unpatrolled)PARTITION BY RANGE(event_time)( PARTITION p06 VALUES LESS THAN ('2015-09-12 06:00:00'), PARTITION p12 VALUES LESS THAN ('2015-09-12 12:00:00'), PARTITION p18 VALUES LESS THAN ('2015-09-12 18:00:00'), PARTITION p24 VALUES LESS THAN ('2015-09-13 00:00:00'))DISTRIBUTED BY HASH(user);
-- insert dataINSERT INTO source_wiki_editVALUES ("2015-09-12 00:00:00","#en.wikipedia","AustinFF",0,0,0,0,0,21,5,0), ("2015-09-12 00:00:00","#ca.wikipedia","helloSR",0,1,0,1,0,3,23,0), ("2015-09-12 08:00:00","#ca.wikipedia","helloSR",0,1,0,1,0,3,23,0);
-- select datamysql> select * from source_wiki_edit;+---------------------+---------------+----------+--------------+----------+--------+----------+----------------+-------+-------+---------+| event_time | channel | user | is_anonymous | is_minor | is_new | is_robot | is_unpatrolled | delta | added | deleted |+---------------------+---------------+----------+--------------+----------+--------+----------+----------------+-------+-------+---------+| 2015-09-12 00:00:00 | #ca.wikipedia | helloSR | 0 | 1 | 0 | 1 | 0 | 3 | 23 | 0 || 2015-09-12 00:00:00 | #en.wikipedia | AustinFF | 0 | 0 | 0 | 0 | 0 | 21 | 5 | 0 || 2015-09-12 08:00:00 | #ca.wikipedia | helloSR | 0 | 1 | 0 | 1 | 0 | 3 | 23 | 0 |+---------------------+---------------+----------+--------------+----------+--------+----------+----------------+-------+-------+---------+3 rows in set (0.34 sec)
复制代码

生成集群快照

启动备份:

mysql> ADMIN SET AUTOMATED CLUSTER SNAPSHOT ON STORAGE VOLUME builtin_storage_volume;Query OK, 0 rows affected (0.10 sec)
复制代码

等待备份完成

mysql> SELECT * FROM  INFORMATION_SCHEMA.CLUSTER_SNAPSHOT_JOBS;+------------------------------------------+--------+---------------------+---------------------+-------------+-------------+---------------+| SNAPSHOT_NAME                            | JOB_ID | CREATED_TIME        | FINISHED_TIME       | STATE       | DETAIL_INFO | ERROR_MESSAGE |+------------------------------------------+--------+---------------------+---------------------+-------------+-------------+---------------+| automated_cluster_snapshot_1739857978127 |  10136 | 2025-02-18 13:52:58 | 2025-02-18 13:54:17 | FINISHED    |             |               || automated_cluster_snapshot_1739858117584 |  10137 | 2025-02-18 13:55:17 | NULL                | SNAPSHOTING |             |               |+------------------------------------------+--------+---------------------+---------------------+-------------+-------------+---------------+2 rows in set (0.02 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.CLUSTER_SNAPSHOTS;+------------------------------------------+---------------+---------------------+---------------+--------------------+------------+------------------------+---------------------------------------------------------------------------------------------------------------------------------+| SNAPSHOT_NAME | SNAPSHOT_TYPE | CREATED_TIME | FE_JOURNAL_ID | STARMGR_JOURNAL_ID | PROPERTIES | STORAGE_VOLUME | STORAGE_PATH |+------------------------------------------+---------------+---------------------+---------------+--------------------+------------+------------------------+---------------------------------------------------------------------------------------------------------------------------------+| automated_cluster_snapshot_1739857978127 | AUTOMATED | 2025-02-18 13:52:58 | 253 | 114 | | builtin_storage_volume | s3://xxx/7351ce6a-f4a4-4937-a876-cb8801085aea/meta/image/automated_cluster_snapshot_1739857978127 |+------------------------------------------+---------------+---------------------+---------------+--------------------+------------+------------------------+---------------------------------------------------------------------------------------------------------------------------------+
复制代码

注意:由于我们设置了每分钟执行一次备份,下面使用的备份路径可能与上文不同。最终结果可以通过 S3 查看。

s3cmd ls s3://xxx/data/7351ce6a-f4a4-4937-a876-cb8801085aea/meta/image/
sDIR s3://xxx/data/7351ce6a-f4a4-4937-a876-cb8801085aea/meta/image/automated_cluster_snapshot_1739858235830/
复制代码

删除已创建的集群

# 卸载 StarRocks 集群helm uninstall  starrocks
# 删除持久化的数据kubectl get pvc | awk '{if (NR>1){print $1}}' | xargs kubectl delete pvcpersistentvolumeclaim "cn-data-kube-starrocks-cn-0" deletedpersistentvolumeclaim "cn-log-kube-starrocks-cn-0" deletedpersistentvolumeclaim "fe-storage-log-kube-starrocks-fe-0" deletedpersistentvolumeclaim "fe-storage-log-kube-starrocks-fe-1" deletedpersistentvolumeclaim "fe-storage-log-kube-starrocks-fe-2" deletedpersistentvolumeclaim "fe-storage-meta-kube-starrocks-fe-0" deletedpersistentvolumeclaim "fe-storage-meta-kube-starrocks-fe-1" deletedpersistentvolumeclaim "fe-storage-meta-kube-starrocks-fe-2" deleted
复制代码

创建用于灾备的新集群

我们将复用之前的 starrocks-values.yaml 文件,因此请确保存储文件已妥善保存。接着,准备一个名为 cluster_snapshot.yaml 的新文件,其中的内容就是我们在灾备中需要配置的内容。

starrocks:  starrocksCluster:    disasterRecovery:      enabled: true      generation: 1      starrocksFESpec:    # mount the cluster_snapshot.yaml    configMaps:    - name: cluster-snapshot      mountPath: /opt/starrocks/fe/conf/cluster_snapshot.yaml      subPath: cluster_snapshot.yaml  configMaps:  - name: cluster-snapshot    data:      cluster_snapshot.yaml: |        # information about the cluster snapshot to be downloaded and restored        cluster_snapshot:            cluster_snapshot_path: s3://xxx/data/7351ce6a-f4a4-4937-a876-cb8801085aea/meta/image/automated_cluster_snapshot_1739858235830            storage_volume_name: builtin_storage_volume
# Operator will add the other FE followers automatically # just leave it blank frontends:[]
# Operator will add the CN nodes automatically # just leave it blank compute_nodes:[]
# used for restoring a cloned snapshot storage_volumes: - name: builtin_storage_volume type: S3 location: s3://xxx/data comment: my s3 volume properties: - key: aws.s3.region value: xxx - key: aws.s3.endpoint value: xxx - key: aws.s3.access_key value: xxx - key: aws.s3.secret_key value: xxx
复制代码

部署集群的命令与第一次不同,这里我们需要同时指定两个 YAML 文件,其中 cluster_snapshot.yaml 是专门用于本次灾备的配置文件。

helm install -f ./starrocks-values.yaml -f cluster_snapshot.yaml starrocks starrocks-community/kube-starrocks --version 1.10.0
复制代码

灾难恢复的详细流程如下:

  1. Operator 会启动一个 FE Pod,并启用灾难恢复。

# ignore the operator podkubectl get podsNAME                  READY   STATUS    RESTARTS        AGEkube-starrocks-fe-0   1/1     Running   0               4m37s
复制代码

此时,当我们检查 StarRocksCluster 的状态时,显示结果如下:

kubectl get src kube-starrocks -oyaml | less
status: phase: running disasterRecoveryStatus: observedGeneration: 1 phase: doing reason: disaster recovery is in progress startTimestamp: "1739860263"
复制代码
  1. 灾难恢复完成后,Operator 会自动启动其他 Pods。

kubectl get podsNAME                  READY   STATUS    RESTARTS        AGEkube-starrocks-cn-0   1/1     Running   0               7m54skube-starrocks-fe-0   1/1     Running   0               7m1skube-starrocks-fe-1   1/1     Running   0               7m54skube-starrocks-fe-2   1/1     Running   0               7m54s
复制代码

集群状态显示如下:

kubectl get src kube-starrocks -oyaml | less
status: phase: running disasterRecoveryStatus: endTimestamp: "1739861262" observedGeneration: 1 phase: done reason: disaster recovery is done startTimestamp: "1739860263"
复制代码

验证灾备是否成功

检查数据恢复是否完成。

# enter the podkubectl exec -it kube-starrocks-fe-0 bash
# connect mysqlmysql -h 127.0.0.1 -P9030 -urootWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 0Server version: 8.0.33 branch-3.4-12d148f
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
# get the datamysql> USE quickstart;Reading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -A
Database changedmysql> select * from source_wiki_edit;+---------------------+---------------+----------+--------------+----------+--------+----------+----------------+-------+-------+---------+| event_time | channel | user | is_anonymous | is_minor | is_new | is_robot | is_unpatrolled | delta | added | deleted |+---------------------+---------------+----------+--------------+----------+--------+----------+----------------+-------+-------+---------+| 2015-09-12 08:00:00 | #ca.wikipedia | helloSR | 0 | 1 | 0 | 1 | 0 | 3 | 23 | 0 || 2015-09-12 00:00:00 | #ca.wikipedia | helloSR | 0 | 1 | 0 | 1 | 0 | 3 | 23 | 0 || 2015-09-12 00:00:00 | #en.wikipedia | AustinFF | 0 | 0 | 0 | 0 | 0 | 21 | 5 | 0 |+---------------------+---------------+----------+--------------+----------+--------+----------+----------------+-------+-------+---------+3 rows in set (2.00 sec)
复制代码


用户头像

StarRocks

关注

新一代极速全场景MPP数据库 2020-08-08 加入

StarRocks一直致力于打造世界顶级的新一代极速全场景MPP数据库,帮助企业建立“极速统一”的数据分析新范式,助力企业数字化经营。当前已帮助腾讯、携程、顺丰、Airbnb等超过110家大型用户构建全新的数据分析能力。

评论

发布
暂无评论
Kubernetes 场景下的 StarRocks 灾备体系:Cluster Snapshot 实践解析_Kubernetes_StarRocks_InfoQ写作社区