news 2026/9/17 11:29:58

GreptimeDB 分布式元数据服务 meta-srv 架构深度解析:心跳、选举、分布式过程与配置实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GreptimeDB 分布式元数据服务 meta-srv 架构深度解析:心跳、选举、分布式过程与配置实战

GreptimeDB 分布式元数据服务 meta-srv 架构深度解析:心跳、选举、分布式过程与配置实战

【免费下载链接】greptimedbThe open-source observability database. One columnar engine for metrics, logs, and traces, on object storage.项目地址: https://gitcode.com/GitHub_Trending/gr/greptimedb

GreptimeDB 采用存算分离的分布式架构,而meta-srv正是这套集群的"元数据大脑":它持久化集群/表/Region 元数据、负责 Leader 选举、驱动心跳循环追踪集群拓扑,并编排 DDL、Region 迁移、Repartition 等分布式过程。本文以 src/meta-srv/AGENTS.md 为核心脉络,结合meta-srvcrate 源码与 config/metasrv.example.toml 真实配置,系统讲解其模块划分、核心流程、配置项语义、公开接口与测试方法,帮助你理解并维护 GreptimeDB 的元数据服务层。

meta-srv 在整个项目中的定位

在分布式模式下,GreptimeDB 由 Frontend、Datanode、Flownode 与 MetaSrv 共同组成。meta-srv承担元数据与协调职能,具体包括:

  • 持久化集群/表/Region 元数据:所有元数据以 KV 形式写入后端存储(默认 etcd),跨节点共享;
  • Leader 选举:在多个 MetaSrv 副本之间选出唯一 Leader,保证写操作一致性;
  • 心跳循环与集群拓扑追踪:通过 Frontend/Datanode/Flownode 上报的心跳维护节点存活状态与集群拓扑;
  • 分布式过程编排:DDL(建表/删表等)、Region 迁移、Repartition 等操作以可恢复的过程(Procedure)形式执行。

从 crate 依赖来看,数据模型、KV 后端抽象、选举、Key 编码与 DDL 管理器都实现在common-metacrate 中;meta-srv在其之上实现服务端、状态机与控制逻辑。分层遵循仓库级架构约束(见 .agents/architecture-invariants.md 中"common-* 不能反向依赖 storage engine、frontend、datanode、meta-srv"的约定),meta-srv通过common-metacommon-procedure等基础 crate 协作,而不是重复实现元数据模型。

模块地图:meta-srv 源码导航

meta-srv的源码全部位于 src/meta-srv/src,AGENTS.md 给出了清晰的模块导航表。下面按模块逐一说明其职责与关键文件:

模块路径职责
bootstrapsrc/meta-srv/src/bootstrap.rs组装 KV 后端、选举、gRPC 服务与过程管理器,完成进程启动
metasrvsrc/meta-srv/src/metasrv.rs、src/meta-srv/src/metasrv/builder.rsMetasrv结构体、MetasrvOptions配置、MetasrvBuilder构建器与启动逻辑
statesrc/meta-srv/src/state.rsLeader/Follower 状态机与状态迁移
handlersrc/meta-srv/src/handler/心跳处理器链(HeartbeatHandler):Leader 检查、Region 租约、统计、信箱
servicesrc/meta-srv/src/service/gRPC 服务(heartbeat、procedure、cluster、store)与 HTTP admin 接口
proceduresrc/meta-srv/src/procedure/分布式过程:region_migration/repartition.rswal_prune/
regionsrc/meta-srv/src/region/Region 监督器、租约维护、故障转移触发
discoverysrc/meta-srv/src/discovery/节点发现与基于租约的节点信息
pubsubsrc/meta-srv/src/pubsub/心跳主题的发布/订阅支持
gcsrc/meta-srv/src/gc/元数据驱动的垃圾回收过程与调度
selectorsrc/meta-srv/src/selector/Region 放置策略(round-robin / load-based / lease-based)
peersrc/meta-srv/src/peer.rs通过 selector 分配 Peer
clustersrc/meta-srv/src/cluster.rsMetaPeerClient:带 Leader 回退的内部 RPC
cache_invalidatorsrc/meta-srv/src/cache_invalidator.rs向 Frontend/Datanode 推送缓存失效通知
keysrc/meta-srv/src/key/MetaSrv 侧的 KV Key 编码

