写在开头:
本章是Redis学习归纳第六部分,着重于归纳redis常见的的缓存问题。
文章内容输出来源:拉勾教育大数据高薪训练营。
缓存穿透
缓存穿透是指在高并发下查询key不存在的数据,那么大量的请求就会穿过redis直接访问数据库上导致数据库宕机。
解决方式:客户端请求redis之前,加上布隆过滤器。我们可以先把数据库中有的key,放到布隆过滤器中,先检查查询的key是否存在,不存在直接返回,存在就再去缓存找,肯定就有。
缓存雪崩
缓存雪崩就是说大量的缓存在某个时间段失效,在失效时请求会直接达到DB上,导致DB宕机
结局方式:
1.key的失效时间分散开,不同的key设置不同的失效时间,这样就可以减少集体失效的问题。
缓存击穿
缓存击穿指的是对于某一个key设置了超时时间,但是这个key会在某个时间段被超高并发访问,然后再被高并发访问时到达超时时间然后失效,大量的请求发现该key已经失效就会穿过缓存直接访问数据库,造成数据库宕机。
解决方案:
1.使用分布式锁来控制访问的线程,使用redis命令setnx设置互斥锁,保证不要让高并发直接去访问数据库,可以先控制一个线程去访问数据库,拿到数据后回填到缓存中。
2.不设置超时时间,但是存在一个问题,缓存中的数据和数据库中的数据并不是时时一致的,那也就是说会读到脏数据。这个可以使用延时双删策略。
数据不一致
刚才上述问题中,如果我们不设置key的超时时间,就会造成数据不一致的问题,要如何解决呢?数据强一致性很难,我们可以追求最终一致性:
1 先更新数据库同时删除缓存,等读的时候在填充回去。为什么要删除而不是修改缓存呢?因为缓存中有可能是复杂数据类型,例如hash,那么修改的消耗很大,不如直接删了。
2 上一项说在更新数据库时同时删除缓存,但是这时数据库可能还未commit,所以万一有请求过来访问数据库,然后回填到redis中,那么这个redis中的还是脏数据。所以我们设定2秒后再删除一次缓存
数据并发竞争
这里的并发指的是多个redis客户端同时set同一个key,那这样value值就会以最后一个客户端设置的值为准。
解决方式:
1 redis分布式锁+时间戳,主要就是setnx命令,早高并发环境下我们要求key的操作都要顺序执行,所以需要保存一个时间戳,如果一个进程b抢到锁,发现缓存中的时间戳大于自己的,那么就不做set操作了。
Hot Key问题
当有十几万的请求访问到某个redis的某个key时,流量达到网络上线,导致该redis宕机。一宕机就穿过缓存打到数据库上导致数据库宕机,如果使用分布式锁的方式回填redis,将继续崩溃。
如何处理热键?
1 发现热键后将缓存数据取出,加载到本地缓存中。
2 在每个redis节点上备份热键数据,读取时采用随机读取的方式平均压力。
3 对于热点数据添加熔断机制,比如设定每秒最多请求集群度操作400次,超过就熔断,直接返回空白信息,提示用户稍后再试。
Big Key问题
大key就是指存储的value非常大,常见于:
- 热门话题下的讨论
- 大V的粉丝列表
- 序列化后的图片
- 没有及时处理的垃圾数据
这种大key的影响是什么?
1 占用大量内存
2 redis性能下降
3 删除时会造成长时间的阻塞
大key的处理:
1 如果是string类型就减少字符串长度,如果是list,hash,set,zset就减少元素数量。
2 string类型的大key不要存入redis中,可以考虑存入mongDB,如果必须用redis存储,那么最好单独存储,不要和其他key一起存。
3 单个简单的key存储的value很大,可以考虑将对象拆分成几个key-value,用hmget获取值,把一个单次操作的压力拆分到多次操作中,降低redis的IO影响。
4 删除大key时不要使用del命令,因为会导致长时间阻塞,使用unlink命令删除大key