赞
踩
缓存穿透
什么是缓存穿透
正常情况下,查询的数据都存在,如果请求一个不存在的数据,也就是缓存和数据库都查不到这个数据,每次都会去数据库查询,这种查询不存在数据的现象我们称为缓存穿透
穿透带来的问题
如果每次都拿一个不存在的id去查询数据库,可能会导致你的数据库压力增大
解决办法
缓存空值:
之所以发生穿透,是因为缓存中没有存储这些数据的key,从而每次都查询数据库我们可以为这些key在缓存中设置对应的值为null,后面查询这个key的时候就不用查询数据库了当然为了健壮性,我们要对这些key设置过期时间,以防止真的有数据BloomFilter(布隆过滤器):
BloomFilter 类似于一个hbase set 用来判断某个元素(key)是否存在于某个集合中,我们把有数据的key都放到BloomFilter中,每次查询的时候都先去BloomFilter判断,如果没有就直接返回null,注意BloomFilter没有删除操作,对于删除的key,查询就会经过BloomFilter然后查询缓存再查询数据库,所以BloomFilter可以结合缓存空值用,对于删除的key,可以在缓存中缓存null
缓存击穿
什么是缓存击穿
在高并发的情况下,大量的请求同时查询同一个key时,此时这个key正好失效了,就会导致同一时间,这些请求都会去查询数据库,这样的现象我们称为缓存击穿
击穿带来的问题
会造成某一时刻数据库请求量过大
解决办法
采用分布式锁,只有拿到锁的第一个线程去请求数据库,然后插入缓存,当然每次拿到锁的时候都要去查询一下缓存有没有
缓存雪崩
什么是缓存雪崩
当某一时刻发生大规模的缓存失效的情况,比如你的缓存服务宕机了
解决办法
解决热点数据集中失效问题
我们在设置缓存的时候,一般会给缓存设置一个失效时间,过了这个时间,缓存就失效了。对于一些热点的数据来说,当缓存失效以后会存在大量的请求过来,然后打到数据库去,从而可能导致数据库崩溃的情况
解决办法
1.设置不同的失效时间
2.采用缓存击穿的解决办法,加锁
3.永不失效,就是采用定时任务对快要失效的缓存进行更新缓存和失效时间
Redis中的数据特征
redis是一种内存级数据库,所有的数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态
删除策略就是针对已过期数据的处理策略
,已过期的数据是真的就立即删除了吗?其实也不是,我们会有多种删除策略,是分情况的,在不同的场景下使用不同的删除方式会有不同效果
时效性数据的存储结构
在redsi中,如果给数据设置了过期时间,那麽数据的存储结构如下图所示
过期数据是一块独立的存储空间,Hash结构,field是内存地址,value是过期时间,保存了所有key的过期描述,在最终进行过期处理的时候,对该空间的数据进行检测, 当时间到期之后通过field找到内存该地址处的数据,然后进行相关操作。
1.2 数据删除策略
数据删除策略的目的是什么?
在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能下降,甚至引发服务器宕机或内存泄漏。
针对过期数据要进行删除的时候都有哪些删除策略呢?
定时删除:
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
优点: 节约内存,到时就删除,快速释放掉不必要的内存占用
缺点: CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响 redis服务器响应时间和指令吞吐量
总结:用处理器性能换取存储空间(拿时间换空间)
惰性删除:
数据到达过期时间,不做处理。等下次访问该数据时,我们需要判断:
优点: 节约CPU性能,发现必须删除的时候才删除
缺点: 内存压力很大,出现长期占用内存的数据
总结: 用存储空间换取处理器性能(拿空间换时间)
定期删除:
定时删除和惰性删除这两种方案都是走的极端,那有没有折中方案?
来说下redis的定期删除方案:
serverCron()--(定时轮询)
------>databasesCron()---(轮询访问当前redis中的所有库)>
---------->activeExpireCycle()
activeExpireCycle()
对每个expires[*]逐一进行检测,每次执行耗时:250ms/server.hz具体流程见下图:
总的来说:定期删除就是周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度
删除策略对比
1:定时删除:
节约内存,无占用,
不分时段占用CPU资源,频度高,
拿时间换空间
2:惰性删除:
内存占用严重
延时执行,CPU利用率高
拿空间换时间
3:定期删除:
内存定期随机清理
每秒花费固定的CPU资源维护内存
随机抽查,重点抽查
数据淘汰策略(逐出算法)
淘汰策略概述
什么叫数据淘汰策略?什么样的应用场景需要用到数据淘汰策略?
当新数据进入redis时,如果内存不足怎么办?在执行每一个命令前,会调用freeMemoryIfNeeded()
检测内存是否充足。如果内存不满足新 加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法。
注意:逐出数据的过程不是100%能够清理出足够的可使用的内存空间,如果不成功则反复执行。当对所有数据尝试完毕, 如不能达到内存清理的要求,将出现错误信息如下
(error) OOM command not allowed when used memory >'maxmemory'
策略配置
影响数据淘汰的相关配置如下:
那数据删除的策略policy到底有几种呢?一共是3类8种
第一类:检测易失数据(可能会过期的数据集server.db[i].expires )
volatile-lru:挑选最近最少使用的数据淘汰,可以理解成最近最久未使用
volatile-lfu:挑选最近使用次数最少的数据淘汰
volatile-ttl:挑选将要过期的数据淘汰
volatile-random:任意选择数据淘汰
结合下图进行理解:
第二类:检测全库数据(所有数据集server.db[i].dict )
allkeys-lru:挑选最近最少使用的数据淘汰
allkeLyRs-lfu::挑选最近使用次数最少的数据淘汰
allkeys-random:任意选择数据淘汰,相当于随机
第三类:放弃数据驱逐
no-enviction(驱逐):禁止驱逐数据(redis4.0中默认策略),会引发OOM(Out Of Memory)
注意:上面说了折磨多废话,那麽这些策略是在哪里配置呢?配置到哪个属性上?怎么配置?
这里只需要进入到redis.conf文件中去进行配置就可以了,具体配置如下:
maxmemory-policy volatile-lru
注意: 如果是你自己想要测试一下一上这些数据删除策略,前提是你的redis中有着海量数据,需要通过大量数据去冲击内存才能达到你想要看到的效果
数据淘汰策略配置依据
使用INFO
命令输出监控信息,查询缓存 hit 和 miss 的次数,根据业务需求调优Redis配置
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。