
PostHog 如何配置 S3 查询缓存降低 Redis 存储成本【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthogPostHog 的查询结果缓存query cache会把每条结果 zstd 压缩后存入 Redis。对于压缩后仍然很大的结果临时查询、API 大结果集它们会长期占据 Redis 内存。PostHog 提供了一条 S3 分流路径压缩后达到QUERY_CACHE_S3_MIN_COMPRESSED_BYTES默认 128KB的缓存条目会上传为 S3 对象Redis 中只保留一条小的指针记录。这样大结果从 Redis 挪走而仪表板小结果仍走亚毫秒级的 Redis 读取。本文基于 S3 query cache setup 与 posthog/query_cache/storage.py、posthog/settings/object_storage.py说明完成这条路径所需的配置、灰度开关、生命周期规则和验证方式。大结果如何被分流到 S3写入流程store_result→schedule_upload_for_pointer见 storage.py结果先序列化为 JSON超过 512 字节COMPRESSION_FLOOR_BYTES时做一次 zstd 压缩。同一个压缩帧同时用作三样东西判断是否走 S3 的路由依据、Redis 内联值、S3 上传体。若压缩帧长度 ≥QUERY_CACHE_S3_MIN_COMPRESSED_BYTES且该 team 所属 organization 的灰度开关允许条目在后台线程上传到 S3成功后把 Redis 中的内联值替换为指针记录指针携带 bucket、key 和last_refresh。任何失败S3 报错、上传线程池饱和都会回落到“条目继续留在 Redis 内联”的状态查询本身不会因此失败。只有 zstd 帧才可能走 S3低于 512 字节的结果存原始字节天然不进入 S3 路径关掉压缩开关USE_REDIS_COMPRESSIONposthog/settings/data_stores.py默认True同样会让条目离开 S3 路由。需要配置的三个环境变量这三个设置是进程启动时读取的普通环境变量定义见 posthog/settings/object_storage.py环境变量默认值含义QUERY_CACHE_S3_BUCKET回退到OBJECT_STORAGE_BUCKET缓存 blob 所在 bucketCloud 上为专用 bucketposthog-query-cache-region-envOBJECT_STORAGE_S3_QUERY_CACHE_FOLDERquery_cachebucket 内的 key 前缀QUERY_CACHE_S3_MIN_COMPRESSED_BYTES131072128KB路由到 S3 的最小 zstd 压缩后大小对象键形如{folder}/{team_id}/{cache_key}/{upload_id}每次上传生成一个新的upload_id避免同一查询并发重算时互相覆盖对象带归属标签cache_typequery_data和team_idid标签只用于归属不代表过期。# 按需覆盖文档说明 Cloud 运行默认值生产覆盖需先通过部署 chart 注入与其他应用设置一致 QUERY_CACHE_S3_BUCKET你的缓存专用或共享 bucket OBJECT_STORAGE_S3_QUERY_CACHE_FOLDERquery_cache QUERY_CACHE_S3_MIN_COMPRESSED_BYTES131072QUERY_CACHE_S3_MIN_COMPRESSED_BYTES的阈值针对的是压缩后字节——那才是条目在 Redis 里的真实成本。按 object_storage.py 中的注释查询结果大约压缩 3-15 倍128KB 阈值对应约 0.4-2MB 的序列化 JSON仪表板图块几乎到不了这个量级留在 Redis字节大头的临时查询和 API 结果则被移出集群。灰度开关 query-cache-s3-writes分流由 organization 组上的多变量特性开关query-cache-s3-writes控制它只限制写入路径读取路径从不评估开关、只跟随已存储的记录形态。三种状态未开启off所有结果照旧内联存 Redis。shadow缓存条目同时写 S3 和 Redis用于验证写入路径没有任何读取走 S3 副本Redis 仍是权威。onRedis 存指针、条目存 S3读取时从 S3 取 blob。评估是本地求值only_evaluate_locallyTrue只有shadow和on两个已知变体会激活 S3 写入布尔开关、未知变体或求值失败都会 fail-closed 回到内联 Redis 路径。开关按 organization 维度开启因此可以按团队灰度推进。必须配套S3 生命周期规则S3 生命周期规则是这条路径的垃圾回收兜底删掉的是主动删除Celery 延迟删除漏掉的对象TTL 自然过期的指针、shadow 模式的上传、回滚的 team、失败的删除以及无法触达 Celery broker 的进程留下的写入。规则只有一条对象在CACHED_RESULTS_TTL_DAYS7天后过期。按 bucket 类型分两种做法见 S3 query cache setup专用 bucketCloud 的posthog-query-cache-region-env只服务这个缓存规则可以作用于整个 bucket。Cloud 侧由 posthog-cloud-infra 的terraform/modules/s3/main.tfenable_query_cache_lifecycle管理。共享 bucket必须把规则限定在OBJECT_STORAGE_S3_QUERY_CACHE_FOLDER前缀默认query_cache/上。因为QUERY_CACHE_S3_BUCKET未设置时回退到共享的OBJECT_STORAGE_BUCKET全 bucket 的过期规则会连 exports、media uploads、error-tracking source maps 一起删掉。还有一个顺序要求如果未来把CACHED_RESULTS_TTL_DAYS调大必须先调大 bucket 生命周期规则。否则 S3 会在 Redis 指针仍然存活时就删掉 blob大缓存条目会提前悄悄失效。调小是安全的——blob 只会比指针多活几天再被 GC。过期与删除语义过期由 Redis 指针的 TTL 决定与 S3 无关。附着于 insight/dashboard 的条目存活CACHED_RESULTS_TTLCACHED_RESULTS_TTL_DAYS 7 天定义在 posthog/settings/schedules.pyinsight/dashboard 之外的程序化写入走更短的CACHED_RESULTS_PROGRAMMATIC_TTL默认 24 小时。指针过期或被驱逐后条目即消失无论 S3 对象是否还在。一旦没有指针引用blob 会被尽快删除替换或驱逐指针条目会入队一个延迟BLOB_DELETE_DELAY_SECONDS60 秒的尽力而为 Celery 删除留出窗口让刚读到指针的读方完成 S3 读取而一次指针交换失败的上传会立刻删掉自己的 blob因为它从未进入 Redis。验证配置是否生效文档给出的可观察点如下Redis 侧形态。条目被分流后Redis 中该缓存键的值以S3_POINTER_MAGICPHQCS3\x00开头的指针记录替代了原来的 zstd 帧未分流的条目仍是 zstd 帧或原始字节。posthog/query_cache/test/test_storage.py 中的test_on_mode_large_result_round_trips_via_pointer演示了这条判定写入大结果后 Redis 持有指针、S3 有 1 个对象且lookup()读回的as_full_response()与原始响应一致。Prometheus 指标见 storage.py 中的指标定义posthog_query_cache_s3_write_total{mode, outcome}写入模式与结果posthog_query_cache_s3_write_bytes_total{mode}上传的压缩字节数是 bucket 增长的直接信号posthog_query_cache_s3_read_total{outcome}/posthog_query_cache_s3_read_duration_seconds指针解析结果hit、missing、error、blob_corrupt、pointer_corrupt、storage_disabled与耗时。 读侧 outcome 为hit说明“指针 → S3 blob”链路已经实际服务流量。shadow 模式的行为。test_shadow_mode_uploads_but_redis_stays_authoritative表明 shadow 模式下 S3 有对象、但 Redis 不出现指针——这正是 shadow 的预期形态。限制与边界故障退化是内联不是失败write_blob失败返回 None条目保留在 Redis 内联指针解析失败corrupt/missing读作 miss 并重算重算的写入会覆盖坏条目。上传并发受限S3 上传走 2 线程池、最多 8 个排队 blob槽位耗尽时直接跳过上传记saturated条目留在内联。读取路径不看开关回滚on→ 已写入的指针条目仍会走 S3 读取直到其自然过期反过来若关掉对象存储OBJECT_STORAGE_ENABLEDFalse读侧会把指针读记为storage_disabled并当作 miss。版本混合旧版本 pod 读到不认识的格式会记一次读错误、删除条目并重算滚动部署期间每条条目最多多一次重算。完成专用或正确限定前缀的共享bucket、7 天生命周期规则与query-cache-s3-writes开关后先让目标组织跑shadow观察写入指标再切on用 Redis 指针形态与posthog_query_cache_s3_read_total{outcomehit}确认大结果已实际离开 Redis。【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考