3. 搜索场景分析:搜索系统的典型架构、搜索对缓存的依赖、搜索缓存的读写比例特征
3.1 搜索系统的典型架构分层
现代搜索系统通常采用倒排索引 + 多层缓存的架构,以平衡查询延迟、索引更新频率与资源成本。一个典型的搜索系统从用户请求到结果返回,经历以下核心层:
| 架构层 | 核心组件 | 主要职责 | 延迟目标 |
|---|---|---|---|
| 接入层 | 负载均衡、API Gateway | 请求路由、限流、鉴权、协议转换 | < 5 ms |
| 查询解析层 | 分词器、Query Parser、意图识别 | 分词、纠错、同义词扩展、Query 改写 | < 10 ms |
| 缓存层 | Redis Cluster、Local Cache | 热点结果缓存、前缀补全、防雪崩 | < 1 ms |
| 索引层 | Elasticsearch / Solr / 自研索引 | 倒排索引检索、向量检索、排序打分 | 10 ~ 100 ms |
| 数据存储层 | MySQL / HBase / 对象存储 | 全量数据持久化、索引重建数据源 | 50 ~ 200 ms |
架构要点:缓存层位于查询解析层与索引层之间,是搜索系统延迟的“第一道防线”。缓存命中时,请求直接返回,不再穿透到索引层。
3.2 搜索对缓存的深度依赖
搜索系统对缓存的依赖体现在三个关键维度:
- 热点查询缓存:高频搜索词(如“手机”、“天气”)的结果集在短时间内被大量重复请求。缓存直接命中可避免索引层重复计算,降低 80% ~ 95% 的查询延迟。
- 前缀补全与联想缓存:用户输入过程中的实时联想(Auto-complete)需要极低延迟(< 5 ms)。Redis 的 Sorted Set 或 Trie 结构可存储热门前缀列表,支撑每秒数万次的前缀查询。
- 防雪崩与降级缓存:当索引层发生故障或 GC 抖动时,缓存层作为“最后一道屏障”返回过期但可用的结果,保证搜索服务的基本可用性。
关键数据:在日均亿级搜索请求的系统中,缓存层的整体命中率通常维持在 75% ~ 90%。每提升 1% 的命中率,可减少约 10 ~ 20 台索引节点的资源开销。
3.3 搜索缓存的读写比例特征
搜索缓存的读写比例具有明显的“读多写少”特征,但写入模式与通用缓存有显著差异:
| 指标 | 典型值 | 说明 |
|---|---|---|
| 读 QPS | 10 万 ~ 100 万+ | 用户搜索请求直接触发缓存读取 |
| 写 QPS | 100 ~ 5000 | 索引更新、数据变更触发缓存淘汰或预热 |
| 读写比例 | 100:1 ~ 1000:1 | 读请求远高于写请求,写操作集中在索引更新窗口 |
| 写入模式 | 批量 + 异步 | 索引重建或增量更新时,批量写入缓存;非实时单条写入 |
| 缓存淘汰策略 | TTL + LRU | 热点数据 TTL 通常设置为 30 s ~ 5 min;冷数据自动淘汰 |
架构陷阱:搜索缓存写入虽然量小,但写入时机集中(如索引全量重建时)。如果缓存写入操作未做限速或异步化,瞬间写入压力可能导致 Redis 主线程阻塞,进而影响读请求。建议采用 Pipeline 批量写入 或 消息队列削峰。
3.4 搜索缓存的关键设计要点
- 缓存粒度:按查询词 + 分页参数 + 排序方式组合作为缓存 Key,避免过度聚合导致缓存失效放大。
- 缓存更新策略:采用 Cache-Aside 模式,读时回填,写时删除或异步更新。避免使用 Write-Through 导致写入放大。
- 缓存穿透防护:对空结果也进行短暂缓存(空值缓存),防止恶意查询穿透到索引层。
- 缓存预热:在索引全量重建后,通过离线任务将 Top N 热点查询预热到 Redis,避免冷启动期间大量穿透。
实践建议:搜索缓存的 TTL 不宜设置过长。建议热点数据 TTL 为 30 s ~ 5 min,冷数据 TTL 为 1 min ~ 10 min。TTL 过长会导致搜索结果与索引数据不一致,影响搜索质量。