请求讲解ElasticSearch各类缓存及问答应用适配与热门问题速显方案
ElasticSearch 内置多种缓存机制,用于优化查询性能、减少重复计算,以下是核心类型:
节点级查询缓存(Node Query Cache)
节点层面的默认缓存,专门存储过滤查询(如filter、constant_score子句)的结果,按分片的segment维度缓存文档ID集合。适合重复执行的过滤逻辑,比如固定分类下的内容筛选,命中时直接返回过滤后的文档集合,无需重复计算。分片请求缓存(Shard Request Cache)
分片级别的缓存,针对聚合、count、suggest等只读请求的计算结果,默认关闭,需手动开启。缓存的是整个请求的最终结果(如topN聚合、统计值),适合非实时性的统计场景,能大幅降低重复统计的资源消耗。字段数据缓存(Field Data Cache)
分片级别的正排数据缓存,用于排序、聚合、脚本中用到的字段值(比如text字段的fielddata、keyword字段聚合)。默认懒加载,首次使用时加载字段的正排数据到内存,适合频繁排序/聚合的字段,但需注意内存占用,避免OOM。索引缓冲区(Index Buffer)
写入侧的内存缓存,暂存待写入的文档,当缓冲区达到阈值或定时触发时,刷新为新的segment。默认占堆内存的10%,优化写入性能,减少磁盘IO频率。内存断路器(Circuit Breaker)
不属于传统缓存,但负责管控缓存内存使用,防止缓存占用过多内存导致节点崩溃。当内存使用达阈值时,会拒绝新请求或释放部分缓存,包含字段数据断路器、请求缓存断路器等细分类型。
问答类应用中,热门提问展示、用户个性化内容筛选是高频场景,分片请求缓存和节点级查询缓存是最优选择:
- 分片请求缓存:适合缓存热门提问的聚合/排序结果(如按浏览量、点赞数排序的topN列表),这类数据无需实时更新(可设置5-10分钟过期),缓存后直接返回结果,响应速度提升明显。
- 节点级查询缓存:适合缓存用户登录后的个性化过滤条件(如“我的提问”“我关注的话题内容”),这类过滤逻辑重复率高,缓存文档ID集合后可跳过重复过滤计算。
1. 数据建模优化
给提问文档添加核心字段:
view_count(integer):浏览量,用于排序like_count(integer):点赞数,用于排序user_id(keyword):提问者ID,用于“我的提问”过滤followed_topics(keyword数组):用户关注的话题ID,用于个性化热门内容筛选create_time(date):提问时间,辅助排序
2. 开启并配置分片请求缓存
首先开启索引级请求缓存:
PUT /questions/_settings { "index.requests.cache.enable": true, "index.requests.cache.expire": "5m" // 设置缓存过期时间,平衡实时性与性能 }
查询热门提问时,显式指定使用缓存(全局开启后也可省略,但建议明确声明):
GET /questions/_search { "size": 10, "query": { "bool": { "filter": [ {"terms": {"followed_topics": ["elasticsearch", "java"]}} // 登录用户关注的话题 ] } }, "sort": [ {"view_count": "desc"}, {"like_count": "desc"} ], "request_cache": true }
3. 利用节点查询缓存加速个性化过滤
用户登录后的个性化查询(如“我的提问”),使用filter子句替代must,确保过滤结果被节点查询缓存:
GET /questions/_search { "query": { "bool": { "filter": [ {"term": {"user_id": "u_12345"}} // 当前登录用户ID ] } }, "sort": [{"create_time": "desc"}] }
4. 缓存预热
通过定时任务(如每分钟一次)提前执行热门提问查询,将缓存加载到内存,避免用户首次查询的延迟:
curl -X GET "http://localhost:9200/questions/_search" -H "Content-Type: application/json" -d '{ "size": 10, "query": {"match_all": {}}, "sort": [{"view_count": "desc"}, {"like_count": "desc"}], "request_cache": true }'
5. 内存资源配置
调整缓存的内存占比,确保有足够资源承载缓存数据:
PUT /_cluster/settings { "persistent": { "indices.requests.cache.size": "2%" // 将请求缓存占比调整为堆内存的2%,可根据实际情况调整 } }
内容的提问来源于stack exchange,提问作者Shivani Jayaswal