bootstrap:启动装配与 gRPC 路由

bootstrap.rs中的MetasrvInstance::start()是进程启动的核心入口:先启动 HTTP 服务,再通过router()函数装配 gRPC 服务。从 src/meta-srv/src/bootstrap.rs 可以看出,gRPC 路由依次注册了五个服务,且全部开启 Gzip/Zstd 压缩与消息大小限制:

  • HeartbeatServer:心跳服务,接收 Frontend/Datanode/Flownode 的心跳流;
  • StoreServer:元数据 KV 读写服务;
  • ClusterServer:集群管理服务;
  • ProcedureServiceServer:过程执行服务;
  • ConfigServer:配置下发服务;
  • admin::make_admin_service:兼容旧版的 admin 服务。

后端选择逻辑见metasrv_builder()(src/meta-srv/src/bootstrap.rs):根据opts.backend决定使用MemoryKvBackend(测试用)、EtcdStore(默认,并同时构造EtcdElection)或 PostgreSQL/MySQL(需要对应 feature)。

state:Leader/Follower 状态机

src/meta-srv/src/state.rs 中有一段 ASCII 状态图,完整描述了状态迁移路径:

+------------------------------+ | | v | +-------------------v--------------------+ | | LeaderState{enable_leader_cache:false} | | +-------------------+--------------------+ | | | +---------v---------+ | | Init Leader Cache | | +---------+---------+ | | | +-------------------v-------------------+ | | LeaderState{enable_leader_cache:true} | | +-------------------+-------------------+ | | | +-------v-------+ | | FollowerState | | +-------+-------+ | | | +------------------------------+

关键语义:新 Leader 上任时先进入enable_leader_cache: false状态(此时禁用 Leader 缓存),完成缓存初始化后切换为enable_leader_cache: true;一旦发生 Leader 变更则回退为FollowerStatebecome_leader()become_follower()两个函数(src/meta-srv/src/state.rs)正是上述迁移的具体实现。这正是 AGENTS.md 中"Leader 使用在 Leader 变更时重置的缓存 KV 后端(LeaderCachedKvBackend)"这一注意事项的状态机体现。

核心流程:四条主线

AGENTS.md 归纳了四条核心流程,下面结合源码逐一展开。

心跳流程(Heartbeat)

心跳是集群拓扑感知的基础。service/heartbeat.rs中的HeartbeatSession维护一条 gRPC 双向流:

  1. 收到首个心跳请求后校验RequestHeader,并向HeartbeatHandlerGroup注册 pusher(src/meta-srv/src/service/heartbeat.rs);
  2. 循环select两条事件:流上新的心跳消息、或 Leader 下台事件(wait_leader_step_down)。一旦通过选举订阅收到LeaderChangeMessage::StepDown,立即向客户端返回 "not leader" 错误并终止会话(src/meta-srv/src/service/heartbeat.rs);
  3. 响应中携带信箱(mailbox)消息,用于下发 DDL 结果、缓存失效等指令。

每个心跳请求会顺序穿过handler/下的处理器链。从 src/meta-srv/src/handler.rs 的add_default_handlers()可以看到默认链的完整组成(顺序即执行顺序):

  1. ResponseHeaderHandler— 写入响应头;
  2. DatanodeKeepLeaseHandler/FlownodeKeepLeaseHandler— 续租节点租约;
  3. CheckLeaderHandler— 仅 Leader 处理,非 Leader 返回 "not leader";
  4. OnLeaderStartHandler— Leader 上任初始化;
  5. ExtractStatHandler— 提取节点统计;
  6. CollectDatanodeClusterInfoHandler/CollectFrontendClusterInfoHandler/CollectFlownodeClusterInfoHandler— 采集各角色集群信息;
  7. MailboxHandler— 处理信箱消息;
  8. RegionLeaseHandler— Region 租约续期(条件挂载);
  9. FilterInactiveRegionStatsHandler— 过滤非活跃 Region 统计;
  10. RegionFailureHandler— Region 故障处理(开启 failover 时挂载);
  11. PublishHeartbeatHandler— 向 pubsub 发布心跳(开启时挂载);
  12. CollectLeaderRegionHandler— 采集 Leader Region 信息;
  13. CollectTopicStatsHandler— 采集 WAL 主题统计;
  14. PersistStatsHandler— 持久化统计(开启时挂载);
  15. CollectStatsHandler— 汇总统计(基于flush_stats_factor触发刷写);
  16. RemapFlowPeerHandler— 流(Flow)Peer 重映射;
  17. FlowStateHandler— 流状态处理(条件挂载)。

