最近面试中遇到redis缓存穿透、缓存雪崩等问题,特意了解下。
redis缓存穿透:
缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
解决的办法:
1. 如果查询数据库也为空,直接设置一个默认值存放到缓存,后续不会继续访问数据库,同时设置过期时间保证高并发情况下保障不被穿透,后续也能及时更新。
2. 假如key是有一定规则的,可key来过滤一部分无效查询。
3. 采用布隆过滤器(Bloom Filter),将所有可能存在的数据哈希到一个足够大的BitSet中,不存在的数据将会被拦截掉,从而避免了对底层存储系统的查询压力。
redis缓存雪崩:
大并发的缓存穿透,导致所有请求都跑去了数据库,引起数据库IO、内存和CPU压力过大,甚至导致宕机,使得整个系统崩溃,这就是缓存雪崩(缓存失效)。
解决的办法:
1. 减少缓存穿透的影响。
2. 使用主备机制,redis双缓存涉及到更新事务的问题,需解决update可能读到脏数据。
redis热点key:
热点key:某个key访问非常频繁,当key失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃。
解决办法:
1. 使用锁,单机用synchronized,lock等,分布式用分布式锁。(性能低)
2. 缓存过期时间不设置,在key对应的value里设置过期时间。如果检测到存的时间超过过期时间则异步更新缓存。
3. 在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。
推荐使用后俩种模式,虽然需要一定的硬编码,但不影响性能。