一、缓存命中率
- 命中:可以直接通过缓存获取到需要的数据,而不是从数据库中获取
- 不命中:无法直接通过缓存获取到想要的数据,需要再次查询数据库或者执行其它的操作。原因可能是由于缓存中根本不存在,或者缓存已经过期。
通常来讲,缓存的命中率越高则表示使用缓存的收益越高,应用的性能越好(响应时间越短、吞吐量越高),抗并发的能力越强。
由此可见,在高并发的互联网系统中,缓存的命中率是至关重要的指标。
如何查看Redis缓存命中率
redis-cli -h xx -p xx info stats
可以看到
keyspace_hits:90176387
keyspace_misses:5182698
缓存命中率:keyspace_hits / (keyspace_hits + keyspace_misses)
二、缓存命中率的影响因素
2.1 业务场景
缓存适合“读多写少”的业务场景,反之,使用缓存的意义其实并不大,命中率会很低。
2.2 时效性
业务需求决定了对时效性的要求,直接影响到缓存的过期时间和更新策略。时效性要求越低,就越适合缓存。在相同key和相同请求数的情况下,缓存时间越长,命中率会越高。
互联网应用的大多数业务场景下都是很适合使用缓存的。
2.3 缓存粒度
通常情况下,缓存的粒度越小,命中率会越高。
举个实际的例子说明:
当缓存单个对象的时候(例如:单个用户信息),只有当该对象对应的数据发生变化时,我们才需要更新缓存或者让移除缓存。而当缓存一个集合的时候(例如:所有用户数据),其中任何一个对象对应的数据发生变化时,都需要更新或移除缓存。
还有另一种情况,假设其他地方也需要获取该对象对应的数据时(比如其他地方也需要获取单个用户信息),如果缓存的是单个对象,则可以直接命中缓存,反之,则无法直接命中。这样更加灵活,缓存命中率会更高。
2.4 过期时间和更新策略
缓存的更新/过期时间和策略也直接影响到缓存的命中率。此处的缓存过期策略并非Redis自带的定期删除和惰性删除策略,而是根据业务场景优化Key的过期时间和更新策略。
如用户的key信息,如果同时过期,那么多个用户同时查询时,就会落到数据库去,也就是要避免缓存同时失效。当数据发生变化时,直接更新缓存的值会比移除缓存(或者让缓存过期)的命中率更高,当然,系统复杂度也会更高。
2.5 缓存预加载-预热
redis的缓存大部分是从数据库加载的,那么第一次使用数据的时候,redis需要从数据库去加载数据,所以在对用户前,可以提前加载需要的数据到缓存,这样用户在第一次访问的时候就可以直接走缓存而不是去查询数据库。
2.6 缓存击穿和缓存穿透
- 缓存击穿:
主要是缓存过期时的高并发访问,可以通过加锁,同一key只允许一个连接访问到DB数据库解决 - 缓存穿透:
一般是访问不存在的key,导致落到数据库(可能数据库也没有),这样会降低缓存命中率
(1)应用访问缓存,假如数据存在,则直接返回数据
(2)数据在redis不存在,则去访问数据库,数据库查询到了直接返回应用,同时把结果写回redis
(3)数据在redis不存在,数据库也不存在,返回空,一般来说空值是不会写入redis的,如果反复请求同一条数据,那么则会发生缓存穿透
解决:可以使用布隆过滤器先判断key是否存在,存在才去redis缓存读取(redis缓存里可能key也不存在,这时候就去数据库读取,没有则返回空)
2.7 缓存容量
要注意缓存容量,太小会触发redis的内存淘汰机制,线上redis一般配置maxmemory-policy allkeys-lru算法来进行内存淘汰,这样有一部分key会被删除,导致缓存穿透,从而降低缓存命中率,因此合理配置缓存容量很有必有。
提高缓存命中率的方法
- 聚焦在高频访问且时效性要求不高的热点业务上(如字典数据、session、token)
- 缓存预加载(预热)
- 增加存储容量
- 调整缓存粒度
- 更新缓存
注意:对于时效性很高(或缓存空间有限),内容跨度很大(或访问很随机),并且访问量不高的应用来说缓存命中率可能长期很低,可能预热后的缓存还没来得被访问就已经过期了。
https://segmentfault.com/a/1190000023730820
https://www.cnblogs.com/shamo89/p/8383915.html