缓存穿透:当用户查询一个不存在的数据时,由于缓存未命中,直接请求数据库,如果恶意攻击会导致数据库压力巨大。解决方案:1. 接口层校验用户输入;2. 缓存空值,设置短过期时间;3. 布隆过滤器快速判断key是否存在。缓存雪崩:大量缓存同时失效,导致请求全部打到数据库。解决方案:1. 缓存设置不同过期时间,避免同时失效;2. 热点数据永不过期或预热;3. 降级熔断,使用限流。缓存击穿:热点key失效瞬间,大量并发请求打到数据库。解决方案:互斥锁,单个线程加载数据,其他线程等待;逻辑过期,定时任务异步刷新。
Redis核心数据结构详解
String类型:最简单,支持二进制数据,常用场景计数器、session存储。List:双向链表,支持LPUSH、RPOP,队列或栈。Hash:键值对集合,节省内存,存储对象。Set:无序集合,支持交并差,抽奖、标签。ZSet:有序集合,按score排序,排行榜、延迟队列。
Redis持久化机制
RDB快照:定时fork子进程生成快照文件,适合冷备份,数据丢失少量。AOF日志:记录每条写命令,重启时重放,数据更安全但恢复慢。混合模式:RDB+AOF,定期AOF重写。选择依据:RDB适合大数据量,AOF适合高可靠性。
Redis主从复制与哨兵
主从复制:异步复制,主节点写,从节点读,提升读性能。满量+增量同步。哨兵:监控主从,自动故障转移,主节点挂了选从节点升主。配置sentinel monitor mymaster 127.0.0.1 6379 2。
Redis Cluster分片集群
16384个槽,CRC16(key)%16384分配槽到节点。节点间gossip协议通信,心跳检测故障。添加节点:cluster meet,新节点加入后rebalance槽。扩容缩容无停机。
缓存穿透实战代码
使用布隆过滤器:BloomFilter filter = new BloomFilter(1000000, 0.01); if (!filter.mightContain(key)) return null; String value = redis.get(key); if (value == null) { value = db.get(key); if (value != null) redis.setex(key, 3600, value); else { redis.setex(key, 60, ""); filter.put(key); } } return value;
雪崩预防
设置随机过期时间:expireTime = currentTime + expireSeconds + random(0, 300); 热点key监控:使用zset存储访问频率,定时刷新高频key。限流:使用令牌桶或漏桶算法,redis原子递减计数器。
FAQ
Q: 缓存穿透和击穿区别?
A: 穿透是查不存在数据,击穿是热点key失效瞬间并发。
Q: Redis内存不足怎么处理?
A: 配置maxmemory-policy allkeys-lru,主动淘汰最近最少用key。
Q: 主从延迟怎么优化?
A: 开启parallel-syncs,调整repl-diskless-sync yes。
Q: Redis如何做分布式锁?
A: set key value nx px 30000,释放用lua脚本del确保原子性。