一、缓存的收益与成本
1、受益
①加速读写
②后端服务器通过前端缓存降低负载,业务端使用redis缓存降低sql负载
2、成本
①缓存端和数据端有时会因为时间窗口不一致导致数据时效不一致,和更新策略有关
②多了一层缓存逻辑,代码维护成本提高
③使用主从,哨兵,集群等,服务器成本提高,进而运维成本也提高
3、使用场景
①降低后端负载:对高消耗的sql,join结果集/分组统计的结果做缓存
②加速请求响应:利用缓存优化io响应时间
③大量写合并为批量写:如计数器先在缓存累加再批量写入sql
二、缓存更新策略
1、算法剔除:如达到maxmemory-policy时,对应的策略
①LRU(Least Recently Used):先剔除没有被使用时间最长的
②LFU(Least Frequenty User):先剔除一定时间段内使用次数最少的
③FIFO(First In First Out):先存入的先剔除
④LIRS(Low Inter-reference Recency Set):页替换算法,相比于其他替换算法,LIRS具有较高的性能,通过使用两次访问同一页之间的距离(该距离指中间被访问了多少非重复块),作为一种尺度去动态地将访问页排序,从而去做一个替换的选择
2、超时剔除:如expire,设置过期时间
3、主动更新:使用定时任务等控制生命周期
4、优劣比较:
①一致性:算法剔除很差,超时剔除较差,主动更新比较好
②维护成本:算法剔除和超时剔除都比较低,主动更新比较高
三、maxmemory-policy配置方案
1、LRU相关
①noeviction: 如果内存使用达到了maxmemory,client还要继续写入数据,那么就直接报错给客户端
②allkeys-lru: 就是我们常说的LRU算法,移除掉最近最少使用的那些keys对应的数据,ps最长用的策略
③volatile-lru: 也是采取LRU算法,但是仅仅针对那些设置了指定存活时间(TTL)的key才会清理掉
④allkeys-random: 随机选择一些key来删除掉
⑤volatile-random: 随机选择一些设置了TTL的key来删除掉
⑥volatile-ttl: 移除掉部分keys,选择那些TTL时间比较短的keys
2、LFU相关:
①volatile-lfu:对有过期时间的key采用LFU淘汰算法(redis4.0新增策略)
②allkeys-lfu:对全部key采用LFU淘汰算法(redis4.0新增策略)
③lfu-log-factor count:可以调整计数器counter的增长速度,lfu-log-factor越大,counter增长的越慢
④lfu-decay-time count:一个以分钟为单位的数值,可以调整counter的减少速度
四、缓存粒度控制
1、缓存全部字段:通用性较好,占用空间较大,维护成本一般较低
2、缓存部分字段:通用性较差,占用空间较小,维护成本一般较高
五、缓存风险
1、缓存穿透
①描述:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为"-1"的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大
②解决方案1:接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截
③解决方案2:从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用),这样可以防止攻击用户反复用同一个id暴力攻击
④解决方案3:通过布隆过滤器拦截
2、缓存击穿
①描述:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
②解决方案:设置热点数据永远不过期
3、缓存雪崩
①描述:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库
②解决策方案1:缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
③解决策方案2:如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中
④解决策方案3:设置热点数据永远不过期