前提概要

伴随着缓存处于高并发下的高性能和高可用的特性,在互联网或者传统软件行业下的地位也与日俱增,无论在平时的开发过程中或者在面试中都是出场率非常高的存在,所以本人写了一些关于从基础到高级的阶段性的面试题集,希望可以对一些小伙伴们有帮助,祝愿天下的小伙伴都可以拥有更加健全的知识体系以及更理想的生活,加油奋斗!

注意:为了防止过大篇幅造成小伙伴们的望而却步,所以小编进行题目的板块拆分,希望小伙伴们可以遵循小编的进度,适度的选择板块以及速度去学习,主要的是基础,不要小看任何的知识点,题目答案主要针对于面试口述,并不深究其底层运作h和具体细节,请见谅!


题目开淦

问题1:Redis是做什么用的?简述它的优缺点?(基础题,希望大家理解本质)

  • Redis 的全称是:Remote Dictionary Server,本质上是一个 Key-Value 类型的内存数据库,很像Java中的HashMap,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据 flush 到硬盘上进行保存。
  • 优点:因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的Key-Value DB
    Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构此外单个value的最大限制是512M不像memcached只能保存 1MB 的数据,因此 Redis可以用来实现很多有用的功能。
  • 缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis适合的场景主要局限在较小数据量的高性能操作和运算上

问题2:Redis 与 memcached 相比有哪些优势?(主要是Redis的优势)

  • 1.memcached所有的值均是简单的字符串,redis支持更为丰富的数据类型
  • 2.redis的速度比memcached快很多,redis的速度比memcached快很多(有争议,考虑到Memache多线程可以充分利用多核,在考虑6.0后的Redis支持多线程,所以存在版本的概念)。
  • 3.redis可以持久化其数据redis可以持久化其数据,数据的可靠性和一致性更高
  • 4.redis单个key存储的value可以达到1G而Memcache只有1M存储大小。
  • 5.redis对集群情况下的高可用支持的方案很多,所以集群情况下高可用更好。
  • 6.针对于第一条的补充,包含功能场景的丰富化,比如,消息队列、原子操作处
    理(Lua脚本以及自增自减的操作)、事务机制和延时队列机制等等功能
  • 7.采用的网络模型非常好(epoll机制)摈弃给纯内存考虑,并且采用了内部共享内存池机制(可以复用内存,惰性分配),采用单线程机制减少用户态和内核态的切换以及线程之间上下文的切换。

问题3:Redis支持哪几种常用数据类型

  • String(字符串)
  • List(列表)
  • Set(集合)
  • Sorted Set(有序集合)
  • hash(哈希表)

问题4:Redis 有哪几种数据淘汰策略?

  • noeviction默认策略,不淘汰,如果内存已满,添加数据是报错:返回当内存限制无法分配的错误,此外并且客户端可能尝试执行让更多内存被使用的命令
  • allkeys-lru回收最不经常使用的键(LRU),使得新添加的数据有空间存放
  • volatile-lru回收最不经常使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放
  • allkeys-random:回收随机的键使得新添加的数据有空间存放
  • volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键
  • volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间
    存放。

问题5:Redis 集群方案应该怎么做?都有哪些方案?

  • codis目前用的最多的集群方案,属于一个基于服务端操作的负载均衡机制属于代理后端服务实例的机制,可以支持1024的集群节点,但它支持在节点数量改变情况下,旧节点数据可恢复到新hash(CRC32算法)节点。
  • twemproxy ,基本和codis一致的效果,但是对于节点变化的情况处理不是很好,所以性能方面来讲依赖于twemproxy的节点的吞吐能力。
  • redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性hash,而是 hash槽(slot)的概念,以及自身支持节点设置从节点,并且节点之间都有引用链接关系帮助定位hash槽的数据,支持节点达到16384个节点。

问题6:Redis Cluster的hash槽的概念?

Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有16384 个哈希槽,每个 key 通 过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分区间的hash槽位


问题7:怎么理解Redis事务?

事务是一个单独的隔离原子性操作:事务中的所有命令都会序列化、按顺序地提交到执行队列中去执行,事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。指令:MULTI(开启事务)、EXEC(执行事务)、DISCARD(清除队列)、WATCH(监听key)、UNWATCH(取消监听)


问题8:(Redis)什么是缓存穿透?如何避免?

缓存穿透:一般的缓存系统,都是按照 key 去缓存查询,如果不存在对应的 value就应该去后端系统查找(比如 DB)一些恶意的请求会故意查询不存在的 key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透

如何避免?

  • 1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,以及如果该key对应的数据 insert 了之后清理Null缓存(防止读取空的数据而不是insert插入的数据)
  • 2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap (布隆过滤器)中,查询时通过该 bitmap(布隆过滤器) 过滤。

问题9:(Redis)什么是缓存雪崩?如何避免?

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃

如何避免?

  • 1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存
  • 2:做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期,牺牲一致性,提高可用性
  • 3:不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀,不要集中同一个点进行失效,作为一个动态分布设计的过期时间。
  • 4:设置热点数据永远不过期(不推荐哦)

问题10:(Redis)什么是缓存击穿?如何避免?

高并发的系统中,大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去。这种现象我们称为缓存击穿

如何避免?

  • 1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存
  • 2:做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期,牺牲一致性,提高可用性
  • 3:设置热点数据永远不过期(不推荐哦)