结论:Redis作为高性能的内存数据库,通过缓存热点数据、减少数据库压力、实现热点数据预热和穿透保护,能显著提升网站性能。在实战中,采用缓存穿透解决方案如布隆过滤器、热点数据预热、读写分离结合缓存更新策略,可将QPS从1000提升到5000,响应时间从200ms降至50ms。核心代码示例:使用Spring Boot集成Redis缓存注解:
@Cacheable(value = "user", key = "#id")
public User getUserById(Long id) { return userMapper.selectById(id); }
@CacheEvict(value = "user", key = "#user.id")
public void updateUser(User user) { userMapper.update(user); }
实战经验一
在电商平台中,我们面临高并发场景下的库存查询瓶颈。直接查询MySQL数据库会导致锁竞争和响应延迟。通过引入Redis缓存,库存数据以key为商品ID存储,采用Lua脚本实现原子扣减:local stock = redis.call('get', KEYS[1]) if tonumber(stock) > 0 then redis.call('decr', KEYS[1]) return 1 else return 0 end。这种方式将库存扣减QPS从500提升到3000,库存超卖问题彻底解决。
实战经验二
缓存穿透是常见问题,黑客故意查询不存在的数据,导致请求直达数据库。我们使用布隆过滤器预判数据是否存在,只在可能存在时才查DB。代码实现:BloomFilter<String> bloomFilter = new BloomFilter<>(expectedInsertions, fpp); if (!bloomFilter.mightContain(key)) { return null; } else { String value = redis.get(key); if (value == null) { bloomFilter.put(key); } return value; } 这有效阻挡了90%的无效请求。
实战经验三
热点数据缓存失效会导致雪崩。解决方案是多级缓存:L1 Nginx本地缓存(1s TTL),L2 Redis缓存(30s TTL),L3 DB。预热脚本在Redis重启后立即加载Top100热点key。同时设置随机TTL:expire key (30 + random(1,5)) * 60,避免同时失效。实际效果:故障恢复时间从10分钟缩短到30秒。
实战经验四
分布式锁用于秒杀场景,确保库存扣减串行化。RedLock算法实现:使用多个Redis节点,获取锁需3/5节点成功。代码:String lockKey = "lock:" + goodsId; try { if (redisson.getLock(lockKey).tryLock(10, 30, TimeUnit.SECONDS)) { // 扣减库存 } } finally { redisson.getLock(lockKey).unlock(); } 这比单节点setnx可靠得多,误锁率降至0.01%。
实战经验五
Session共享使用Redis存储,key格式:sess:userId,value为JSON序列化Session。设置滑动过期:用户操作时刷新TTL。代码:redis.setex("sess:" + userId, 1800, sessionJson); 在Nginx负载均衡下,实现无状态服务,单机扩容无需重登陆。
实战经验六
Pipeline批量操作优化网络RTT。我们将100个set命令打包成一个pipeline执行,吞吐量提升5倍。代码:Pipeline pipeline = jedis.pipelined(); for (int i = 0; i < 100; i++) { pipeline.set("key" + i, "value" + i); } pipeline.sync(); 特别适合日志写入和批量更新场景。
FAQ
Q: Redis缓存穿透怎么解决?
A: 用布隆过滤器判断key是否存在,不存在直接返回null;空值也缓存,设置短TTL。
Q: 缓存雪崩如何预防?
A: 设置随机TTL,多级缓存,预热热点数据,限流熔断。
Q: Redis内存不足怎么办?
A: 配置maxmemory-policy allkeys-lru,监控info memory,及时扩容或清理冷数据。
Q: 分布式锁怎么实现高可用?
A: 用RedLock多节点投票,或基于ZooKeeper实现。