ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OGX 存储层完全指南:KVStore 与 SqlStore 架构、多后端配置与租户安全模型

OGX 存储层完全指南:KVStore 与 SqlStore 架构、多后端配置与租户安全模型 OGX 存储层完全指南KVStore 与 SqlStore 架构、多后端配置与租户安全模型【免费下载链接】ogxOpen GenAI Stack项目地址: https://gitcode.com/GitHub_Trending/ll/ogxOGXOpen GenAI Stack的存储子系统位于 src/ogx/core/storage/它以KV 键值存储 SQL 关系存储双轨架构支撑着分布注册表、配额中间件、Provider 状态持久化、推理历史Chat Completions 日志、会话、提示词等核心数据的读写。阅读本文后你将掌握 StorageConfig 的完整配置方法SQLite/Redis/PostgreSQL/MongoDB 六种后端、KVStore 与 SqlStore 两套接口的底层实现以及 AuthorizedSqlStore 的租户隔离与 ABAC 双层访问控制原理并学会通过inference.enabled精确控制推理日志的持久化开关。存储层全景KV 与 SQL 双轨架构从 storage 目录结构可以看到整个存储子系统分为两大模块storage/ kvstore/ # Key-value store backends config.py # KVStore config classes kvstore.py # KVStore factory and base implementation sqlite/ # SQLite KV backend (aiosqlite) redis/ # Redis KV backend postgres/ # PostgreSQL KV backend mongodb/ # MongoDB KV backend sqlstore/ # SQL store backends (SQLAlchemy-based) sqlstore.py # SqlStore factory and config sqlalchemy_sqlstore.py # SQLAlchemy implementation authorized_sqlstore.py # SqlStore with access control datatypes.py # Storage config types两者的设计分工非常明确KVStore面向简单键值读写场景get、set、delete、按范围枚举键值值一律是字符串通常为 JSON 序列化后的内容键支持命名空间namespace前缀隔离SqlStore面向类型化表格操作场景支持列定义ColumnDefinition、过滤where、分页cursor/limit、排序order_by基于 SQLAlchemy 实现以保持数据库可移植性。这种双轨设计让不同的数据特性各得其所需要高吞吐、低延迟的分布式状态如分布注册表、Provider 状态走 KV 路径需要结构化查询与关联的历史数据推理日志、会话、提示词走 SQL 路径。KVStore轻量键值接口与四种后端实现接口定义KVStore 是一个 PythonProtocol鸭子类型接口定义在 src/ogx_api/internal/kvstore.pyclass KVStore(Protocol): async def set(self, key: str, value: str, expiration: datetime | None None) - None: ... async def get(self, key: str) - str | None: ... async def delete(self, key: str) - None: ... async def values_in_range(self, start_key: str, end_key: str) - list[str]: ... async def keys_in_range(self, start_key: str, end_key: str) - list[str]: ... async def shutdown(self) - None: ...接口亮点在于值类型为字符串set写入的 value 是str实际使用时通常承载 JSON 序列化后的对象由调用方负责编解码可选的过期时间expiration: datetime | None支持 TTL 语义各后端实现方式不同SQLite 存 TIMESTAMP 并在查询时过滤、Redis 用EXPIREAT范围查询values_in_range/keys_in_range以键的字典序区间 [start_key, end_key) 枚举数据这一能力被分布注册表等场景用于按前缀扫描。四种后端与配置参数KVStore 支持 SQLite默认、Redis、PostgreSQL、MongoDB 四种后端全部在 datatypes.py 中通过StorageBackendType枚举注册kv_redis、kv_sqlite、kv_postgres、kv_mongodb。各后端的配置类继承自CommonConfig其中namespace字段为公共项All keys will be prefixed with this namespace所有键都会带上此前缀。后端类型配置类关键字段默认值kv_sqliteSqliteKVStoreConfigdb_path数据库文件路径必填由环境变量SQLITE_STORE_DIR决定目录kv_redisRedisKVStoreConfighost/portlocalhost/6379连接串为redis://{host}:{port}kv_postgresPostgresKVStoreConfighost/port/db/user/password/ssl_mode/ca_cert_path/table_name/pool_size/max_overflow/command_timeoutlocalhost/5432/ogx/ogxtable_nameogx_kvstorepool_size5max_overflow10command_timeout30.0kv_mongodbMongoDBKVStoreConfighost/port/db/user/password/collection_namelocalhost/27017/ogxcollection_nameogx_kvstore需要特别注意的是 PostgreSQL KV 后端对表名的强校验见 datatypes.py表名必须以字母或下划线开头、只能包含字母数字和下划线且长度不超过 63 字节PostgreSQL 标识符规则不满足会直接抛ValueError。从源码实现看各后端的差异点kvstore/SQLitesqlite.py底层表结构为kvstore(key TEXT PRIMARY KEY, value TEXT, expiration TIMESTAMP)文件型数据库采用每操作一连接避免挂起内存库:memory:或modememory才使用持久连接get查询时用WHERE key ? AND (expiration IS NULL OR expiration ?)过滤过期键。Redisredis.pyset之后若有 expiration 则调用EXPIREAT范围查询通过SCAN游标迭代 MGET批量取值实现。PostgreSQL / MongoDB分别依赖asyncpg与pymongo驱动配置类提供sample_run_config()类方法生成带环境变量默认值的示例配置。工厂与实例缓存kvstore.py 中的register_kvstore_backends()与kvstore_impl()构成了注册 按引用取实例的工厂模式启动时register_kvstore_backends(backends)将StorageConfig.backends中的命名后端灌入全局注册表kvstore_impl(reference)以(backend_name, namespace)为缓存键通过asyncio.Lock保证并发下只初始化一次实例化时用config.model_copy()深拷贝配置并把引用中的 namespace 写入副本再按配置类型分支选择具体实现类并调用initialize()除四种持久后端外源码还提供了InmemoryKVStoreImplkvstore.py专门用于测试与临时内存场景。SqlStore类型化表操作与 SQLAlchemy 实现接口定义SqlStore 同样是一个 Protocolsrc/ogx_api/internal/sqlstore.py提供比 KVStore 丰富得多的表格语义class SqlStore(Protocol): async def create_table(self, table: str, schema: Mapping[str, ColumnType | ColumnDefinition]) - None: ... async def create_index(self, index_name: str, table: str, columns: Sequence[str]) - None: ... async def insert(self, table: str, data: Mapping[str, Any] | Sequence[Mapping[str, Any]]) - None: ... async def upsert(self, table, data, conflict_columns, update_columnsNone, ...) - None: ... async def fetch_all(self, table, whereNone, where_sqlNone, where_sql_paramsNone, limitNone, order_byNone, cursorNone) - PaginatedResponse: ... async def fetch_one(self, table, whereNone, order_byNone, ...) - dict[str, Any] | None: ... async def update(self, table, data, where, ...) - None: ... async def delete(self, table, where, ...) - None: ... async def delete_many(self, operations: Sequence[DeleteOperation]) - None: ... async def add_column_if_not_exists(self, table, column_name, column_type, nullableTrue) - None: ... async def shutdown(self) - None: ...配套的列类型枚举ColumnType定义了七种受支持的类型INTEGER、STRING、TEXT、FLOAT、BOOLEAN、JSON、DATETIMEsqlstore.py。注意fetch_all返回的是PaginatedResponse含data与has_more字段分页通过cursor元组驱动这是 OGX API 统一的分页语义。SQLAlchemy 实现与后端配置sqlalchemy_sqlstore.py 中维护了TYPE_MAPPING将ColumnType映射到 SQLAlchemy 列类型Integer、String、Float、Boolean、DateTime、Text、JSON并针对 SQLite/PostgreSQL 分别使用各自方言的insertsqlite_insert/pg_insert以实现 upsert。SqlStore 仅支持 SQLite默认与 PostgreSQL 两种后端配置类为后端类型配置类关键字段默认值 / 说明sql_sqliteSqliteSqlStoreConfigdb_path必填engine 串为sqliteaiosqlite:///{db_path}sql_postgresPostgresSqlStoreConfighost/port/db/user/password/ssl_mode/ca_cert_path/pool_size/max_overflow/pool_recycle/pool_pre_pingpool_size10max_overflow20pool_recycle3600秒-1 禁用pool_pre_pingTruePostgreSQL 的ssl_mode取值严格限定为disable、allow、prefer、require、verify-ca、verify-full六档见 datatypes.py配合ca_cert_path即可对接云端受管数据库的 TLS 要求engine 串通过URL.create(drivernamepostgresqlasyncpg, ...)构造全程异步驱动。与 KVStore 类似的sqlstore.py 提供register_sqlstore_backends()注册后端并以backend_name为键缓存实例。其中get_system_sqlstore()返回无访问控制过滤的裸 SqlStore专用于基础设施表如跨进程共享的 job 队列面向用户数据的读写必须走authorized_sqlstore()见下文。AuthorizedSqlStore租户隔离 ABAC 双层强制authorized_sqlstore.py 中的AuthorizedSqlStore是 API 层获取 SQL 存储的唯一正规途径authorized_sqlstore()工厂函数注释明确说明 This is the only supported way to obtain a SQL store for API use。它在底层 SqlStore 之上叠加了两层强制逻辑作用于每一次操作第一层租户隔离Tenant Isolation当启用了租户模式single或multi时create_table会为每张表自动追加tenant_id列见 authorized_sqlstore.py所有写入insert/upsert通过_enhance_item_with_access_control()打上当前认证用户的tenant_id同时剥离客户端提交的tenant_id字段Never trust client-supplied access control fields所有读取与变更fetch_all/fetch_one/update/delete都会拼接一个不可绕过的WHERE tenant_id ?过滤条件_build_tenant_filter()见 authorized_sqlstore.pymulti 模式下的默认拒绝当请求缺少租户上下文时过滤条件退化为10直接返回空结果——宁可少返回也绝不越租户single 模式无租户上下文的请求回退到进程级default_tenant_idupsert额外做租户冲突检查_check_tenant_conflict_for_upsert若冲突键命中的是其他租户的行则抛ConflictError防止跨租户覆盖。第二层ABAC 访问控制在租户边界之内owner_principal与access_attributes两列承载基于策略的访问规则例如user is owner。其实现要点写路径自动捕获属主insert/upsert自动把当前用户的principal写入owner_principal、把其属性写入access_attributes客户端无法伪造这两个字段读路径双层过滤先构建 SQL 层的 WHERE 条件_build_access_control_where_clause再用is_action_allowed()逐行做内存级精确判定SqlRecord包装为ProtectedResourceSQL 过滤优化当策略恰为默认策略SQL_OPTIMIZED_POLICY用户在任意属性类别的 owners 列表中即放行时会生成参数化 SQL 直接下推过滤PostgreSQL 用-/-/jsonb SQLite 用JSON_EXTRACT与json_each自定义策略则退化为保守模式只过滤 100% 确定应拒绝的记录避免误伤变更操作的属主冻结update/upsert会从update_columns中剔除owner_principal、access_attributes启用租户时还有tenant_id即更新记录不会转移所有权。租户模式的进程级配置README 指出租户模式在启动时通过 stack.py 的set_default_tenancy_config()进程级设置——该函数在 stack 初始化阶段被调用register_kvstore_backends(kv_backends)、register_sqlstore_backends(sql_backends)之后紧跟set_default_tenancy_config(run_config.server.tenancy)把run.yaml中server.tenancy的配置注入全局默认值。AuthorizedSqlStore在tenancy_modeNone时自动读取该进程级默认authorized_sqlstore.py。配置实战StorageConfig 从 run.yaml 到代码存储配置位于StackConfig.storage类型为StorageConfigdatatypes.py由两个字段构成backends命名后端配置字典key 是自定义后端名如kv_default、sql_defaultvalue 是六种后端配置之一按type判别字段区分storesServerStoresConfig把逻辑存储名映射到后端引用。ServerStoresConfig预置了七个逻辑存储槽位datatypes.py下表列出了每个槽位的默认引用后端 表名/命名空间逻辑存储引用类型默认 backend默认 table_name / namespacemetadataKVStoreReferencekv_defaultnamespaceregistryinferenceInferenceStoreReferencesql_defaulttableinference_storeconversationsSqlStoreReferencesql_defaulttableopenai_conversationsresponsesResponsesStoreReferenceNone默认 tableopenai_responsespromptsSqlStoreReferencesql_defaulttablepromptsconnectorsSqlStoreReferencesql_defaulttableconnectorsvector_storesSqlStoreReferenceNone向量库元数据两类引用的区别datatypes.pyKVStoreReference(backend 名, namespace)namespace 是所有键的前缀用于在共享 KV 后端内做逻辑隔离SqlStoreReference(backend 名, table_name)table_name 指定该存储使用的表。如果未显式配置backendsStorageConfig的default_factory会构造kv_defaultkv_sqlitekvstore.db与sql_defaultsql_sqlitesql_store.db两个默认后端目录由环境变量SQLITE_STORE_DIR决定datatypes.py。仓库中 benchmarking/rag/config.yaml 提供了一个可直接对照的完整真实配置示例storage: backends: kv_default: type: kv_sqlite db_path: ${env.SQLITE_STORE_DIR:~/.ogx/distributions/rag-benchmarks}/kvstore.db sql_default: type: sql_sqlite db_path: ${env.SQLITE_STORE_DIR:~/.ogx/distributions/rag-benchmarks}/sql_store.db stores: metadata: namespace: registry backend: kv_default inference: table_name: inference_store backend: sql_default max_write_queue_size: 10000 num_writers: 4 conversations: table_name: openai_conversations backend: sql_default prompts: namespace: prompts backend: kv_default connectors: namespace: connectors backend: kv_default要点解读db_path使用了${env.SQLITE_STORE_DIR:...}形式的环境变量注入:表示未设置时使用默认值这与其他 run.yaml 配置保持一致max_write_queue_size: 10000与num_writers: 4是_QueuedSqlStoreReference提供的后台写入队列调优参数datatypes.py推理日志、responses 等高吞吐写入会先进入内存队列由num_writers个并发后台 writer 异步落库避免阻塞请求路径生产级多后端方案参考 benchmarking/k8s-benchmark/stack_run_config.yamltype: sql_postgres可据此把 SQL 后端切换为 PostgreSQL。Inference Store 的 enabled 开关精确控制推理日志持久化InferenceStoreReference在 SQL 引用之上增加了enabled: bool True字段datatypes.py这是 README 重点强调的配置语义行为规则显式设置inference.enabled: false→禁用Chat Completions 持久化省略enabled字段或整个inference引用→保持启用向后兼容默认值为True把inference引用本身设为null→ 属于配置错误ServerStoresConfig.inference的类型为InferenceStoreReference | None但按语义不应置空。禁用后的具体效果不构造InferenceStore实例、不创建inference_store表、不启动任何后台写 worker流式streaming与非流式 Chat Completions照常工作只是不再持久化日志历史查询端点list、retrieve、messages返回HTTP 501明确告知持久化未配置其他存储responses、datasets、eval、files、prompts、vector_io完全不受影响——它们各自有独立的引用与表。这个开关非常适合以下场景追求极致的写入吞吐与低延迟、把推理日志托管到外部系统如遥测管道而不想在 OGX 内留存、或临时关闭持久化进行基准测试对比。总结OGX 的存储层用KV SQL 双轨给出了清晰的分层答案KVStore 以极简接口get/set/delete/范围查询和 SQLite/Redis/PostgreSQL/MongoDB 四种后端承载注册表、配额、Provider 状态等散列型数据SqlStore 以 SQLAlchemy 为底座提供类型化表操作承载推理日志、会话、提示词等结构化数据AuthorizedSqlStore则在两者之上统一注入租户隔离与 ABAC 访问控制并支持 SQL 下推过滤的性能优化。结合StorageConfig的backendsstores双层配置模型与inference.enabled粒度开关运维与开发者可以在开箱即用的 SQLite与生产级 PostgreSQL/Redis/MongoDB 多后端之间平滑迁移同时精确掌控每一类数据的持久化与安全边界。进一步阅读存储配置类型的完整定义见 datatypes.pyKVStore 工厂与实例缓存见 kvstore/kvstore.pySqlStore 工厂与 SQLAlchemy 实现见 sqlstore/sqlstore.py 与 sqlstore/sqlalchemy_sqlstore.py访问控制实现见 sqlstore/authorized_sqlstore.py进程级初始化装配见 core/stack.py。【免费下载链接】ogxOpen GenAI Stack项目地址: https://gitcode.com/GitHub_Trending/ll/ogx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表