ARTICLE DETAIL

资讯详情

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

Quickwit Metastore 本地开发指南:PostgreSQL 与 File-backed 双实现的测试、迁移与演进实践

Quickwit Metastore 本地开发指南:PostgreSQL 与 File-backed 双实现的测试、迁移与演进实践 Quickwit Metastore 本地开发指南PostgreSQL 与 File-backed 双实现的测试、迁移与演进实践【免费下载链接】quickwitCloud-native OSS search engine for observability项目地址: https://gitcode.com/GitHub_Trending/qu/quickwit本篇技术指南以 quickwit-metastore 模块 为核心系统讲解 Quickwit云原生可观测性搜索引擎元数据存储层的本地开发全流程如何用 Docker 快速拉起 PostgreSQL 测试环境、如何分别运行 File-backed 与 PostgreSQL 两套后端的测试、如何使用 sqlx-cli 管理 schema 迁移以及 deferred migrations延迟迁移机制的设计原理与编写规则。读完本文你将能独立搭建 quickwit-metastore 的开发与测试环境理解其迁移流水线并为该模块贡献或调试代码。一、quickwit-metastore 模块定位quickwit-metastore是 Quickwit 中用于持久化索引元数据的抽象层。从 crate 根文档 可以看到它负责屏蔽不同 metastore 实现的差异目前提供两种后端File-backed metastore文件后端元数据以文件形式存储适用于单机、开发调试场景PostgreSQL metastore数据库后端官方推荐用于分布式部署场景。该层维护的元数据包括索引配置index configuration、每个 split 的元信息ID、文档数、大小、min/max 时间戳、标签集合、各数据源的 checkpoint以及索引创建时间等附加信息详见 metastore 配置文档。从源码结构看MetastoreResolver 负责根据metastore_uri的协议前缀将请求分发到对应工厂MetastoreFactory 是构建MetastoreServiceClient的 trait 抽象其中postgres后端只有在编译期开启postgresfeature 时才会注册见 metastore_resolver.rs否则会注册一个返回UnsupportedBackend错误的占位实现。理解这一点就能明白为什么测试命令要区分cargo test与cargo test --featurespostgres。二、本地启动 PostgreSQL 测试环境README 提供的第一个命令是启动一个本地 PostgreSQL 服务器用于测试 postgres metastore 实现docker-compose up postgres该服务定义在仓库根目录的 docker-compose.yml 中关键配置如下配置项值镜像postgres:${POSTGRES_VERSION:-12.17-alpine}默认锁定最低受支持版本端口映射${MAP_HOST_POSTGRES:-127.0.0.1}:5432:5432默认只绑定本机回环地址用户${POSTGRES_USER:-quickwit-dev}密码${POSTGRES_PASSWORD:-quickwit-dev}数据库${POSTGRES_DB:-quickwit-metastore-dev}数据目录PGDATA/var/lib/postgresql/data/pgdata数据卷postgres_data:/var/lib/postgresql/data健康检查pg_isready1 秒间隔、最多重试 100 次docker-compose 文件头部注释docker-compose.yml特别说明关键服务如 postgres、pulsar会刻意运行在最老的支持版本上以验证向后兼容如需使用最新镜像版本可修改.env文件覆盖POSTGRES_VERSION等变量但要注意旧数据卷可能与新版本不兼容。数据持久化与清理README 明确指出PostgreSQL 的数据保存在数据卷volume中两次运行之间不会被自动清理。也就是说上一次测试遗留的库表会保留下来这是有意为之——避免每次启动都重新建表。清理命令在 README 中写作make rm-postgres需要说明的是在当前仓库的 Makefile 中对应的实际目标是docker-rm-postgres-volume其执行内容为docker volume rm quickwit_postgres_data此外make docker-clean见 Makefile也会连同 azurite、fake GCS、grafana、localstack 等开发服务的 volume 一并清理。你可以根据实际仓库的 Makefile 目标选择对应的清理命令。三、测试 quickwit-metastore从纯文件后端到 PostgreSQL3.1 仅测试 FileBackedMetastore如果只想运行不依赖外部服务的文件后端测试直接在quickwit项目根目录执行cargo test此命令运行quickwit-metastorecrate 的单元测试此时postgresfeature 处于关闭状态测试只覆盖FileBackedMetastore。从 lib.rs 可以看到测试模式下会通过metastore_for_test()构造一个基于RamStorage内存存储的FileBackedMetastore客户端因此纯文件后端测试完全不需要任何外部进程。3.2 测试包含 PostgresqlMetastore要测试 PostgreSQL 后端需要先启动 PostgreSQL。README 给出的标准做法是在项目根目录使用 Makefile 封装make docker-compose-up DOCKER_SERVICESpostgresdocker-compose-up目标Makefile会设置COMPOSE_PROFILESpostgres并执行docker compose up -d --remove-orphans --wait通过 compose profile 只启动postgres这一个服务并等待其健康检查通过后再返回。PostgreSQL 就绪后运行cargo test --featurespostgres--featurespostgres会启用 Cargo.toml 中定义的 feature它级联开启quickwit-proto/postgres、quickwit-parquet-engine/postgres并引入sea-query、sea-query-binder、sqlx等数据库相关依赖。只有开启该 featurePostgresqlMetastore才会被编译见 lib.rs相关集成测试也才会执行。测试结束后停止并移除 PostgreSQL 容器docker-compose down从源码看metastore 的测试覆盖相当全面tests 目录 下包含index.rs、split.rs、delete_task.rs、source.rs、template.rs、shard.rs、metrics.rs、list_splits.rs、get_identity.rs等测试模块覆盖了索引生命周期、split 管理、删除任务、源 checkpoint、模板、分片、指标等核心路径backward_compatibility_tests 则利用 test-data 下的历史版本 JSON 快照如 v0.7/v0.8/v0.9验证新旧数据格式的兼容性。四、sqlx-cli 与迁移工作流PostgreSQL 后端的 schema 演进由sqlx迁移框架管理。README 建议但非必需安装 sqlx-cli 来手工操作迁移cargo install sqlx-cli安装完成后可以用以下命令**应用run或回滚revert**常规迁移。迁移源目录为migrations/postgresql数据库连接串为postgres://quickwit-dev:quickwit-devlocalhost:5432/quickwit-metastore-devsqlx migrate run --database-url postgres://quickwit-dev:quickwit-devlocalhost:5432/quickwit-metastore-dev --source migrations/postgresql sqlx migrate revert --database-url postgres://quickwit-dev:quickwit-devlocalhost:5432/quickwit-metastore-dev --source migrations/postgresql这两条命令分别用于在开发数据库上应用最新迁移、或回滚最近一次迁移适合在修改迁移文件后反复验证。对于延迟迁移deferred migrations则使用另一个迁移源目录sqlx migrate run --database-url postgres://quickwit-dev:quickwit-devlocalhost:5432/quickwit-metastore-dev --source migrations/postgresql_deferred迁移文件组织方式migrations/postgresql下的迁移采用成对的 up/down 文件组织目前已有编号 1 至 28 的常规迁移例如1_create-indexes.up.sql/1_create-indexes.down.sql创建indexes表、update_timestamp触发器函数并兼容旧版 diesel 迁移见 1_create-indexes.up.sql2_create-splits.up.sql/2_create-splits.down.sql创建splits表含split_id主键、split_state、time_range_start/end、tags TEXT[]、split_metadata_json等字段并通过触发器在 split 变更时联动更新所属索引的update_timestamp见 2_create-splits.up.sql后续迁移按需为表增加字段如publish_timestamp、incarnation_id、maturity_timestamp、node_id、创建新表delete_tasks、templates、metrics_splits、sketch_splits或调整主键与唯一索引如 22/23 号迁移。这种编号递增 up/down 对称的模式保证了 schema 可以双向演进也便于 sqlx-cli 追踪当前版本。五、Deferred migrations长耗时迁移的优雅降级方案5.1 为什么需要 deferred migrations常规迁移要求在启动时同步、快速地完成因此不适合承载CREATE INDEX CONCURRENTLY这类长时间运行、且不能放在事务块内的 DDL。为此Quickwit 引入了第二个迁移目录migrations/postgresql_deferred专门存放这类长耗时、允许优雅降级的迁移。其设计约束在 deferred migrations 说明 中有明确记载版本号全局唯一两个目录共享同一张_sqlx_migrations表因此版本号必须跨目录延续同一条编号序列当前常规迁移到 28deferred 从 29 开始必须幂等每条迁移在任何中断场景下都必须可以安全重放不能依赖未发布的常规迁移常规迁移绝不允许依赖 deferred 迁移的结果。5.2 后台任务 Postgres advisory lock 的选举机制deferred migrations 的运行时实现位于 migrator.rs常规迁移在run()中同步执行run_required见 migrator.rsdeferred 迁移则在就绪readiness之后通过quickwit_common::spawn_named_task派发一个名为postgres_deferred_migrations的后台任务执行见 migrator.rs为避免多个 metastore 节点pod同时执行长迁移后台任务先通过SELECT pg_try_advisory_lock($1, $2)竞争一把 Postgres advisory lock锁键是硬编码的魔数424242和1789见 migrator.rs。拿到锁的节点成为迁移领导者负责执行拿不到锁的节点打印deferred PostgreSQL migrations handled by another node后直接退出见 migrator.rs关键实现细节执行前会把连接从连接池detach()出来让 advisory lock 绑定在单个会话上——PostgreSQL 会在会话结束或连接断开时自动释放该锁即使迁移执行期间发生 panic 或失败也不会造成锁泄漏见 migrator.rs。执行结果通过指标DEFERRED_MIGRATIONS_APPLY带success/failure标签对外暴露便于运维监控。5.3 幂等编写规则与真实示例deferred 迁移的编写有一个硬性要求凡是不能在事务中执行的语句如CREATE INDEX CONCURRENTLY文件首行必须标注-- no-transaction之后直接写 DDL。由于concurrently模式下每条语句自动提交迁移中途被 kill 后必须能安全重跑。以实际的 29 号 deferred 迁移 为例它为核心压缩器compaction planner的扫描路径在splits表上创建一个(maturity_timestamp, split_id)的 B-tree 部分索引-- no-transaction CREATE INDEX CONCURRENTLY IF NOT EXISTS splits_maturity_timestamp_idx ON splits (maturity_timestamp, split_id);该 SQL 文件的注释详细解释了设计考量planner 每个 tick 都要读取split_state Published且maturity_timestamp now()的 split 并按时间升序取LIMIT因此 B-tree 可以让 PostgreSQL 直接按索引顺序 seek 到尚未成熟的时间范围免去额外的排序split_id作为决胜列保证LIMIT分页的确定性部分索引谓词必须是 IMMUTABLE所以不能用now()出现在谓词中而只能靠maturity_timestamp now()的查询条件配合。对应的回滚迁移同样以-- no-transaction开头并使用DROP INDEX CONCURRENTLY IF EXISTS见 29 号 down 迁移。deferred 说明文档还提醒了几个运维要点如果某条迁移执行失败CREATE INDEX CONCURRENTLY可能留下一个无效invalid索引且不会在迁移表中登记记录因此需要手工清理后再重试文档也记录了一个经验教训——曾经尝试在迁移 SQL 内部先清理无效索引但两条独立语句会被 PostgreSQL 隐式包进一个事务块反而覆盖了-- no-transaction指令使concurrently无法工作因此该方案被放弃。六、从源码看 metastore 的接入与演进保障6.1 URI 协议到后端的分发metastore_uri是 Metastore 的唯一配置入口。在 metastore_resolver.rs 中可以看到协议映射规则azure://、gs://、file://、ram://、s3://→File-backed后端底层复用对象存储postgres://、postgresql://→PostgreSQL后端其他协议 → 返回UnsupportedBackend错误。其中postgres与postgresql两种协议前缀均被接受这一点在 resolver 测试 中有明确断言。测试默认连接串为postgres://quickwit-dev:quickwit-devlocalhost/quickwit-metastore-dev可通过环境变量QW_TEST_DATABASE_URL覆盖。另外resolver 还提供了resolve_read_only()方法用于解析只读连接适用于从库/读副本场景该能力仅 PostgreSQL 后端支持——若对 file 后端调用会直接报错且只读连接上执行写操作如create_index会收到Forbidden错误见 resolver 测试。6.2 生产配置要点补充参考虽然本指南聚焦开发测试但理解生产配置有助于反向理解测试环境的默认值。根据 metastore 配置文档PostgreSQL URI 格式为postgres://[user]:[password][host]:[port]/[dbname]部分参数可省略但数据库必须预先创建Quickwit 首次启动时会自动建表升级时会在启动阶段自动执行迁移每个运行 metastore 服务的节点维护独立连接池默认metastore.postgres.max_connections为 10因此节点最多承载2 * max_connections 20个在途请求排池时需保证metastore_nodes * max_connections低于 PostgreSQL 连接数上限file-backed 后端每个索引一个元数据文件路径为[storage_uri]/[index_id]/metastore.json可通过#polling_interval30sURI 片段开启轮询刷新仅支持秒注意 file-backed 后端没有锁机制同一时刻只允许一个实例运行。七、开发自检清单完成阅读后建议按以下清单快速自检环境docker-compose up postgres可正常拉起 PostgreSQL容器健康检查通过未启动数据库时cargo test全绿只覆盖 File-backed 后端启动数据库后make docker-compose-up DOCKER_SERVICESpostgres再跑cargo test --featurespostgres全绿覆盖 PostgreSQL 后端新增迁移时常规迁移放在migrations/postgresql长耗时/不可事务化的 DDL 放在migrations/postgresql_deferred编号全局递增、up/down 成对、-- no-transaction正确标注、语句幂等用 sqlx-cli 对本地库反复run/revert验证迁移可双向执行结束时docker-compose down如需彻底重置数据卷再执行make docker-rm-postgres-volumeREADME 中写作make rm-postgres。通过上述流程你可以在不污染任何共享环境的前提下独立完成 quickwit-metastore 的测试、迁移开发与调试并为该模块的后续演进打下坚实基础。【免费下载链接】quickwitCloud-native OSS search engine for observability项目地址: https://gitcode.com/GitHub_Trending/qu/quickwit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表