Feast 架构内部机制详解:从 Python SDK 到 Kubernetes Operator 的组件与数据流
【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast
Feast(Feature Store for AI/ML)是一个开源特征存储系统,本文基于仓库内的.claude/skills/feast-architecture/SKILL.md架构技能文档,系统梳理 Feast 的完整组件地图:包括 Python SDK 核心(FeatureStore、Registry、Provider、Online/Offline Store)、四大核心数据流(apply、materialize、get_online_features、get_historical_features)、Python/Go 特征服务器、Kubernetes Operator 以及 Protobuf 序列化层。读完本文,你将能够准确回答"feast apply 如何工作、registry 如何存储元数据、materialization 如何搬移数据、get_online_features 如何检索特征、Kubernetes Operator 如何管理部署"等架构问题,并能直接定位到具体源码文件进行二次开发。
Feast 特征存储整体架构流程示意图
一、组件全景图:两种部署形态
Feast 支持两种部署形态,但共享同一套核心组件抽象(SKILL.md):
- 本地 / Python SDK 形态:以
feature_store.yaml为配置入口,在进程内构造FeatureStore对象,直接使用 Registry、Provider(内含 OnlineStore 与 OfflineStore)与 FeatureServer。 - Kubernetes 形态(feast-operator):以
FeatureStoreCR(自定义资源,CRD)描述期望状态,Operator 负责部署 feature-server(Go 或 Python)、offline-store-server、registry-server 等服务,并自动生成feature_store.yaml配置。
两种形态最终都汇聚到相同的核心抽象层,这是理解 Feast 内部机制的关键——"同一套代码,两种编排方式"。
二、Python SDK 核心:FeatureStore 作为总协调者
2.1 FeatureStore:唯一的操作入口
FeatureStore是全部操作的唯一入口,源码位于 sdk/python/feast/feature_store.py。从源码结构看(feature_store.py 中的方法定义),它从不直接读写数据,而是将职责委派给两个子系统:
- Registry:负责元数据(实体、特征视图、数据源、特征服务、权限的定义与持久化);
- Provider:负责基础设施生命周期与数据搬移(在线表创建/销毁、
online_write_batch、get_historical_features)。
典型用法:
from feast import FeatureStore store = FeatureStore(repo_path=".") # 加载 feature_store.yaml store.apply(objects) # 注册特征定义(apply) store.materialize(start_date, end_date) # 离线 → 在线 数据搬移 store.get_online_features(features, entity_rows) # 在线服务 store.get_historical_features(entity_df, features) # 训练数据生成FeatureStore的完整方法面(可参考 feature_store.py 中的定义列表)还包括materialize_incremental、push、write_to_online_store、serve、plan、teardown等,覆盖了特征注册、物化、在线写入、服务启动与清理全生命周期。
2.2 RepoConfig:feature_store.yaml 的类型化解析
sdk/python/feast/repo_config.py 负责把feature_store.yaml解析为类型化的RepoConfig。所有组件类(online store、offline store、registry)都通过配置中的type:字符串动态加载:
repo_config.ONLINE_STORE_CLASS_FOR_TYPE:online store 类型 → 类路径映射(另含LEGACY_ONLINE_STORE_CLASS_FOR_TYPE兼容旧命名);OFFLINE_STORE_CLASS_FOR_TYPE/OFFLINE_STORE_TYPE_MAP:offline store 类型映射;DATA_SOURCE_CLASS_FOR_TYPE:数据源类型映射;get_registry_config_from_type、get_batch_engine_config_from_type、get_auth_config_from_type等辅助函数负责各子配置的按类型解析。
这意味着新增一个存储后端,本质上就是"实现接口 + 注册类型映射"两步,见下文离线/在线存储章节。
三、Registry:元数据注册中心
3.1 职责与后端
Registry 是元数据存储,持久化 entities、feature views、data sources、feature services、permissions 的定义。四种内置后端及源码位置:
| 后端 | 源码文件 | 说明 |
|---|---|---|
| File/GCS/S3(默认) | sdk/python/feast/infra/registry/registry.py(Store 实现见同目录file.py、gcs.py、s3.py) | 单个 proto blob,内存缓存 |
| SQL | sdk/python/feast/infra/registry/sql.py | 按对象建表,SQLAlchemy 访问 |
| Snowflake | sdk/python/feast/infra/registry/snowflake.py | Snowflake 表 |
| Remote | sdk/python/feast/infra/registry/remote.py | 通过 gRPC 委托给远端 registry server |
Registry store 的类型解析也支持按 URL scheme 自动匹配:REGISTRY_STORE_CLASS_FOR_SCHEME(gs/s3/file/hdfs/空)映射到对应的 store 类(见 registry.py)。
3.2 proto/file 后端的工作机制
- 所有元数据被序列化进一个
Registryprotobuf(定义见 protos/feast/core/Registry.proto); - 该 proto blob 写入配置的
registry:路径(本地文件、GCS 或 S3 对象); - 内存中的
cached_registry_proto按 TTL 刷新(默认 10 秒); - 写入时整体重新序列化并覆盖整个 blob——没有部分更新。
3.3 apply 的核心模式
# Python 对象 → proto → 写入 registry blob registry.apply_feature_view(feature_view, project) # → feature_view.to_proto() # → upserts into cached_registry_proto.feature_views # → registry_store.update_registry_proto(proto)apply_feature_view的幂等更新、apply_diff_to_registry(sdk/python/feast/diff/registry_diff.py)负责将 diff 落盘。
3.4 SQL 后端:ProtoBytes 的坑与诊断
SQL 后端按对象建表,每张表用二进制列存储序列化后的 proto。这里有一个重要的实现陷阱(sql.py 中的注释明确记录):
- 二进制 proto 列必须使用
ProtoBytes,不能直接用LargeBinary。ProtoBytes在 MySQL/MariaDB 上映射为LONGBLOB(上限 4GB),在其他方言上回退为LargeBinary默认类型(SQLite 上为BLOB,PostgreSQL 上为BYTEA)。 - 直接用
LargeBinary在 MySQL 上会映射为BLOB(64KB 上限),大的 proto(例如一个FeatureView)会被静默截断,之后反序列化失败。任何新增的"序列化 proto/blob 元数据"列若误用LargeBinary,都会静默复现该 bug。 - 所有表都声明在 sql.py 模块级
metadata对象上(权威来源)。metadata.create_all只创建缺失的表,从不扩宽已有列,因此对既有 registry 的 schema 变更需要手动迁移(见 docs/reference/registries/sql.md)。 - 在 MySQL/MariaDB 上,
SqlRegistry._warn_if_narrow_blob_columns(sql.py)启动时会以 ERROR 级别记录任何仍为窄BLOB的 registry proto 列,提示执行ALTER TABLE ... MODIFY ... LONGBLOB迁移。该诊断只按column.type is ProtoBytes的身份判断筛选列——新列只要类型是ProtoBytes就会被自动覆盖;若误用普通LargeBinary则会被静默漏过。
3.5 支撑文件
- sdk/python/feast/infra/registry/base_registry.py:抽象接口;
- sdk/python/feast/infra/registry/proto_registry_utils.py:proto 序列化辅助;
- sdk/python/feast/infra/registry/caching_registry.py:在任意后端之上叠加 TTL 缓存。从该文件源码可见,每次读操作都会调用
_refresh_cached_registry_if_necessary(),通过cached_registry_proto_ttl(默认由cache_ttl_seconds决定)判断缓存是否过期,过期时借助_refresh_lock非阻塞锁执行刷新。
四、Provider:基础设施生命周期
Provider 的职责是基础设施生命周期管理——创建/更新/销毁在线存储表,同时分发online_write_batch和get_historical_features。抽象类定义在 sdk/python/feast/infra/provider.py。
内置 provider(通过feature_store.yaml的provider:字段设置):
local:SQLite 在线存储 + 文件离线存储(开发环境默认);gcp:Datastore/Bigtable 在线存储 + BigQuery 离线存储;aws:DynamoDB 在线存储 + Redshift 离线存储。
自定义 provider 需要继承Provider并覆写update_infra/teardown_infra。provider 的类型注册映射PROVIDERS_CLASS_FOR_TYPE也位于 provider.py(gcp/aws/local/azure 均指向PassthroughProvider,另有unity_catalog提供者)。
五、Online Store:低延迟在线特征服务
在线存储保存每个实体键对应的最新特征值,面向低延迟推理。
- 接口:sdk/python/feast/infra/online_stores/online_store.py
- 实现:sdk/python/feast/infra/online_stores/(redis、dynamodb、sqlite、bigtable、postgres、snowflake 等)
关键方法:
online_write_batch:写入 entity → feature 值;online_read:按实体键读取;update:在feast apply时创建/释放表;teardown:在feast teardown时清理。
实体键的序列化逻辑集中在 sdk/python/feast/infra/online_stores/helpers.py。
六、Offline Store:历史特征与训练数据
离线存储面向历史特征检索与训练数据生成(点对时间 join,point-in-time join)。
- 接口:sdk/python/feast/infra/offline_stores/offline_store.py
- 实现:sdk/python/feast/infra/offline_stores/(bigquery、snowflake、redshift、duckdb、file 等)
- PIT join 共享逻辑:sdk/python/feast/infra/offline_stores/offline_utils.py
离线检索返回惰性RetrievalJob——在调用.to_df()或.to_arrow()之前不会真正移动数据。
新增一个离线后端需要实现的方法签名:
class MyOfflineStore(OfflineStore): def get_historical_features(self, config, feature_views, feature_refs, entity_df, registry, project, ...) -> RetrievalJob: ... def pull_latest_from_table_or_query(self, config, data_source, join_key_columns, feature_name_columns, timestamp_field, created_timestamp_column, start_date, end_date) -> RetrievalJob: ... def pull_all_from_table_or_query(self, config, data_source, join_key_columns, feature_name_columns, timestamp_field, start_date, end_date) -> RetrievalJob: ... def write_logged_features(self, config, data, source, logging_config, registry) -> None: ... # 可选配套工作:
- Config 类:继承
FeastConfigBaseModel,用typeLiteral 声明短别名与完整点路径,并在 sdk/python/feast/repo_config.py 的OFFLINE_STORE_TYPE_MAP中注册; - 数据源:每个离线后端与一个
DataSource子类配对(如BigQuerySource、FileSource),放入 sdk/python/feast/data_sources/,并在DATA_SOURCE_CLASS_FOR_TYPE中注册。
七、四大核心数据流
7.1 feast apply:注册与建表
feast apply (CLI → repo_operations.py) ├── Parse Python files → collect FeastObjects ├── store.apply(objects) │ ├── diff against registry (diff/registry_diff.py) │ ├── update registry metadata for changed objects │ └── provider.update_infra(tables_to_keep, tables_to_delete) │ └── online_store.update(...) ← create/drop tables └── Write updated registry to storageCLI 侧的执行入口在 sdk/python/feast/repo_operations.py(parse_repo、apply_total等),diff 逻辑在 sdk/python/feast/diff/registry_diff.py(diff_between、apply_diff_to_registry),基础设施 diff 在 sdk/python/feast/diff/infra_diff.py。
7.2 feast materialize:离线 → 在线
store.materialize(start_date, end_date) ├── Load feature views from registry ├── For each feature view: │ ├── offline_store.pull_latest_from_table_or_query(...) │ │ └── Returns RetrievalJob (lazy) │ ├── job.to_arrow() ← executes query, fetches Arrow table │ └── provider.online_write_batch(...) │ └── online_store.online_write_batch(config, table, data, progress) └── Update last_updated_timestamp in registryFeatureStore.materialize的具体实现(含_materialize_fvs_batch、tqdm进度条、OpenLineage/MLflow 埋点)见 feature_store.py。
7.3 get_online_features:在线推理
store.get_online_features(features, entity_rows) ├── Resolve feature refs → FeatureViews from registry ├── online_store.online_read(config, table, entity_rows, requested_features) │ └── Deserialize ValueProto → Python dict ├── Apply OnDemandFeatureView transformations (if any) └── Return OnlineFeaturesResponse响应封装OnlineResponse(sdk/python/feast/online_response.py)提供to_dict()/to_df()/to_arrow()/to_tensor()等转换;OnDemand 变换的响应增强逻辑在 sdk/python/feast/utils.py(_augment_response_with_on_demand_transforms)。
7.4 get_historical_features:训练数据
store.get_historical_features(entity_df, features) ├── Resolve feature refs → FeatureViews from registry ├── offline_store.get_historical_features(config, feature_views, entity_df) │ └── Point-in-time join: │ for each entity row, find latest values where │ event_timestamp ≤ entity_df.event_timestamp │ (prevents data leakage in training) └── Returns RetrievalJob → .to_df() / .to_arrow()PIT join 的核心约束是"取event_timestamp ≤ entity_df.event_timestamp的最新值",从机制上防止训练阶段的数据泄漏。PIT 相关 SQL 模板与工具函数位于 offline_utils.py。
八、特征服务器(Feature Server)
8.1 Python Feature Server(FastAPI)
源码:sdk/python/feast/feature_server.py。这是一个包装FeatureStore的 FastAPI 应用,通过feast serve启动。从该文件的get_app/lifespan源码可见:应用启动时加载feature_store.yaml、创建FeatureStore,并通过后台异步定时器周期刷新 registry(registry_ttl_sec参数控制,默认 60 秒)。
主要端点:
POST /get-online-features:在线特征检索;POST /push:向在线/离线存储推送特征;POST /materialize:触发物化(支持async、force查询参数);GET /health:健康检查。
feast serve的 CLI 参数(host、port、type_、workers、max_requests、tls 证书路径、metrics 等)定义在 sdk/python/feast/cli.py 与 sdk/python/feast/serve.py。
8.2 Go Feature Server
- 目录:go/
- 入口:go/main.go
Go 特征服务器是 Python 版的高性能替代实现,支持 HTTP、HTTPS、gRPC 三种传输方式:
go run go/main.go -type http -port 6566 go run go/main.go -type grpc -port 6566从 go/main.go 的命令行参数可看到还支持-host、-metrics-port(默认 9090,Prometheus 指标)、-tls-cert-file/-tls-key-file(HTTPS)、-chdir(指定 feature store yaml 所在目录)以及 OpenTelemetry 链路追踪初始化。
关键包:
- go/internal/feast/:FeatureStore 的 Go 移植(读取 feature_store.yaml、调用在线存储);
- go/internal/feast/server/:HTTP 与 gRPC 服务实现;
- go/internal/feast/server/logging/:向离线存储写特征日志(feature logging)。
需要特别说明的边界:Go 服务器直接读取 registry(proto 文件或远端)并调用在线存储,不支持feast apply和 materialization——这两者仍是 Python 专属能力。
九、Feast Operator(Kubernetes)
- 目录:infra/feast-operator/
- 语言:Go(controller-runtime / kubebuilder)
Operator 通过FeatureStore自定义资源(CRD)管理 Feast 在 Kubernetes 上的完整生命周期。
9.1 CRD:FeatureStore
- API 版本:
feast.dev/v1 - 类型定义:infra/feast-operator/api/v1/featurestore_types.go
apiVersion: feast.dev/v1 kind: FeatureStore metadata: name: my-feast spec: feastProjectName: my_project services: offlineStore: persistence: file: type: dask onlineStore: persistence: store: type: redis secretRef: name: redis-credentials registry: local: persistence: file: path: /data/registry.db9.2 Operator 管理的内容
| 服务 | 部署内容 |
|---|---|
| 在线存储服务器 | feature server(Go 或 Python)的 Deployment + Service |
| 离线存储服务器 | 离线特征服务器的 Deployment + Service |
| Registry 服务器 | registry gRPC 服务器的 Deployment + Service |
| feature_store.yaml | 由 CR spec 自动生成的 ConfigMap |
| 物化任务 | CronJob(spec.services.onlineStore.cronJob) |
| TLS | 通过spec.services.*.tls管理证书 |
| 鉴权 | 通过spec.authz配置 OIDC / Kubernetes RBAC |
9.3 协调循环(Reconcile Loop)
控制器位于 infra/feast-operator/internal/controller/featurestore_controller.go,FeatureStoreReconciler.Reconcile方法在每次 CR 变更时执行:
- 获取
FeatureStoreCR; - 调用
deployFeast()→ 创建/更新 Deployments、Services、ConfigMaps; - 更新 CR 状态条件(
OfflineStore、OnlineStore、Registry的就绪条件); - 监听自有资源,任何变化触发重新协调。
各服务的具体部署逻辑集中在 infra/feast-operator/internal/controller/services/。
十、序列化层:一切皆 Proto
所有持久化元数据与特征服务器线格式都使用Protocol Buffers:
Python object (FeatureView, Entity, ...) ├── .to_proto() → Protobuf message → stored in registry or sent over gRPC └── .from_proto() ← Protobuf message Proto 定义: protos/feast/core/ # registry 对象(FeatureView、Entity、DataSource 等) protos/feast/serving/ # serving API(GetOnlineFeaturesRequest/Response) protos/feast/types/ # Value、EntityKey、Field例如 protos/feast/core/Registry.proto 是 registry 对象(含 FeatureView/Entity 等的集合)的根消息。
当需要为 Feast 对象新增字段时:
- 更新
.proto文件; - 运行
make compile-protos-python(如需 Go 侧同步运行make compile-protos-go); - 更新 Python 类中的
.to_proto()与.from_proto()。
十一、关键文件速查表
| 关注点 | 关键文件 |
|---|---|
| 用户面 Python API | sdk/python/feast/feature_store.py |
| 配置解析 | sdk/python/feast/repo_config.py |
feast applyCLI 逻辑 | sdk/python/feast/repo_operations.py |
| Registry diff | sdk/python/feast/diff/registry_diff.py |
| Registry(proto/file) | sdk/python/feast/infra/registry/registry.py |
| Registry(SQL) | sdk/python/feast/infra/registry/sql.py |
| PIT join | sdk/python/feast/infra/offline_stores/offline_utils.py |
| 在线存储接口 | sdk/python/feast/infra/online_stores/online_store.py |
| 实体键序列化 | sdk/python/feast/infra/online_stores/helpers.py |
| Python 特征服务器 | sdk/python/feast/feature_server.py |
| Go 特征服务器 | go/main.go、go/internal/feast/server/ |
| Operator CRD 类型 | infra/feast-operator/api/v1/featurestore_types.go |
| Operator 控制器 | infra/feast-operator/internal/controller/featurestore_controller.go |
| Operator 服务逻辑 | infra/feast-operator/internal/controller/services/ |
| Proto 定义 | protos/feast/ |
| Web UI | ui/(React) |
十二、进一步阅读:官方架构文档
仓库的 docs/ 目录提供了与本文互补的、面向用户的架构文档:
| 主题 | 文档 |
|---|---|
| 架构总览 | docs/getting-started/architecture/overview.md |
| Push vs Pull 模型 | docs/getting-started/architecture/push-vs-pull-model.md |
| 写入模式 | docs/getting-started/architecture/write-patterns.md |
| 特征转换 | docs/getting-started/architecture/feature-transformation.md |
| RBAC / 鉴权 | docs/getting-started/architecture/rbac.md |
| 在线存储组件 | docs/getting-started/components/online-store.md |
| 离线存储组件 | docs/getting-started/components/offline-store.md |
| Registry 组件 | docs/getting-started/components/registry.md |
| 特征服务器组件 | docs/getting-started/components/feature-server.md |
| Provider 组件 | docs/getting-started/components/provider.md |
| 计算引擎 | docs/getting-started/components/compute-engine.md |
| 设计决策记录(ADR) | docs/adr/ |
总结
Feast 的内部架构可以概括为一条清晰的分层线索:feature_store.yaml→RepoConfig类型化配置 →FeatureStore统一入口 → Registry(元数据)+ Provider(Online/Offline Store 与数据搬移)→ Feature Server(Python FastAPI 或 Go gRPC/HTTP)→ 可选 Kubernetes Operator 编排。四条核心数据流(apply、materialize、在线检索、历史检索)贯穿其中,全部持久化与线格式基于 Protobuf。无论是排查"feast apply 为什么不建表"、理解"materialize 为什么走 Arrow"、定位 SQL registry 的 64KB 截断问题,还是为 Feast 贡献一个新的存储后端,本文梳理的组件边界与源码坐标都能帮助你快速进入正确的代码位置。
【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考