时序数据库后端数据存储可观测性云原生【免费下载链接】mimirGrafana Mimir provides horizontally scalable, highly available, multi-tenant, long-term storage for Prometheus.项目地址https://gitcode.com/gh_mirrors/mimir/mimir点击查看免费下载Grafana Mimir 的 querier 是一个无状态组件负责在读取路径上执行 PromQL 查询长期存储中的历史数据并向 ingester 查询尚未落盘的最新数据。本文以官方架构文档 querier.md 为主线结合仓库源码深入讲解其工作原理、查询请求解剖、块一致性校验、hash ring 连接方式、元数据缓存以及关键配置项帮助读者在部署 Mimir 时正确配置并理解 querier 的查询行为。Querier 的定位与角色在 Mimir 的读路径架构中query-frontend、query-scheduler、querier、store-gateway 与 ingester 分工明确query-frontend接收客户端请求负责查询分片query sharding与结果缓存query-scheduler对拆分后的查询子请求进行排队调度querier真正执行 PromQL 求值从下游拉取时间序列与标签数据store-gateway有状态组件从长期存储中查询块数据详见 store-gateway.mdingester有状态组件持有最近写入、尚未上传到长期存储的内存数据。querier 本身不保存任何数据因此可以水平扩展、随时重启属于读路径上最容易伸缩的一环。工作原理bucket index 驱动的块发现要回答查询应该读取哪些块这一问题querier 依赖bucket index桶索引机制当 querier 收到某个租户的第一个查询时它才懒加载lazily download该租户的 bucket index随后在内存中缓存该索引并周期性地刷新保持最新。bucket index 中包含一个租户的块列表blocks与块删除标记block deletion marks。querier 正是基于这两类信息来确定当前查询时间范围内需要查询哪些块。源码印证在 blocks_finder_bucket_index.go 中BucketIndexBlocksFinder实现了BlocksFinder接口该接口定义于 blocks_store_queryable.go方法签名为GetBlocks(ctx, userID, minT, maxT)。其核心逻辑L85-L105遍历 bucket index 中所有块仅保留时间范围与[minT, maxT]有交集的块block.Within(minT, maxT)遍历删除标记若删除时间已超过配置的IgnoreDeletionMarksDelay则将该块从候选列表中剔除逻辑与 Thanos 的IgnoreDeletionMarkFilter一致返回候选块列表及其元数据。同时该 finder 还会做两类防御性检查bucket index 过期检查若time.Since(idx.GetUpdatedAt()) cfg.MaxStalePeriod返回BucketIndexTooOld错误L78-L80避免基于过期的索引做错误决策新租户无索引兜底若新租户尚未写入任何块、bucket index 尚未创建则返回空列表而不是报错L68-L72这是合法的边界场景。对应测试见 blocks_finder_bucket_index_test.go覆盖了正常查找、bucket index 不存在、索引损坏、索引过旧等场景。解剖一个查询请求当 querier 收到一个range query查询区间请求时请求中携带以下参数参数含义示例queryPromQL 查询表达式rate(node_cpu_seconds_total[1m])start查询起始时间2026-10-01 00:00:00end查询结束时间2026-10-01 01:00:00step查询分辨率时间步长30表示每 30 秒一个数据点查询执行的主流程定位块querier 根据start与end计算出所有在时间范围内至少包含一个样本的已知块列表定位 store-gateway对每个块基于 store-gateway hash ring 计算出持有该块的实例列表并向每个匹配的 store-gateway 发起请求拉取时间范围内匹配query表达式的序列样本请求/响应携带块 ID发给 store-gateway 的请求包含预期查询的块 ID 列表store-gateway 的响应则返回实际被查询的块 ID 列表。由于最近几秒内可能刚发生 blocks-resharding块重分片事件响应中的块 ID 列表可能是请求列表的子集一致性校验与重试querier 对 store-gateway 的响应做一致性校验确保所有预期块都已被查询。若存在缺失块querier 会向不同的store-gateway 重试拉取缺失块重试次数上限为-store-gateway.sharding-ring.replication-factor默认 3与 3 两者中的较小值失败即报错若所有重试后一致性校验仍失败查询执行失败。宁可查询失败也不返回不完整结果这是为了保证查询结果的正确性查询 ingester若查询时间范围与-querier.query-ingesters-within指定的时长有重叠querier 还会向 ingester 发起请求拉取尚未上传到长期存储、或尚未能被 store-gateway 查询到的样本求值返回当从 store-gateway 与 ingester 都拉取完样本后querier 运行 PromQL 引擎执行查询并向客户端返回结果。源码印证上述流程在源码中有完整的对应实现多数据源编排multiQuerierquerier.go同时持有了 ingester 侧distributor与块存储侧blockStore两个storage.Queryable。在getQueriers中通过ShouldQueryIngestersquerier.go判断是否应查询 ingester、通过ShouldQueryBlockStorequerier.go判断是否应查询块存储最终将两类 querier 收集后并发执行 Select 并合并结果mergeSeriesSetsquerier.go块定位与 store-gateway 选择blocksStoreReplicationSet.GetClientsForblocks_store_replicated_set.go对每个块通过mimir_tsdb.HashBlockID(block.ID)计算哈希并在 ring 上做GetWithOptions选择非排除exclude的实例并把块按实例分组、再按-querier.max-blocks-per-store-request分片最终返回客户端 → 块 ID 分区的映射一致性校验 重试循环queryWithConsistencyCheckblocks_store_queryable.go以for attempt : 1; attempt q.dynamicReplication.MaxReplicationFactor(); attempt循环重试每轮用consistencyTracker.Check(queriedBlocks)算出缺失块缺失块清零即成功返回循环结束后仍缺失则抛出newStoreConsistencyCheckFailedError。一致性校验的细节一致性校验的跟踪器实现在 blocks_consistency_checker.goNewTracker会跳过上传时间在uploadGracePeriod上传宽限期以内的块避免因 store-gateway 尚未发现刚上传的块而产生误报——此时块仍可从 ingester 或按删除标记延迟规则查询L41-L67Check统计所有被追踪块中尚未被任何一次Check确认查询到的缺失块L79-L98Complete在请求完成后上报两个指标cortex_querier_blocks_consistency_checks_total需做一致性校验的查询总数与cortex_querier_blocks_consistency_checks_failed_total校验失败总数L100-L107。注意若查询因其他错误如 context 取消中断则不计入一致性校验统计。query-ingesters-within 与 query-store-after 的配合-querier.query-ingesters-withinYAML 对应query_ingesters_within属于 runtime limits 范畴见 limits.go 与 limits.go与-querier.query-store-afterYAML 对应query_store_after见 querier.go共同决定新数据查 ingester、历史数据查 store-gateway的分界查询时间范围的末端落在query-ingesters-within窗口内 → 查询 ingester查询时间范围的起点早于now - query-store-after→ 查询块存储。原文档特别强调-querier.query-ingesters-within的取值必须同时大于以下两者-querier.query-store-afteringester 上传的块中最旧样本被发现并可被查询的预估最短时间。在默认配置下该预估值为3h。若违反该约束可能出现部分数据既没从 ingester 查到、也尚未在 store-gateway 可见的查询空洞。源码中通过ValidateLimits强制校验当QueryIngestersWithin ! 0 QueryStoreAfter ! 0时QueryStoreAfter必须小于QueryIngestersWithin否则返回errBadLookbackConfigs错误querier.go、errors.go从配置层面杜绝返回部分结果的可能。说明默认配置下-querier.query-store-after为12hquerier.go-querier.query-ingesters-within默认值为13hlimits.go满足上述约束。连接 store-gateway共享 hash ring 配置querier 需要通过 store-gateway hash ring 发现 store-gateway 实例的地址。因此必须用与 store-gateway 完全相同的-store-gateway.sharding-ring.*参数或对应的 YAML 配置来配置 querier。store-gateway 侧的 ring 关键参数定义于 gateway_ring.go参数默认值说明-store-gateway.sharding-ring.replication-factor3块的分片复制因子需在 store-gateway、querier、ruler 上保持一致-store-gateway.sharding-ring.heartbeat-period15s向 ring 发送心跳的周期-store-gateway.sharding-ring.heartbeat-timeout1m心跳超时超过后该 store-gateway 在 ring 中被视为不健康-store-gateway.sharding-ring.zone-awareness-enabledfalse是否启用跨可用区复制启用时需设置instance-availability-zone-store-gateway.sharding-ring.instance-availability-zone空实例所在的可用区启用 zone-awareness 时必填-store-gateway.sharding-ring.auto-forget-enabledtrue自动移除长期不健康实例该参数已废弃建议通过auto-forget-unhealthy-periods0禁用-store-gateway.sharding-ring.wait-stability-min-duration0启动时等待 ring 稳定的最短时间生产环境建议1m-store-gateway.sharding-ring.wait-stability-max-duration5m启动时等待 ring 稳定的最长时间超时则直接启动在 gateway_ring.go 中这些 flag 的 help 文本带有sharedOptionWithRingClient后缀This option needs be set both on the store-gateway, querier and ruler when running in microservices mode.微服务模式下需同时在 store-gateway、querier 与 ruler 上设置这正是原文档要求的代码级佐证。从 querier 侧看ring 客户端还额外提供-querier.ring.auto-forget-unhealthy-periods默认 10设为 0 可禁用自动遗忘见 querier_ring.go。重试与动态复制queryWithConsistencyCheck中的重试上限取自dynamicReplication.MaxReplicationFactor()。在未启用实验性的动态复制dynamic replication时该值即等于配置的replication-factor默认 3与原文档重试replication-factor次或最多 3 次取较小值的描述一致。动态复制接口定义于 dynamic_replication.go其思路是当块满足MaxTimeDynamicReplication的条件如 max time 足够新时可将块同步/查询到比默认复制因子更多的 store-gateway 上从而缩短新块可见延迟、降低查询失败概率。连接 ingester共享 ingester ring 配置同理querier 要发现 ingester 地址必须使用与 ingester 相同的-ingester.ring.*参数或对应的 YAML 配置。同时为降低读放大querier 在查询 ingester 时默认启用了最小化请求策略-querier.minimize-ingester-requests默认true见 querier.go先只查询达到法定人数所需的最少 ingester仅当这批 ingester 出现失败时才按-querier.minimize-ingester-requests-hedging-delay默认0延迟后补查其余 ingester。这在 happy path 上降低资源消耗但失败路径上可能增加延迟。缓存元数据缓存Metadata cache可缓存内容store-gateway 与 querier 可以共用 Memcached 来缓存以下桶元数据租户列表list of tenants每个租户的块列表list of blocks per tenant块的meta.json是否存在及其内容块的deletion-mark.json是否存在及其内容租户的bucket-index.json.gz内容。缓存这些元数据能显著减少对长期存储的 API 调用次数并且消除随 querier 与 store-gateway 副本数线性增长的 API 调用量——每增加一个副本都会重复拉取同一份元数据缓存让这些副本共享同一份结果。启用方式与相关参数通过设置-blocks-storage.bucket-store.metadata-cache.backend启用元数据缓存。注意目前 Mimir 仅支持memcached作为元数据缓存后端。Memcached 客户端还有额外配置通过前缀-blocks-storage.bucket-store.metadata-cache.memcached.*的 flag 提供。其他配置 flag 均以-blocks-storage.bucket-store.metadata-cache.*为前缀。将某项的 TTL 设为 0 或负值即可禁用该项的缓存。从源码 caching_config.go 可看到完整的 TTL 默认值Flag默认值含义-blocks-storage.bucket-store.metadata-cache.backend空禁用缓存后端目前仅支持memcached-blocks-storage.bucket-store.metadata-cache.tenants-list-ttl15m桶中租户列表的缓存时长-blocks-storage.bucket-store.metadata-cache.tenant-blocks-list-ttl5m每个租户块列表的缓存时长-blocks-storage.bucket-store.metadata-cache.chunks-list-ttl24h块的 chunk 列表缓存时长-blocks-storage.bucket-store.metadata-cache.metafile-exists-ttl2h块meta.json存在性信息的缓存时长也用于租户删除标记文件-blocks-storage.bucket-store.metadata-cache.metafile-doesnt-exist-ttl5m块meta.json不存在性信息的缓存时长-blocks-storage.bucket-store.metadata-cache.metafile-content-ttl24h块meta.json内容的缓存时长-blocks-storage.bucket-store.metadata-cache.metafile-max-size-bytes1MiB可缓存的最大元文件内容字节数超过则跳过缓存-blocks-storage.bucket-store.metadata-cache.metafile-attributes-ttl168h块元文件属性的缓存时长-blocks-storage.bucket-store.metadata-cache.block-index-attributes-ttl168h块索引属性的缓存时长-blocks-storage.bucket-store.metadata-cache.bucket-index-content-ttl5mbucket index 内容的缓存时长-blocks-storage.bucket-store.metadata-cache.bucket-index-max-size-bytes1MiB可缓存的 bucket index 最大字节数超过则跳过缓存重要store-gateway 与 querier 应使用同一个 Memcached 后端集群这样才能最大化命中率、避免重复向对象存储发起请求。元数据缓存的底层实现在 caching_config.go 中由BucketStoreConfig.MetadataCacheconfig.go统一承载store-gateway 与 querier 走的是同一套配置结构。生产环境建议缓存是可选配置但在生产环境中强烈推荐开启。除元数据缓存外store-gateway 侧还支持索引缓存index cache支持inmemory/memcached与 chunk 缓存仅memcached完整的缓存配置指引可参考 production tips。查询引擎与相关实验性配置从 querier.go 可以看到Mimir 支持两种查询引擎prometheus原生 Prometheus 查询引擎mimirMimir 自研的流式 PromQL 引擎streaming PromQL默认启用见 querier.go。当使用mimir引擎时-querier.enable-query-engine-fallback默认true见 querier.go保证了对 Mimir 引擎暂不支持的查询自动回退到 Prometheus 引擎执行。源码中New函数querier.go据此组装promql.QueryEngine并最终构建出multiQueryableingester 块存储的合并查询入口。其他值得关注的 querier 参数参数默认值说明-querier.query-store-after12h早于该时长的历史数据改由块存储查询见上文配合说明-querier.shuffle-sharding-ingesters-enabledtrue读取路径上仅查询可能持有该租户内存序列的最小 ingester 集合-querier.prefer-availability-zones空查询时优先使用的可用区列表逗号分隔各区域优先级相同-querier.streaming-chunks-per-ingester-series-buffer-size256从 ingester 流式拉取 chunk 时每实例缓冲的序列数-querier.streaming-chunks-per-store-gateway-series-buffer-size256从 store-gateway 流式拉取 chunk 时每实例缓冲的序列数-querier.max-concurrent-remote-read-queries2远程读remote read查询的并发上限0 或负值表示不限-querier.experimental-search-api-enabledfalse启用实验性的流式标签/值搜索 HTTP 端点/api/v1/search/{metric_names,label_names,label_values}-querier.max-fetched-series-per-query见 limits单查询最多拉取的序列数运行时限见 limits.go可观测性一致性校验与 store-gateway 查询指标querier 暴露了与本文主题直接相关的关键指标便于在生产环境监控块查询是否完整指标含义cortex_querier_blocks_consistency_checks_total需要做一致性校验的查询总数cortex_querier_blocks_consistency_checks_failed_total一致性校验失败的查询总数cortex_querier_blocks_found_total基于查询时间范围找到的块数cortex_querier_blocks_queried_total实际查询的块数部分块可能被查询分片优化过滤cortex_querier_storegateway_instances_hit_per_query单查询命中的 store-gateway 实例数cortex_querier_storegateway_refetches_per_query因缺失块而发起的重拉取次数指标注册代码位于 blocks_consistency_checker.go 与 blocks_store_queryable.go。总结querier 配置要点清单共享 ring 配置querier 的-store-gateway.sharding-ring.*与-ingester.ring.*必须分别与 store-gateway、ingester 保持一致否则无法发现数据源实例时间窗口配合确保-querier.query-ingesters-within大于-querier.query-store-after且大于新块可见的预估最短时间默认配置下约3h避免查询空洞开启元数据缓存生产环境建议启用-blocks-storage.bucket-store.metadata-cache.backendmemcached并与 store-gateway 共享同一 Memcached 集群TTL 设为 0 或负值可禁用对应条目监控一致性指标关注cortex_querier_blocks_consistency_checks_failed_total其增长通常意味着 store-gateway 重启、扩缩容或 ring 不稳定导致部分块暂时不可查询理解失败语义querier 在重试上限replication-factor或 3取小者后仍无法查询全部块时会直接让查询失败——这是保证查询结果正确性的有意设计而非故障。完整的 querier 配置参数清单可参考官方 configuration parameters 中的querier一节。赞分享时序数据库后端数据存储可观测性云原生【免费下载链接】mimirGrafana Mimir provides horizontally scalable, highly available, multi-tenant, long-term storage for Prometheus.项目地址https://gitcode.com/gh_mirrors/mimir/mimir点击查看免费下载相关推荐Grafana Mimir Exemplar 存储深度解析环形缓冲区、内存开销与配置实战Grafana Mimir Exemplar 存储深度解析环形缓冲区、内存开销与配置实战 导读 Exemplar示例样本是时间序列数据中某个具体事件的代表时序数据库后端数据存储可观测性云原生Grafana Mimir 查询指南通过 Grafana 与 HTTP API 查询指标数据及范围查询缓存机制详解Grafana Mimir 查询指南通过 Grafana 与 HTTP API 查询指标数据及范围查询缓存机制详解 本文以 Grafana Mimir 官方查时序数据库后端数据存储可观测性云原生Nacos Config 动态配置规范深度解析资源身份、查询链、灰度发布与缓存一致性Nacos Config 动态配置规范深度解析资源身份、查询链、灰度发布与缓存一致性 本篇指南基于 Nacos 仓库 specs/zh cn/config/c后端微服务配置中心服务注册发现云原生上一篇洛雪音乐助手入门指南7 个音乐源聚合的免费音乐播放器下一篇デジタル庁デザインシステム企業向けカスタマイズとブランディング適用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考