一篇总结Redis面试题知识点

为什么要使用Redis

        使用Redis主要是因为Redis的三大特性,高可靠高并发高性能。在请求访问数据时,如果直接从数据库中获取数据,它的并发量可能只有1000次/秒,这已经算是很不错的表现。如果在程序启动的时候就将数据放到Redis中,数据访问时如果直接从缓存中读取,他的性能以及并发量会明显提高很多,再加上Redis的主从集群部署和哨兵机制也保证了Redis的可靠性。(延伸主从集群和哨兵的机制)

Redis和数据库双写的时候如何保持数据一致

  1.先更新DB再更新缓存或者先更新缓存再更新DB(不可行)

  先更新缓存再更新DB或者先更新DB再更新缓存都会因为延迟的原因导致产生一些脏数据或者导致缓存和数据库的数据不一致。如果先更新DB再更新缓存,在更新期间,如果前面有请求打到了缓存上,这时候就会返回旧的数据,如果先更新缓存再更新DB,缓存更新成功了但是DB更新失败了,请求发到缓存的时候返回的新数据,导致很难察觉到DB没有更新成功导致数据不一致

  2.先删除缓存,再更新DB,

  这个策略会出现并发的场景,当两个请求同时来的时候,一个请求去删除缓存然去数据库更新,这时候又来了一个请求打到了缓存上,发现没有缓存就去DB更新,DB还没有更新完成,这时候第二个请求就去数据库把旧的数据更新到了缓存里,导致缓存里面还是旧的数据。

  解决方法(延迟双删)

  先删除缓存然后再去更新DB,更新完DB之后延迟一下,具体的延迟要看情况来决定,延迟一段时间后再删除缓存,如果删除失败,可以通过消息队列机制进行重试。不能保证百分百的没有脏数据

  归纳总结

  一般采用删除缓存类的操作,因为会避免很多问题

  因为缓存删除或者缓存更新的操作会比在DB中的操作要快一些,所以一般会采用先更新数据库再去删除缓存,这样的话只有查询操作比删除慢的时候才会出现数据不一致的问题,但是这种情况相对是比较少的,再结合延迟双删的策略,可以很大程度上避免数据的不一致。

为什么要把数据存到内存中

        首先如果将数据存储在磁盘上,系统首先需要从磁盘中读取数据,然后加载到内存中,再从内存中调用。这种方式的查询速度相比直接将数据存储在内存中要慢得多,虽然并没有差太多但是当数据量大或者并发量一多的时候还是会影响性能的。

最终内存数据持久化不是还要存储到磁盘不会更耗费时间吗

        Redis在查询内存中的数据的时候他是以一个单线程的形式去查询的,但是在对数据进行持久化的时候会采用异步的方式去对数据进行持久化,所以实际上对于我们这个内存没有影响。

Redis的过期淘汰策略

        Redis中的数据在设置了一个过期时间之后并不一定会直接被刷掉。分为三种策略

  惰性过期

        其中有惰性过期,就是在当过期时间到的时候并不一定会直接把数据删除掉,会等到一个请求访问数据的时候判断这个key有没有到过期时间,如果没有过期的话直接返回不管,如果过期的话会进入下一步判断他是否是master节点,只有在master节点的时候他才会去分出两个线程,一个同步的一个异步的去做删除的操作。

  定时过期

          定时过期的话会有一个后台的线程去跑,他会去监控数据有没有设置过期时间,如果有过期时间的话,涉及的一个Hash桶的概念,一次去拿一定数量的key,然后把其中过期的数据给删除掉。删除完之后不会直接结束,会判断一下如有没有拿到过期的数据或者拿到的过期的数据是否超过了百分之十,就是说没拿到或者拿到的过期的数据很多,他都会去立马再跑一遍,再去拿一遍数据,然后删除过期的,最多循环16次且时间大于 25ms。

  内存淘汰策略

        当Redis的使用内存达到上限的时候 ,会根据配置的淘汰策略来删除部分的key,具体如下。

Redis的内存淘汰策略

内存淘汰策略一共八种

1.noevication默认,不淘汰,对于一些没用的数据也不会去管他,一直堆着等到内存满的时候会报错

2.ttl 根据过期的时间,到过期时间之后就会把过期的数据给删除掉