该构建器还提供add_handler_after/add_handler_before/add_handler_last三个扩展点,并支持通过HeartbeatHandlerGroupBuilderCustomizer插件化定制链,测试与扩展都围绕这套机制展开。

DDL 流程

DDL 由 src/meta-srv/src/service/procedure.rs 暴露,是Leader-only的:非 Leader 节点会返回 "not leader"。Leader 收到 DDL 请求后交给common-metaDdlManager处理,并经由common-procedure以可恢复过程的形式执行。这意味着 DDL 状态会被持久化到 KV 后端,节点崩溃后可恢复继续执行。

Region 迁移流程

Region 迁移由 src/meta-srv/src/procedure/region_migration/manager.rs 以及region_migration/目录下的分步文件实现。从目录结构看,迁移被拆分为多个步骤:

  • migration_start.rs/migration_end.rs/migration_abort.rs— 迁移的启停与中止;
  • downgrade_leader_region.rs/flush_leader_region.rs/close_downgraded_region.rs— 旧 Leader Region 降级与刷盘关闭;
  • open_candidate_region.rs/upgrade_candidate_region.rs— 候选 Region 打开与升级;
  • update_metadata.rs及其子步骤(upgrade_candidate_regiondowngrade_leader_regionrollback_downgraded_region)— 元数据更新与回滚。

迁移可以由故障转移触发,也可以通过显式命令发起;其状态机定义与执行步骤可进一步参考 src/meta-srv/src/procedure/region_migration.rs。

Leader 选举流程

选举能力来自common-meta的 election 抽象(etcd 后端对应EtcdElection),meta-srv侧的状态迁移集中在 src/meta-srv/src/state.rs。当选时become_leader()触发 Leader 缓存初始化;失选时become_follower()回退状态并重置 Leader 缓存,从而保证新的 Leader 从 KV 后端重建内存视图。

MetasrvOptions 配置详解

配置结构体MetasrvOptions定义在 src/meta-srv/src/metasrv.rs,完整示例见 config/metasrv.example.toml。下面按主题分组解读核心配置项。

元数据后端(backend / store_addrs)

  • backend:元数据存储实现,对应BackendImpl枚举(src/meta-srv/src/metasrv.rs),取值包括etcd_store(默认)、memory_store(测试用)、postgres_storemysql_store(需编译对应 featurepg_kvbackend/mysql_kvbackend);
  • store_addrs:后端地址列表。etcd 为"host:port"列表;PostgreSQL 为 libpq 连接串或 URI;MySQL 为连接 URL;
  • store_key_prefix:非空时所有 KV key 加此前缀,用于多个 meta-srv 集群共享同一存储;
  • max_txn_ops:单事务最大操作数,默认 128,应小于 etcd 的--max-txn-ops
  • backend_client:后端客户端保活与连接超时(keep_alive_timeout=3s、keep_alive_interval=10s、connect_timeout=3s);
  • backend_tls:KV 后端的 TLS 配置,支持disable/prefer/require/verify_ca/verify_full五种模式。

心跳与故障转移(heartbeat / failover)

  • heartbeat_interval:基础心跳间隔,用于推导分布式时间常量,例如 Region 租约时长约为heartbeat_interval * 3 + 1s。Frontend 的心跳间隔是基础间隔的 6 倍,Datanode/Flownode 为 1 倍;心跳间隔在握手阶段由 MetaSrv 协商下发,节点本地配置不会覆盖它;
  • enable_region_failover:是否启用 Region 故障转移,仅在使用 Remote WAL + 共享存储(如 S3)的集群模式下可用;
  • region_failure_detector_initialization_delay:Region 故障检测启动前的延迟(默认 10 分钟),避免 Datanode 尚未全部就绪时误触发 failover,对未使用 GreptimeDB Operator 且未开启维护模式的部署尤为重要;
  • allow_region_failover_on_local_wal:是否允许本地 WAL 场景下的 Region failover,官方不建议开启,可能造成数据丢失;
  • node_max_idle_time:节点信息从 MetaSrv 内存移除前的最大空闲时间(默认 24h)。

