redis缓存的数据类型分析
字符串(string):
- 优点:字符串存储节省内存
- 缺点:序列化转换(读写过程需要做数据的转换处理)消耗时间,更新操作不方便。
其他类型(hash、set、zset、list):
- 优点:读写时不需要序列化转换,可以更新内部指定数据
- 缺点:相比于string,采用复合结构存储占用空间比较大
设置过期时间:
作用:节省内存,保持数据的弱一致性(过期时间的设置,能在一定程度上保持缓存与数据库之间的数据一致)
- 定时过期
每个设置过期时间的key,都需要创建一个定时器,到过期时间就会立即清除
优点:对内存友好(节省内存)
缺点:会占用大量的CPU资源处理过期数据,影响缓存的响应时间和吞吐量 - 惰性过期
只有当访问一个key时,才会判断是否过期,过期则清除
优点:最大化的节省CPU资源
缺点:对内存非常不友好(极端情况会出现大量的过期的key没有被访问,从而不会被清除,占用大量内存) - 定期过期
每隔一定的时间间隔,会随机的扫描一部分缓存数据,并清除其中已经过期的key,可以通过调整过期时间与扫描范围来使得CPU与内存达到一个性能的最优先
内存淘汰策略
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key
- allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除使用频率最少的key
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
- volatile-lfu:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除使用频率最少的key
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
注意:redis 4.x 后支持LFU策略,最少频率使用
两种内存淘汰算法
- LRU(Least recently used,最近最少使用):
LRU算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”
基本思路:
1、新数据插入到列表头部;
2、每当缓存命中(即缓存数据被访问),则将数据移到列表头部;
3、当列表满的时候,将列表尾部的数据丢弃。 - LFU(Least Frequently Used 最近最少使用算法):
LFU算法基于“如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小”的思路
注意:LFU算法需要用到定期衰减
缓存模式(详解后续更新…)
- Cache Aside
- Read-Through
- Write-Through
- Write-Back
更新方式:
- 先更新数据库,再更新缓存
- 先删除缓存,再更新数据库
- 先更新数据库,再删除缓存
缓存问题及解决方案
- 缓存穿透
缓存只是为了缓解数据库压力而添加的一层保护层,当从缓存中查询不到我们需要的数据就要去数据库中查询了。如果被黑客利用,频繁去访问缓存中没有的数据,那么缓存就失去了存在的意义,瞬间所有请求的压力都落在了数据库上,这样会导致数据库连接异常
解决方案:
1、对于返回为NULL的依然缓存,对于抛出异常的返回不进行缓存,注意不要把抛异常的也给缓存了。采用这种手段的会增加我们缓存的维护成本,需要在插入缓存的时候删除这个空缓存,当然我们可以通过设置较短的超时时间来解决这个问题。
2、制定一些规则过滤一些不可能存在的数据,小数据用BitMap,大数据可以用布隆过滤器。 - 缓存雪崩
缓存雪崩是指缓存不可用或者大量缓存由于超时时间相同在同一时间段失效,大量请求直接访问数据库,数据库压力过大导致系统雪崩
解决方案:
1、给缓存加上一定区间内的随机生效时间,不同的key设置不同的失效时间,避免同一时间集体失效
2、采用多级缓存,不同级别缓存设置的超时时间不同
3、利用加锁或者队列方式避免过多请求同时对服务器进行读写操作