Appearance
问:缓存穿透(查询不存在的数据)
- 布隆过滤器(Bloom Filter):在缓存层前加一层布隆过滤器,预先存储所有合法数据的key。请求过来时,先检查布隆过滤器,如果不存在则直接返回,避免访问数据库。
- 缓存空值:即使数据库查不到,也缓存一个空值(比如key:null),并设置较短的过期时间(如30秒),防止重复查询穿透。
问:缓存雪崩(大量缓存同时过期)
- 随机过期时间:在基础过期时间上增加随机值(比如基础时间 + 1~5分钟随机值),避免集中失效。
- 热点数据永不过期:对核心数据(如首页推荐商品)不设过期时间,改为逻辑过期——后台异步刷新缓存。
- 熔断降级:当数据库压力过大时,触发熔断机制,暂时拒绝部分请求,优先保障核心服务。
问:缓存穿透(过期瞬间大量请求)
- 互斥锁(Mutex Lock):当缓存失效时,用分布式锁(如Redis的SETNX)保证只有一个线程去查数据库,其他线程等待后重试。
- 逻辑过期:不设置物理过期时间,而是在缓存中存储过期时间戳。若发现数据过期,触发异步线程更新缓存,期间旧数据仍可返回。
- 永不过期+主动更新:结合定时任务(如Quartz)在缓存失效前主动刷新数据。
问:redis缓存热点数据如何发现和优化?
热点数据发现:
- 使用redis-cli --hotkeys命令:(需开启maxmemory-policy allkeys-lfu): 这个命令能快速找出高频访问的键,但生产环境慎用,因为会阻塞Redis(类似KEYS *)数据量超过单机内存,需分片存储。
- 客户端埋点统计:在业务代码里记录键的访问次数,比如用AOP切面拦截缓存操作,统计每个Key的访问频率,上报到监控系统(如Prometheus)。
- 网络流量监控抓Redis端口流量:用工具(如tcpdump)分析请求分布,发现异常高频的Key。
优化思路:
- 本地缓存:在应用层(如JVM内存)缓存数据,减少Redis访问。
- 数据分片:将热点Key拆分为多个子Key,分散到不同节点或实例。场景:单个Key访问量过大(如秒杀商品)。
问:redis慢查询如何发现和优化?
慢查询发现: 启用Redis的慢查询日志功能:配置slowlog-log-slower-than 1000(记录超过1ms的命令),分析高频或耗时的操作。一般来说可能是因为操作了一个非常大的哈希表(Big Key),这时候就需要考虑优化数据结构或者拆分键了。
优化思路(Big Key):
- 必须保留Big Key:如果必须保留大键,可以考虑异步处理或者分页查询,避免一次性操作全部数据。
- 数据分片:将Big Key拆分为多个子Key,比如库存数据,我们可能会根据不同的货主或者仓库去做数据拆分。
问:Redis内存占用过高如何排查和优化?
排查和优化:
- 大键:用redis-cli --bigkeys快速扫描大键,看是不是某个键的数据量异常,比如一个哈希表存了几十万条数据。同时,用MEMORY USAGE key_name可以精确计算某个键的内存占用,定位到具体问题键。分析是否可以拆分数据,或者异步迁移到冷存储(比如MySQL),Redis只保留最近的热数据。
- 内存碎片:检查内存占用率,可以用INFO memory里的mem_fragmentation_ratio字段判断,如果比率大于1.5,说明碎片较严重。这时候如果条件允许可以考虑重启redis。或者用CONFIG SET activedefrag yes开启自动内存碎片整理。
- 过期key未及时清理:如果大量键设置了过期时间但未及时清理,内存可能被已过期但未回收的键占用,这时可以手动检查并删除过期键,或者调高hz配置让Redis更频繁回收内存。