状态机与过程(state / procedure)

  • [procedure]:过程执行配置。max_retry_times=12(最大重试次数)、retry_delay=500ms(初始重试延迟,指数递增)、max_metadata_value_size=1500KiB(etcd 单请求上限 1.5 MiB 减去 36KiB key 保留空间)、max_running_procedures=128(并发过程上限,超出即拒绝)。

故障检测(failure_detector)

MetaSrv 使用Phi Accrual Failure Detector算法检测 Datanode 故障:

  • threshold(默认 8.0):判定 Peer 故障的 φ 阈值,越小反应越快但误报越多;
  • min_std_deviation(默认 100ms):心跳间隔的最小标准差,防止间隔几乎不变时 φ 爆炸;
  • acceptable_heartbeat_pause(默认 10000ms):心跳间可接受的暂停时长,为学习到的平均间隔追加额外宽限期,吸收网络抖动与 GC 暂停。

Region 放置(selector)

selector决定 Region 放置在哪个 Peer 上,支持三种策略:

  • round_robin(默认):轮询分配;
  • lease_based:基于租约;
  • load_based:基于负载。

对应实现见 src/meta-srv/src/selector/:round_robin.rsload_based.rslease_based.rs,以及weight_compute.rs/weighted_choose.rs提供的加权计算。修改 selector 时需注意与RegionStatAwareSelector消费的统计字段保持一致(见下文"修改关联")。

统计持久化与 GC(stats / gc)

  • [stats_persistence]ttl默认0s(关闭持久化,大于 0 时开启,建议小值如3h);interval默认10m,低于10m会被强制覆盖为10m
  • [gc]enable=false默认关闭,且必须与 Datanode 的mito.gc.enable保持一致;gc_cooldown_period=5m为同一 Region 两次 GC 之间的冷却期。

事件记录与遥测(event_recorder / telemetry)

  • [event_recorder]:事件表 TTL 默认90devent_types为空数组时禁用记录,省略时记录全部当前与未来事件类型(如region_migrationcreate_tablerepartitionwal_prunebatch_gc等);
  • enable_telemetry:默认开启 GreptimeDB 遥测。

gRPC / HTTP 监听

  • [grpc]bind_addr(默认127.0.0.1:3002)、server_addr(向 Frontend/Datanode 通告的地址,留空则自动取主机第一网卡 IP 加同端口)、runtime_sizemax_recv/send_message_size、HTTP/2 keep-alive 参数;
  • [http]addr(默认127.0.0.1:4000)、timeoutbody_limit(默认64MB)。

WAL 配置(wal)

MetaSrv 在 Kafka 作为远端 WAL 时需要同步配置[wal]

  • providerraft_engine(默认)或kafka
  • Kafka 相关:broker_endpointsauto_create_topicsnum_topics=64topic_name_prefixreplication_factorselector_type、SASL/TLS;
  • auto_prune_interval=30m:自动清理远端 WAL 的间隔,0s关闭;auto_prune_logical_delete用于不支持 DeleteRecords 的 Kafka 部署;
  • flush_trigger_size=512MB/checkpoint_trigger_size=128MB:基于(latest_entry_id - flushed_entry_id) * avg_record_size估算的刷盘/检查点触发阈值,0表示由系统自行决定。

公开接口:客户端与 Admin API

AGENTS.md 明确指出对外接口分两侧:

  • 客户端侧:统一使用meta-clientcrate 的MetaClient,封装了对 MetaSrv 各 gRPC 服务的调用;
  • 服务端侧:入口是 src/meta-srv/src/service/ 下的 gRPC 服务(heartbeat、procedure、cluster、store),以及 src/meta-srv/src/service/admin/ 下的 HTTP admin API。

从 admin 目录可看到一组实用的运维接口:health(健康检查)、leader(查看当前 Leader)、procedure(过程管理)、maintenance(维护模式)、recovery(恢复)、node_lease(节点租约)、sequencer(序列号)、heartbeat(心跳调试)等。

修改代码时的联动关系