3.LRU,RANDOM,LFU其中每种都分为allkey和volatile

        常用的一般就是LRU和LFU,一般的淘汰策略FIFO就是一个FIFO链表,在存储到达限制的时候,新插入的数据会把最老的数据给挤掉,Redis是没有这种策略的。

        LRU就是在FIFO的基础上,如果在此期间,有数据被调用,就会把这个数据挪到头部去,避免热点数据被刷掉。但是新插入的数据可能还没来得及被访问就被淘汰了,因此需要进一步改进。比如新插入的数据不会给他放到头部,而是给他放到后端偏尾部的位置,主要是为了避免他新增还没被访问就被刷掉,然后被调用的数据也不会直接给他放到头部,会根据他的这个调用次数给他进行排序,调用次数越多的就给他放的越靠前。

        LFU既最不经常使用,它通过记录每个缓存项的使用频率来决定哪些数据应被淘汰。当缓存空间不足时,LFU 会优先移除那些使用频率最低的数据。相比于其他策略,LFU 更适合用于数据访问频率有明显差异的场景,能更有效地保留高频访问的数据,从而提高缓存命中率。

Redis的基本类型和应用场景

Redis一共有五大基本类型,分别是String,List,Hash,Set,Z Set

List就是做列表,一般用来做一些文章列表消息队列之类的

Set是一个无序的集合,里面是可以有交集并集差集的应用的,可以做一些标签,抽奖之类的场景

Zset是有序的集合,一般适用于一些需要排序的比如排行榜,时间播放量之类的场景

String就是字符串类型,一般用来存缓存,分布式Id,还有分布式锁

Hash一般用来存储一些对象类数据,统计类的数据,或者购物车,也同样可以用来存分布式锁

Redis为什么快

1.纯内存访问,不涉及到磁盘的交互

2.Redis是单线程的,避免了上下文的切换

3.采用了合理的数据结构,合理的分配内存的空间

4.多路复用epo||模型

5.渐进式ReHash,缓存时间戳等设计

Redis持久化的方式有哪些

        Redis的持久化分两种一种是AOF(追加命令)一种是RDB(内存快照)

        AOF会先去看有没有配置appendonly和appendfilename,如果有的话就会开启一个AOF,AOF默认有三种策略。

        一种always,就是在每个命令执行完毕之后就会立马同步日志到磁盘。

        everysec,在执行完一个命令之后先把日志写到缓存区,然后每隔一秒再将缓存区的内容写到磁盘。

        还有一个就是no,就是他默认的策略,默认的策略就是每个命令执行完也将数据放到缓存区,由操作系统决定什么时候写入磁盘,通常同步周期不超过30秒。

        如果没有去配置AOF他就会默认开启RDB,是基于快照的,但是他有可能会造成数据丢失,可能会有一些影响。

        RDB备份分为自动触发和手动触发。自动触发可以通过配置参数save seconds updates,即在指定时间内修改一定次数后自动触发快照。另外,在系统关闭(shutdown)时也会触发快照。主动触发的话用save命令,但是会阻塞主线程,所以不建议去使用 ,可以用bgsave,可以在后台开启一个线程去将快照写入磁盘。

RDB持久化有哪些优缺点

        优点的话Redis加载RDB恢复数据的速度远超于AOF的方式,适用于备份,全量复制的场景。缺点的话,RDB没法做到实时的持久化,因为每次bgsave运行都要创建一个子进程,属于重量级操作,频繁执行的话成本太高了。而且RDB使用特定的二进制格式保存,Redis版本演化的时候有多个RDB版本,老版本的Redis的话可能会无法兼容新版本的RDB格式,数据恢复就会遇到麻烦。

怎么提高缓存的命中率

        首先的可以采取缓存预热的方式,在系统启动的时候提前将一些热点数据缓存到内存中。这样的话会避免一些初始的数据一开始没有被命中缓存导致的数据库压力过大。

        其次要考虑项目的架构设计合理,如果架构合理的话会提高很多命中率。

什么是缓存击穿?要如何避免?

        缓存的话就相当于给数据库的资源前面放一个盾牌,本身数据库是顶不住特别高的并发量或者特别大量的数据操作,所以就需要缓存来挡在前面阻挡请求,让请求从缓存中获取数据,如果有大量的恶意的请求打到缓存上,导致缓存顶不住,就会突然有大量的请求打到DB上,可能会导致DB顶不住甚至直接挂掉,就是缓存击穿。

        一般来说的这种恶意的请求都要想办法把他解决掉,要避免缓存被击穿的话,在面对恶意的请求的时候,可以直接在缓存里存入一个空对象,请求来的时候直接把这个空对象给他返回去,就不会造成缓存的压力。但是如果恶意的请求每次查询的对象都不一样的话,这种方法就会导致缓存中有很多多余的空对象数据,带来一些额外的内存消耗。

        还有一种布隆过滤器,对于发来的请求先进去看一下,如果有这个数据的话就去查询,没有数据的话直接把请求拒绝掉,这样的话他的内存占用会比较小,也没有很多多余的key,但是同时也会带来一些缺点比如实现起来比较复杂,而且可能存在对请求的误判。

