缓存穿透和缓存雪崩的预防和解决-Redis

Redis:

缓存穿透和缓存失效的预防和解决

缓存穿透:

场景:

     缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

解决方案:

1、对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。还有最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

2、也可以采用一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

缓存雪崩

场景:

     如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。

     这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。

解决方案:

     在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
     可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是Redis缓存穿透、击穿和雪崩的简单demo: ## Redis缓存穿透 Redis缓存穿透是指查询一个不存在的数据,由于缓存中没有,导致请求直接打到数据库上,从而可能引起数据库压力过大或宕机等问题。 ```python import redis # 初始化Redis连接 redis_conn = redis.Redis(host='localhost', port=6379, db=0) # 模拟查询一个不存在的数据 key = 'non_existent_key' data = redis_conn.get(key) if not data: # 如果Redis缓存中没有该数据,则从数据库中获取数据 # 这里省略从数据库中获取数据的代码 print('Data not found in Redis cache or database!') ``` ## Redis缓存击穿 Redis缓存击穿是指某个热点数据在缓存失效的瞬间,同时有大量并发请求访问该数据,由于缓存失效,这些请求都会直接打到数据库上,从而可能引起数据库压力过大或宕机等问题。 ```python import redis import time # 初始化Redis连接 redis_conn = redis.Redis(host='localhost', port=6379, db=0) # 设置一个热点数据,缓存有效期为10秒 key = 'hot_data' value = 'hot_data_value' redis_conn.setex(key, 10, value) # 模拟大量并发请求访问该热点数据 for i in range(100): data = redis_conn.get(key) if not data: # 如果Redis缓存中没有该数据,则从数据库中获取数据 # 这里省略从数据库中获取数据的代码 print('Data not found in Redis cache or database!') else: print(f'Data: {data}') time.sleep(0.1) # 等待0.1秒,模拟并发请求 ``` ## Redis缓存雪崩 Redis缓存雪崩是指缓存中大量数据在同一时间失效,导致大量并发请求直接打到数据库上,从而可能引起数据库压力过大或宕机等问题。 ```python import redis import time # 初始化Redis连接 redis_conn = redis.Redis(host='localhost', port=6379, db=0) # 设置大量缓存数据,缓存有效期为10秒 for i in range(10000): key = f'data_{i}' value = f'data_{i}_value' redis_conn.setex(key, 10, value) # 模拟大量并发请求访问这些缓存数据 for i in range(10000): key = f'data_{i}' data = redis_conn.get(key) if not data: # 如果Redis缓存中没有该数据,则从数据库中获取数据 # 这里省略从数据库中获取数据的代码 print(f'Data {key} not found in Redis cache or database!') else: print(f'Data {key}: {data}') time.sleep(0.01) # 等待0.01秒,模拟并发请求 ``` 这些demo仅作为演示Redis缓存穿透、击穿和雪崩的基本情况,实际应用中还需要更加复杂和完善的解决方案

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值