首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
您找到你想要的搜索结果了吗?
是的
没有找到

缓存穿透、击穿、雪崩的成因及解决方案

缓存击穿的成因 缓存击穿是指在高并发场景下,某个热点数据的缓存突然失效(如缓存过期),而这时恰好有大量的并发请求来访问这个刚刚失效的key,所有请求都无法从缓存中获取到数据,进而都涌向数据库,导致数据库瞬时压力过大,这就是所谓的“击穿”。尤其是在数据更新并不频繁的情况下,这种集中性的数据库查询压力可能导致数据库响应变慢,甚至宕机。 解决方案 - Java代码示例(使用Redis分布式锁) 下面是一个基于Redis实现分布式锁,用于解决缓存击穿问题的基本Java代码框架: import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.RedisScript; import java.util.Collections; @Service public class CacheService { private final StringRedisTemplate redisTemplate; private final RedisScript<Long> luaLockScript; public CacheService(StringRedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; luaLockScript = new DefaultRedisScript<>(// 定义Lua脚本,用于获取分布式锁 "if redis.call('exists', KEYS[1]) == 0 then " + "redis.call('hset', KEYS[1], ARGV[1], 1);" + "redis.call('pexpire', KEYS[1], ARGV[2]); " + "return 1; " + "end;" + "return 0;", Long.class); } public Object getDataFromDBWithLock(String cacheKey) { Boolean locked = acquireLock(cacheKey, "uniqueId"); // 尝试获取锁 if (locked) { try { // 如果获取到锁,则尝试从缓存中获取数据 Object data = getDataFromCache(cacheKey); if (data != null) { return data; } // 缓存未命中,从数据库加载数据 data = loadFromDatabase(cacheKey); // 将数据写入缓存 writeToCache(cacheKey, data); return data; } finally { releaseLock(cacheKey, "uniqueId"); // 无论何时,都要确保最后释放锁 } } else { // 没有获取到锁,等待其他线程完成数据库操作后从缓存中读取 return getDataFromCacheAfterWait(cacheKey); } } private Boolean acquireLock(String key, String uniqueId) { // 调用Lua脚本获取分布式锁,这里假设expireTime是你设置的锁超时时间 Long result = redisTemplat

01
领券