引言
在这篇文章讲解一下 redis 中 其他的知识。
什么是缓存穿透?怎么解决?
缓存穿透的就是指请求一个不存在的数据,缓存层和数据库层都没有这个数据,这种请求会穿透缓存直接到数据库中进行查询。可能会耗尽数据库连接资源造成性能问题。
常用的解决方法有
对请求增加校验机制
缓存空值 或者 特殊值
使用布隆过滤器
什么是布隆过滤器?
布隆过滤器(Bloom Filter)是一种数据结构,用于快速判断一个元素是否属于一个集合中。它基于哈希函数实现,可以高效地判断一个元素是否在集合中,但不能精确地确定一个元素在集合中的位置。
布隆过滤器是适合处理大规模数据集,比如:海量数据去重、垃圾邮件过滤、避免缓存穿透等。
什么是缓存击穿?
缓存击穿的意思是对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大量并发的请求可能会瞬间把 DB 压垮。
解决方案有两种方式:
可以使用互斥锁:当缓存失效时,不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db的操作并回设缓存,否则重试get缓存的方法。
对于热点的key设置成永不过期。
缓存预热,分成提前预热和定时预热。
降级处理。
什么是缓存雪崩 ? 怎么解决 ?
缓存雪崩是缓存中同一类型大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。
解决方案:
使用锁进行控制
对同一类型信息的key设置不同的过期时间
缓存预热
redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)
1.对数据实时性有一定要求
对数据实时性有一定要求即数据库数据更新需要近实时查询到最新的数据,针对这种情况可采用延迟双删、Canal+MQ异步同步的方式。
2、对数据实时性要求不高
使用定时任务的方式定时更新缓存。
什么是延迟双删?
线程1先删除缓存,再写入主数据库,延迟一定时间再删除缓存。 确保新的读强求会重新从数据库中读取对新的数据。
redis做为缓存,数据的持久化是怎么做的?
在Redis中提供了两种数据持久化的方式:1、RDB 2、AOF
RDB是一个快照文件,它是把redis内存存储的数据写到磁盘上,当redis实例宕机恢复数据的时候,方便从RDB的快照文件中恢复数据。
AOF的含义是追加文件,当redis操作写命令的时候,都会存储这个文件中,当redis实例宕机恢复数据的时候,会从这个文件中再次执行一遍命令来恢复数据。
这两种方式,哪种恢复的比较快呢?
RDB因为是二进制文件,在保存的时候体积也是比较小的,它恢复的比较快,但是它有可能会丢数据,我们通常在项目中也会使用AOF来恢复数据,虽然AOF恢复的速度慢一些,但是它丢数据的风险要小很多,在AOF文件中可以设置刷盘策略。
Redis的数据过期策略有哪些 ?
第一种是惰性删除,在设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。
第二种是 定期删除,就是说每隔一段时间,我们就对一些key进行检查,删除里面过期的key。
定期清理的两种模式:
SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf 的 hz 选项来调整这个次数
FAST模式执行频率不固定,每次事件循环会尝试执行,但两次间隔不低于2ms,每次耗时不超过1ms
Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用。
Redis的数据淘汰策略有哪些 ?
默认是noeviction,不删除任何数据,内部不足直接报错。
是可以在redis的配置文件中进行设置的,里面有两个非常重要的概念,一个是LRU,另外一个是LFU。
LRU的意思就是最少最近使用,用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
LFU的意思是最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。
我实习时在项目设置的allkeys-lru,挑选最近最少使用的数据淘汰,把一些经常访问的key留在redis中。
Redis的内存用完了会发生什么?
这个要看redis的数据淘汰策略是什么,如果是默认的配置,redis内存用完以后则直接报错。我们当时设置的 allkeys-lru 策略。把最近最常访问的数据留在缓存中。
Redis分布式锁如何实现 ?
在redis中提供了一个命令setnx(SET if not exists)
由于redis的单线程的,用了命令之后,只能有一个客户端对某一个key设置值,在没有过期或删除key的时候是其他客户端是不能设置这个key的
Redis是单线程的,但是为什么还那么快?
1、完全基于内存的,C语言编写
2、采用单线程,避免不必要的上下文切换可竞争条件
3、使用多路I/O复用模型,非阻塞IO