查看缓存占用的内存数量
基于一个 8 节点集群,查询 QPS 大概 30 左右。通过 node 信息查看请求缓存
curl localhost:9200/_nodes/stats/indices/request_cache?pretty
执行结果:
{ "_nodes" : { "total" : 8, "successful" : 8, "failed" : 0 }, "cluster_name" : "moka-es", "nodes" : { "4FbqP65LTf-uwF1sGZAnQQ" : { "timestamp" : 1597291580728, "name" : "es-node-3", "transport_address" : "172.17.240.18:9300", "host" : "172.17.240.18", "ip" : "172.17.240.18:9300", "roles" : [ "master", "data", "ingest" ], "attributes" : { "ml.machine_memory" : "33738051584", "ml.max_open_jobs" : "20", "xpack.installed" : "true", "ml.enabled" : "true" }, "indices" : { "request_cache" : { "memory_size_in_bytes" : 53328, "evictions" : 0, "hit_count" : 1395, "miss_count" : 10267 } } }, "q0_ZkHoASzqRsGrCVUlQPA" : { "timestamp" : 1597291580729, "name" : "es-node-8", "transport_address" : "172.17.47.73:9300", "host" : "172.17.47.73", "ip" : "172.17.47.73:9300", "roles" : [ "master", "data", "ingest" ], "attributes" : { "ml.machine_memory" : "32300605440", "ml.max_open_jobs" : "20", "xpack.installed" : "true", "ml.enabled" : "true" }, "indices" : { "request_cache" : { "memory_size_in_bytes" : 16287, "evictions" : 0, "hit_count" : 23, "miss_count" : 74 } } },
....
|
结果比较奇怪,相较于每个节点 32GB 的内存,几百 kb 的换存量几乎相当于没有缓存任何请求结果。
而随便找一台测试用的单机 es ,缓存量反而比上面集群的缓存总和还要多:
{ "_nodes" : { "total" : 1, "successful" : 1, "failed" : 0 }, "cluster_name" : "elasticsearch", "nodes" : { "ccC4H-1mR4apSB5pgR6yXw" : { "timestamp" : 1597292348183, "name" : "ccC4H-1", "transport_address" : "172.17.46.126:9300", "host" : "172.17.46.126", "ip" : "172.17.46.126:9300", "roles" : [ "master", "data", "ingest" ], "attributes" : { "ml.machine_memory" : "33191542784", "xpack.installed" : "true", "ml.max_open_jobs" : "20", "ml.enabled" : "true" }, "indices" : { "request_cache" : { "memory_size_in_bytes" : 2653163, "evictions" : 0, "hit_count" : 1353, "miss_count" : 2439 } } } } }
|
什么样的 query 会被 cache ?
It is not possible to look at the contents being cached.
而且除非自己 log,es 也没办法看到 query history(?)我们只能通过 node API,index 级别的配置和 query type 去判断缓存的使用情况。
这里不同的 doc 、书、网上的文章说的有点出入。在我的理解里,只有两种 query cache, node query cache 和 shards query cache。
node query cache
node query cache 只保留 filter 类型的 query result。
es 的 node query cache 默认是开启的,基于 LRU(least recently use),当缓存达到上限,一条新缓存出现的同时会驱逐(evict)最近最少使用的那一条。
从 query 类型来看,除了 filter 类型的 query ,其他任何类型的 query 结果都不会被缓存。从数量和大小来看,默认会保存最多一万条或最多 10% 的 heap size 的 query。因 cache 基于 segment, 当 segment(一个真实的倒排索引文件)的 doc 数量小于一万条或小于当前 shards 的 3% 或者总的请求数量过小时,都不会触发 cache。
shard request cache
shard request cache 就是把在各个 shard 上执行的 query 本地结果缓存下来。 一样也是 LRU 机制。他会缓存频繁请求的结果或者通过对每一个 query 手动添加 request_cache=true
来决定一个请求是否触发缓存。
注意,这里默认只会缓存 size = 0 的 query 结果,也就是一些可以不在意 hits 的 query,比如 aggregation,suggestion。这意味着如果不手动标识,日常针对普通 field 的搜索想要召回具体命中 doc 的 query 全部不会被缓存。这也解释了为什么上述的集群几乎没有 request cache。
其他方案
其他的缓存方案大同小异,就是在得到结果后,配合 query 做一个 k-v 形式的缓存,区别只是缓存选型、数据更新、缓存过期时间上的处理。例如这个 利用 Redis 做缓存
参考
Mastering Elasticsearch
ElasticSearch Cache Usage
Query Cache