AGENTS.md 的"When you change X, also touch Y"部分给出了高度可操作的联动清单,这既是维护契约,也是理解模块耦合的捷径:

  • 心跳间隔 / 租约:时间常量定义在common-metadistributed_time_constants(源码中可见BASE_HEARTBEAT_INTERVALfrontend_heartbeat_interval等引用,见 src/meta-srv/src/metasrv.rs);修改它会同时影响handler/region_lease_handler.rs的租约续期与region/supervisor.rs的故障判定。
  • 过程(Procedure):状态必须持久化在 KV 后端,且execute()必须幂等,才能保证崩溃恢复正确(这与 .agents/architecture-invariants.md 的持久化格式兼容性约束一致)。
  • 缓存失效:新增元数据类型时,需要在cache_invalidator.rs与心跳发布处理器(PublishHeartbeatHandler)中同步补充失效逻辑。
  • Selector 统计字段selector/的实现必须与其消费的统计字段保持同步,否则 Region 放置会读到错误数据。

测试方法

AGENTS.md 给出了标准的测试命令:

# 运行 meta-srv 的全部测试 cargo nextest run -p meta-srv # 使用 mock 选举 / KV 后端(更快的单元测试) cargo nextest run -p meta-srv --features mock

mockfeature 在 src/meta-srv/Cargo.toml 中声明,可避免依赖真实 etcd。测试基础设施还包括三个辅助文件:

  • src/meta-srv/src/mocks.rs — 各类 mock 组件;
  • src/meta-srv/src/test_util.rs — 通用测试工具;
  • src/meta-srv/src/procedure/test_util.rs — 过程测试工具。

此外,handler.rs的测试模块中大量使用HeartbeatHandlerGroupBuilder::new(...).add_default_handlers()组装真实处理器链,并通过add_handler_after/add_handler_before注入自定义处理器,验证链的顺序与扩展点行为(src/meta-srv/src/handler.rs)。

常见陷阱(Gotchas)

AGENTS.md 总结了三个最容易踩坑的点,也是 review 与排障的检查清单:

  1. 写操作必须 Leader-only:绝大多数变更操作只允许 Leader 执行,handler/service/procedure.rs中都有对应的 Leader 检查;非 Leader 节点统一返回 "not leader"。心跳会话中若监听到 Leader 下台也会主动断开(见 src/meta-srv/src/service/heartbeat.rs)。
  2. 内存状态不可持久:Leader 变更后需要保留的任何状态都必须写入 KV 后端;Leader 使用LeaderCachedKvBackend,该缓存会在 Leader 变更时重置。
  3. 租约时序必须协调:Region 租约续期节奏与 supervisor 的检查间隔必须协调,否则同一个 Region 可能同时出现在两个 Datanode 上(双活脑裂)。

维护契约:何时更新 AGENTS.md

AGENTS.md 本身也是一份需要随代码演进的活文档,其维护契约要求:新增过程(procedure)、修改心跳处理器链、变更 Leader-only 边界、或调整 metasrv 与 common-meta 的分工时,必须同步更新本文件。对贡献者而言,遵循该契约可以确保这份导航文档始终与实际代码结构一致,这也是本仓库将 crate 级 AGENTS.md 作为协作规范的一部分(其余仓库级规范见 .agents/README.md 与 .agents/architecture-invariants.md)。

小结

meta-srv是 GreptimeDB 分布式模式的控制面核心,其设计呈现出清晰的"分层 + 状态机 + 过程化"特征:元数据模型下沉到common-meta,服务与状态机在meta-srv,分布式操作全部以可恢复过程执行,心跳链则通过可定制的处理器组完成拓扑感知与指令下发。理解模块地图、四条核心流程、MetasrvOptions配置语义以及联动修改清单,是深入参与 meta-srv 开发与运维的第一步;配合cargo nextest run -p meta-srv与 mock feature,你可以快速验证改动而不必依赖真实集群。

【免费下载链接】greptimedbThe open-source observability database. One columnar engine for metrics, logs, and traces, on object storage.项目地址: https://gitcode.com/GitHub_Trending/gr/greptimedb

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 11:28:28

Intel Vortex NPU调用与DCIM配置实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 11:27:25

用Dify搭建多语言PDF原格式翻译流水线:拆译合查全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 11:22:07

PMSM无感启动全速域控制:破解0-50rpm观测盲区

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华