
缓存穿透直冲 DB 的排查现场让 Codex 帮你逐行拆布隆过滤器电商首页的商品详情接口平时 QPS 稳定在几千某天凌晨突然数据库连接池被打满慢查询日志里全是SELECT * FROM product WHERE id 999999这类根本不存在的 ID。缓存命中率从 98% 掉到 40%Redis 里却看不到这些 key——这就是典型的缓存穿透请求既不在缓存里也不在数据库里每一发都实打实落到 DB 上。面试里谢飞机被问到这个问题时卡了壳现实排障中更麻烦的是你知道要加布隆过滤器和空值缓存但面对一段已有的Cacheable代码不确定该从哪一行开始改。这篇就用 TaoToken 给 Codex 配好模型通道让它按原文的Cacheable空值缓存 BloomFilter 步骤逐行对照着排查product:999999为什么会打到 DB。TaoToken 官网 https://taotoken.net/ 在这里的角色很明确只做 Codex 的 Key 和 Base URL 提供方保证你问 Codex 时模型调用稳定不负责替你实现布隆过滤器。一、原问题与场景穿透为什么绕过了缓存先把现象拆清楚。正常请求product:1001的路径是查 Redis → 命中则返回未命中则查 DB → 写回 Redis。问题出在product:999999这种 ID 上Redis 里没有DB 里也没有于是每次请求都走完整条链路缓存形同虚设。黑产用脚本遍历不存在的 ID等于拿无效请求当 DDoS 打 DB。原文给出的两条防线是布隆过滤器前置过滤和空值短 TTL 缓存。布隆过滤器在请求进入缓存层之前就判断 key 是否可能存在返回 false 直接拒绝空值缓存则处理布隆过滤器误判为 true 但 DB 确实无数据的情况把 null 也写进 Redis 并设一个短 TTL避免同一批无效 key 反复穿透。排障对象是缓存穿透击穿 DB这个现象不是让 TaoToken 去实现布隆过滤器。正确做法是先打开 https://taotoken.net/ 创建 Key把 Codex 的模型通道 Base URL 指向 https://taotoken.net/api然后让 Codex 按原文的步骤逐行对照排查。TaoToken 在这里只作为 Codex 的 Key/Base URL 提供方保证你问 Codex 时模型调用稳定拿到 Key 后就能用它把 Redis 穿透面试题拆成布隆过滤器前置过滤 空值短 TTL的标准答案。二、TaoToken 前置给 Codex 配一条稳定通道Codex 默认走 OpenAI 的接口国内直连经常超时排查到一半模型调用断了思路也跟着断。TaoToken 提供兼容 OpenAI 协议的通道把 Base URL 换掉即可。先去 https://taotoken.net/ 注册账号在控制台创建 API Key记下YOUR_API_KEY。这一步只做一次后面所有排查都复用这个 Key。需要说明的是TaoToken 不替代编辑器也不替你写代码。它的作用是让你在 Codex 里连续追问这行unless为什么没生效布隆过滤器误判率怎么算时模型调用不中断。排查缓存穿透往往要来回改好几版代码通道稳定性直接决定效率。三、可复制配置Codex 的 config.toml 与 settings.jsonCodex 的配置分两处模型通道走config.tomlClaude Code 风格的 settings 走settings.json。先配config.toml# ~/.codex/config.toml model gpt-4o model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY然后在环境变量里写入 Keyexport TAOTOKEN_API_KEYYOUR_API_KEY如果你用的是 Claude Code 风格的 settings.json配置ANTHROPIC_*系列变量{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: YOUR_API_KEY, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }两处配置的 Base URL 都指向https://taotoken.net/api注意 API 地址不带 UTM 参数。配完后重启 Codex让它重新读取配置。四、验证请求让 Codex 逐行对照排查配置生效后在 Codex 里发起一次验证请求确认通道可用codex 用一句话确认你已就绪返回正常即可进入正题。接下来把原文的ProductService代码贴给 Codex让它逐行对照排查product:999999为什么打到 DB。可以这样提问下面这段 Spring Boot 代码product:999999 这类不存在的 ID 会打到 DB。 请逐行指出1) 布隆过滤器在哪一步失效2) 空值缓存的 TTL 和 key 设计有什么问题 3) 给出修改后的完整方法。 Service public class ProductService { Autowired private RedisTemplateString, Object redis; Autowired private BloomFilterString bloomFilter; public Product getProduct(Long id) { String key product: id; if (!bloomFilter.mightContain(key)) { return null; } Product p (Product) redis.opsForValue().get(key); if (p ! null) return p; p productMapper.selectById(id); if (p ! null) { redis.opsForValue().set(key, p, 30, TimeUnit.MINUTES); } else { redis.opsForValue().set(key _null, , 2, TimeUnit.MINUTES); } return p; } }Codex 通常会指出几个关键点布隆过滤器初始化时如果没把所有有效商品 ID 加进去mightContain会误判空值缓存的 key 用了_null后缀但查询时读的是原 key导致空值缓存永远命中不了TTL 设 2 分钟但没有加随机抖动同一批攻击 key 会在同一时刻集体过期形成缓存雪崩。这些正是原文答案详解区强调的空值缓存陷阱。成功结果应该是Codex 给出修改后的方法布隆过滤器前置判断、空值缓存 key 与查询 key 一致、TTL 带随机后缀。你对照原文的Cacheable(valueproducts, unless#result null)写法确认逻辑一致。五、本篇常见错排查错误一Base URL 写成带 UTM 的地址。https://taotoken.net/api是接口地址不要拼上?utm_source...否则 Codex 请求会 404。错误二环境变量名和 config.toml 里的env_key不一致。config.toml写env_key TAOTOKEN_API_KEY环境变量就必须是TAOTOKEN_API_KEY大小写敏感。错误三布隆过滤器 key 和缓存 key 前缀不统一。布隆过滤器里存的是product:1001查询时也必须用product:前缀否则mightContain永远返回 false所有请求都被拒绝。错误四空值缓存 TTL 设太长。原文建议 2 分钟设成 30 分钟会导致商品上架后长时间查不到。TTL 要短且加随机抖动。错误五只加布隆过滤器不加空值缓存。布隆过滤器有误判率误判为 true 的请求仍会穿透到 DB空值缓存是第二道防线两者缺一不可。遇到配置类问题去 TaoToken 的 API Keys 页面和接入文档核对参数https://taotoken.net/console/api-keys 和 https://taotoken.net/doc 。验证模型是否正常用模型对话页面https://taotoken.net/model-chat 。六、语义一致 CTA缓存穿透的排查本质是把布隆过滤器前置过滤 空值短 TTL这两条防线落到代码的每一行。Codex 能帮你逐行对照但前提是模型通道稳定。如果你只是偶尔问几个排查问题用 API Keys 配好通道即可如果长期在编码和 Agent 场景里反复调用Coding Plan 更合适https://taotoken.net/coding-plan 。先把 Key 拿到手再让 Codex 按原文步骤拆解product:999999的穿透路径比对着面试题空想有效得多。