什么是缓存雪崩?要如何处理 ?

        缓存雪崩是指大量缓存数据在同一时间失效,导致大量请求涌向数据库,造成数据库负载过高或直接挂掉。一般会引起非常严重的性能问题。

        处理的方法呢一般有

        分散缓存失效时间,就是在设置缓存的过期时间的时候,给每一个缓存添加一个随机的偏移量,比如在设置一个key的过期时间的时候在过期时间的基础上加上一个随机的值(随机加上一定时间),避免大量的缓存在同一时间失效。

        分布式缓存部署,通过分布式部署缓存服务器,比如Redis的主从结构或者分片部署,减轻单个节点的缓存节点的负载压力,某个节点失效的时候其他节点也可以继续提供服务,减轻对数据库的冲击。

        缓存预热,在程序启动的时候,将一些热点数据加载到缓存里面,避免系统在负载高峰期的时候因为缓存未命中导致DB的压力过大。

        还有很多别的策略可以去了解。

什么是bigKey?有什么影响

        bigKey的话一般用来指一个key对应的value值过大,这时候就会把这个称为bigKey。bigkey在缓存系统里会带来很多潜在的危害。

        首先会造成堵塞,bigkey的读取和写入操作会占用大量的资源,可能会影响到其他正常大小的请求,导致其他请求无法正常处理 ,整体响应时间变慢。

        其次会造成内存的分布不均匀,在缓存集群中,如果很多bigkey都在一个分片上,会导致某个分片的压力非常大,就导致内存的空间分布不均匀。

        在查询bigkey的时候也可能会导致cpu飙升等等还有不少危害

        要避免bigkey带来的危害的话 ,可以在设计key的结构的时候就把他设计的优雅一点,其次如果必须要写入大量的value的值的话,可以对他根据一些业务场景进行一下拆分,比如根据服务,模块或者功能进行拆分,将一个key拆分成多个,这样的话他承受的压力要相对的小很多。

什么情况下可能导致Redis阻塞

        首先会造成redis阻塞的情况有很多,其中一种就是bigkey,bigkey的查询,删除操作都会导致Redis的阻塞,就算删除的时候,操作系统在删除一块空间的时候,会先将这块空间插入到一个空闲的内存块链表里面,这样的话也会在删除的时候造成一些影响、

        其实错误的客户端命令,比如keys*,save也会导致Redis的阻塞,由于Redis是单线程的,在执行这些操作大量数据的命令的时候会导致正常的请求在后面排队,导致Redis阻塞。

        在AOF的日志同步的时候,如果配置的同步策略是always的时候,每一个命令都会去同步日志,大量的同步写操作也会导致阻塞。在清空库或者一些其他清空的时候也可能有这种问题。

什么是热点数据什么是冷数据

        热点数据就是指在在系统中访问频率比较高,读写操作较为密集的数据,热点数据对系统的性能有很大的影响,因为会别频繁的使用,通常需要放在缓存中,确保被快速的访问。一般比如电商平台上的商品信息,如果都往DB中去查询的话很影响性能和数据库的压力。

        冷数据就是不经常被访问,但是又不可缺少的数据,在某些特点的场景下需要被访问,没准什么时候去访问一次。

Redis如何解决key冲突

        key冲突的话,比如在多个系统里面,如果对于某一个key值都有一个赋值的操作,在执行查询的时候,可能会导致返回的值和预期的不同,这个是key冲突,如何解决的话。

        首先可以在设计key的名字的时候对名字进行统一的规范,比如设计的时候采用业务模块+系统+关键字的形式,这样的话能有效的减少key冲突的可能性

        其次可以采用分布式锁+时间戳的方式,比如A在执行的时候把她执行的时间戳给加到后面,B在执行的时候也同样,这样的话执行的时候可以比较一下时间戳,如果跟预期的不一样的话我就可以不认可这个结果。

Redis集群什么情况下会导致整个集群不可用

1.当访问master和slave节点都挂掉的时候

2.当集群主库半数都挂掉的时候,一般来说当主库挂掉的时候会进行投票来选举新的主,投票选主的话需要有 一半以上的票才能选举成功新的主库,所以如果当半数都挂掉的时候 ,整个集群也会瘫痪掉。

3.大量的异步请求或者节点不均匀。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值