
redis 最常用的场景
核心思路就是把一些常用的数据,放到触手可及(访问速度更快)的地方
速度快的设备,可以作为速度慢的设备的缓存
CPU 寄存器 > 内存 > 硬盘 > 网络最常见的是,使用内存作为硬盘的缓存(redis 定位)
硬盘也可以作为网络的缓存——浏览器的缓存
http/https 从服务器上获取到数据(html、css、js、图片、视频、音频、字体…)并进行展示 缓存能够有意义,二八定律
20% 的数据,可以应对 80% 的请求通常是使用 redis 作为数据库的缓存(MySQL)
MySQL 的速度又比较慢为什么说关系型数据库性能不高?
SQL 的执行会做一系列的解析,校验,优化工作因为 MySQL 等数据库,效率比较低,多以承担的并发量就有限,一旦请求数多了,数据库的压力就会很大,甚至很容易就宕机了
如何提高 MySQL 能承担的并发量?(客观需求)
MySQL 了
redis 上只能存少数数据,但是大部分请求都是使用的这少数的热点数据3:7,1:9 无所谓,基本思想是一致的如何知道 redis 中应该存储哪些数据?
如何知道哪些数据是热点数据呢?
这里就要谈到“缓存的更新策略“
会把访问的数据,以日志的形式记录下来
比如一个搜索引擎,“查询词”就是要关注的“访问的数据”
20% 的词,就可以把这些词认为是“热点词” Hadoop 的 map-reduce 来写代码进行统计;也可以基于 HDFS 的 HBASE 这样的数据库来写 SQL 统计redis”这样的缓存中了此处的数据,就可以根据当前这里统计的未读,来定期更新
shell,Python 写脚本代码),可以通过定时任务来触发优点:上述过程,实际上实现起来比较简单,过程更可控(缓存中有什么是比较固定的),方便排查问题 缺点:实时性不够。如果出现一些突发性时间,有一些本来不是热词的内容,成了热词了,新的热词就可能会给后面的数据库什么的带来比较大的压力
redis 查到了,就直接返回redis 中不存在,就从数据库查,把查到的结果同时也写入 redis这样不停地写 redis,就会使 redis 的内存占用越来越多,就会逐渐达到内存上限
redis 中也可以配置,最多使用多少内存(maxmermory 参数)如果继续往里插入数据,就会触发问题,为了解决上述问题,redsi 就引入了“内存淘汰策略”
#高频面试
FIFO(First In First Out)先进先出
把缓存中存在时间最久的(也就是先来的数据)淘汰掉
LRU (Least Recently Used) 淘汰最久未使用的
记录每个 key 的最近访问时间,把最近访问时间最老的 key 都淘汰掉
LFU(Least Frequently Used)淘汰访问次数最少的
记录每个 key 最近一段时间的访问次数,把访问次数最少的淘汰掉
Random 随机淘汰
从所有的 key 中抽取幸运儿被随机淘汰
理解上述几种淘汰策略: 想象你是个皇帝,有后宫佳丽三千。虽然你是真龙天子,但是经常宠信的妃子也就那么寥寥数人(后宫佳丽散散,相当于数据库中的全量数据,经常宠信的妃子相当于热点数据,是放在缓存中的) 今年选秀的一批新的小主,其中一个被你看上了,宠信新人,自然就需要有旧人被冷落,到底谁是要被冷落的人呢?
FIFO:皇后是最先受宠的,现在已经年老色衰了==>皇后失宠LRU:统计最近宠幸时间,皇后(一周前),熹妃(昨天),安答应(两周前),华妃(一个月前)==>华妃失宠LFU:统计最近一个月的宠幸次数,皇后(3 次),熹妃(15 次),安答应(1 次),华妃(10 次)==>安答应失宠(最合理)Random:随机挑选一个妃子失宠(最不合理)
具体采取哪种策略,要结合实际场景来具体问题具体分析redis 里面,有一个配置项,就可以设置 redis 采取上述哪种策略淘汰内存数据
volatile-lru 当内存不⾜以容纳新写⼊数据时,从设置了过期时间的 key 中使⽤ LRU(最近最少使⽤)算法进⾏淘汰
allkeys-lru 当内存不⾜以容纳新写⼊数据时,从所有 key 中使⽤ LRU(最近最少使⽤)算法进⾏淘汰.
volatile-lfu 4.0版本新增,当内存不⾜以容纳新写⼊数据时,在过期的 key 中,使⽤ LFU 算法进⾏删除 key.
allkeys-lfu 4.0版本新增,当内存不⾜以容纳新写⼊数据时,从所有 key 中使⽤ LFU 算法进⾏淘汰.
volatile-random 当内存不⾜以容纳新写⼊数据时,从设置了过期时间的 key 中,随机淘汰数据.
allkeys-random 当内存不⾜以容纳新写⼊数据时,从所有 key 中随机淘汰数据.
volatile-ttl 在设置了过期时间的 key 中,根据过期时间进⾏淘汰,越早过期的优先被淘汰.(相当于 FIFO, 只不过是局限于过期的 key)
key,很可能是没有保存设置时间的noeviction 默认策略,当内存不⾜以容纳新写⼊数据时,新写⼊操作会报错.
经过一段时间的“动态平衡”,redis 中的 key 就逐渐都成了热点数据了
#高频面试 缓存中的数据
redis 服务器首次接入之后,服务器里面是没有数据的
redis,如果没有查到,就再查一次 MySQL,查到了之后,会把数据也写到 redis 中MySQL,随着时间的推移,redis 上的数据越积累越多,MySQL 承担的压力就逐渐减小了缓存预热,就是用来解决上面问题的
把定期生成和实时生成结合一下。先通过离线的方式,通过一些统计的途径,先把热点数据找到一批,导入到 redis 中。此时导入的这批热点数据,就能帮 MySQL 承担很大的压力了。随着时间推移,逐渐就使用新的热点数据淘汰掉旧的数据
#高频面试
查询的某个 key,在 redis 中没有,MySQL 中也没有,这个 key 肯定也不会被更新到 redis 中
MySQL 带来很大的压力为何产生?
key 也被进行查询了 如何解决?
通过改进业务/加强监控报警等方式,都是亡羊补牢
相比之下更靠谱的方案:(降低问题的严重性**)
key 在 redis 和 MySQL 上都不存在,仍然写入 redis 中,value 设成一个非法值(比如"")redis / MySQL 之前,都先判定一下 key 是否在布隆过滤器上存在(把所有的 key 都插入到布隆过滤器中) hash+bitmap,以比较小的空间开销,比较快的时间速度,实现针对 key 是否存在的判定#高频面试
由于在短时间内,redis 上大规模的 key 失效,导致缓存命中率陡然下降,并且 MySQL 的压力迅速上升,甚至直接宕机
redis 直接挂了 redis 宕机/ redis 集群模式下,大量节点宕机redis 好着呢,但是可能之前短时间内设置了很多 key 给 redis,并且设置的过期时间是相同的 redis 里设置 key 作为缓存的时候,有的时候为了考虑缓存的时效性,就会设置过期时间(和 redis 内存淘汰机制,是配合使用的)如何解决?
redis 集群可用性的保证key 设置过期时间/过期时间的时候添加随机的因子(避免同一时刻过期)#高频面试
相当于缓存雪崩的特殊情况。针对热点 key,突然过期了,导致大量的请求直接访问到数据库上,甚至引起数据库宕机
key 访问频率高,影响更大如何解决?
key,并设置永不过期 redis 作为缓存redis 内存淘汰机制