面试题答案
一键面试避免缓存雪崩策略
- 设置不同过期时间:避免大量缓存同时过期,通过在原过期时间基础上增加一个随机时间偏移量,如使用
EXPIRE key seconds
命令设置过期时间时,seconds
为原本过期时间加上一个较小的随机值(例如1 - 10秒)。这样不同实例设置的过期时间就会分散开,不会集中失效。 - 使用二级缓存:当一级缓存失效时,先从二级缓存读取数据。二级缓存可以使用本地缓存(如Guava Cache等),它的优点是访问速度快且不依赖网络。在一级缓存失效后,先从本地缓存获取数据,如果没有再去查询数据库并更新两级缓存。
- 互斥锁:在缓存失效时,通过
SETNX key value
命令获取互斥锁,只有获取到锁的实例才能去查询数据库并更新缓存,其他实例等待一段时间后重试获取缓存。当获取锁的实例更新完缓存后,使用DEL key
命令释放锁。这样可以防止大量实例同时查询数据库。
避免缓存穿透策略
- 布隆过滤器:在查询数据前,先通过布隆过滤器判断数据是否存在。布隆过滤器可以用
bf.add key element
命令添加元素,用bf.exists key element
命令判断元素是否存在。如果布隆过滤器判断数据不存在,就直接返回,不再查询数据库,从而避免查询不存在的数据穿透到数据库。 - 缓存空值:当查询数据库发现数据不存在时,仍然在缓存中设置一个空值,并设置较短的过期时间。这样下次查询同样的数据时,直接从缓存中获取空值,不会穿透到数据库。使用
SET key "" EX seconds
命令设置空值及过期时间。
优化内存使用策略
- 合理设置数据结构:根据数据特点选择合适的数据结构,例如,如果数据是简单的键值对,使用
SET key value
命令存储;如果是需要排序的集合,使用ZADD key score member
命令创建有序集合。避免使用不必要的复杂数据结构导致内存浪费。 - 内存淘汰策略:在Redis配置文件(redis.conf)中设置合适的内存淘汰策略,如
maxmemory-policy allkeys-lru
表示当内存达到设置的maxmemory
时,使用LRU(最近最少使用)算法淘汰所有键。还可以选择volatile-lru
(只淘汰设置了过期时间的键)、allkeys-random
(随机淘汰所有键)等策略。 - 定期清理无用数据:通过
DEL key
命令及时删除不再使用的数据,释放内存。可以结合业务逻辑,在数据不再使用时立即删除,或者定期扫描删除过期或无用的数据。