redis的进程锁避免缓存击穿
首先由于系统的特性知道哪些键是热键,针对这些热键,哪个线程发现自己现在拿的是空,马上锁住,获取向下操作的资格,其他阻塞(这样就不会对db压力大(不然都去访问db)),然后马上这UI个线程请求db获取数据填充缓存
缓存击穿
对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方案
1.使用互斥锁(mutex key)
业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。在redis2.6.1之前版本未实现setnx的过期时间,所以这里给出两种版本代码参考:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
//2.6.1前单机版本锁
String get(String key) {
String value = redis.get(key);
if (value == null) {
if (redis.setnx(key_mutex, "1")) {
// 3 min timeout to avoid mutex holder crash
redis.expire(key_mutex, 3 * 60)
value = db.get(key);
redis.set(key, value);
redis.delete(key_mutex);
} else {
//其他线程休息50毫秒后重试
Thread.sleep(50);
get(key);
}
}
}
最新版本代码:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
public String get(key) {
String value = redis.get(key);
if (value == null) { //代表缓存值过期
//设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(key_mutex);
} else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
sleep(50);
get(key); //重试
}
} else {
return value;
}
相关推荐
4. 使用分布式锁机制,例如使用 ZooKeeper 或 Etcd 等分布式锁,来避免缓存击穿问题。 缓存穿透、雪崩、击穿都是缓存使用中可能出现的问题,但是通过合理的解决方案,可以避免这些问题的出现,并确保系统的稳定运行...
缓存系统设计解决方案分析 缓存系统是当前web应用程序中最常用的性能...缓存系统设计需要考虑的要素很多,但是如果我们采用合适的解决方案,可以避免缓存穿透、缓存雪崩和缓存击穿等问题,提高系统的性能和可靠性。
缓存穿透、缓存击穿、缓存雪崩解决方案分析 本文主要介绍了缓存系统中三个常见的问题:缓存穿透、缓存击穿和缓存雪崩,并对每个问题提供了多种解决方案。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于...
在Redis 2.6.1之前的版本,`SETNX`命令没有设置过期时间的能力,因此在旧版本中需要手动添加过期时间,以避免持有锁的进程崩溃导致无法释放锁。 ```java // 2.6.1前单机版本锁实现 public String get(String ...
- **缓存失效策略**:缓存穿透、缓存雪崩和缓存击穿是高并发场景下的潜在风险,需合理设计缓存失效机制。 - **键的设计**:通常将表名作为key前缀,用冒号分隔,然后是列名和主键值,如`user:6`。 **Redis的特定...
缓存击穿通常发生在高并发访问热点数据时,如果这些数据恰好过期了,也会造成瞬间流量集中到数据库。为此,可以采取热点数据不过期或者使用分布式锁保护数据更新。 二、缓存整合Redis 在Spring Boot项目中整合...
在使用 Redis 过程中,你如何处理缓存击穿的问题?能详细说明一下解决方案吗? - **缓存击穿**:缓存和数据库中的数据同时失效,导致大量请求直接打到数据库,引起数据库压力过大。 - **解决方案**: - 使用互斥...
- **缓存击穿**: 大量并发请求同时访问同一缓存数据,导致后端数据库压力过大。 - **解决方案**: 使用互斥锁(Mutex)或者双重检查锁定(Double-Checked Locking)来控制并发访问。 - **缓存雪崩**: 缓存中大量数据同时...
3. **缓存击穿**:某一热点key刚好过期,此时大量请求同时到达,导致数据库压力剧增。 解决方案:设置热点key永不过期,或者使用预加载策略。 六、缓存更新策略 1. **写后读(Write Through)**:更新数据库后...
6. **缓存穿透、缓存击穿与缓存雪崩**:这三个是缓存系统常见的问题,需要合理设计缓存策略来避免。缓存穿透是指请求的数据在数据库中不存在,造成对数据库的无效查询;缓存击穿是大量请求同一时刻到达,导致缓存...
- **区别**: 缓存击穿针对单一热点key,而缓存雪崩涉及大量key同时过期,影响更大。 - **解决方案**: - **热点数据永不过期**: 减少因过期导致的请求激增。 - **随机过期时间**: 为每个key设置不同的过期时间,...
11. **Redis缓存击穿解决方案**: - 分布式锁:保证同一时刻只有一个线程更新缓存。 - 设置超时标记:在缓存对象中包含一个超时时间戳,临近超时时异步刷新缓存。 - 热点数据不过期:在高峰期保持缓存,低峰期再...
- **缓存击穿**:特定key在缓存中过期,大量请求直接到达数据库。 - **缓存雪崩**:大量缓存同时过期,导致请求瞬间涌入数据库。 - **缓存穿透**:恶意请求不存在的key,导致数据库压力增大。 15. **TCP连接**:...
- **实现数据一致性**:使用缓存穿透、缓存击穿和缓存雪崩的解决方案,如使用布隆过滤器预防穿透,设置合理的缓存超时时间防止击穿,分散热点数据减轻雪崩效应。 **知识点四:消息队列故障处理** - **消息队列作用*...
9. **Redis雪崩和击穿**: - 雪崩:大量缓存同时过期,导致数据库瞬间压力过大。 - 击穿:某个热点key过期,所有请求直接穿透到数据库。 10. **面向对象的理解**: 面向对象编程(OOP)是一种编程范式,以对象为...