当前位置: 首页>后端>正文

1000道互联网java面试题(六)Redis面试题

1. 什么是Redis?

Redis是完全开源的免费的。遵守BSD协议。一个高性能的key-value数据库。
Redis与其他kv缓存产品有以下三个特点:

  1. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用(两种持久化手段:aof和rdb。一个file追加,一个快照)
  2. Redis不仅仅支持简单的 key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  3. Redis支持数据的备份。即master-slave模式的数据备份。

Redis的优势:

  • 性能极高。Redis的读是11w/s。写是8.1w/s
  • 丰富的数据类型。 Redis支持二进制案例的Strings,Lists,Hashes,Sets以及ordered Sets数据类型操作
  • 原子。Redis的所有操作都是原子性的。意思是要么成功要么失败。当然了这里说的是单个操作是原子性的。而多个操作的话要用multi和exec指令包起来,手动去维护原子性。(单个操作的原子性和memcached类似。多个操作的手动维护原子性是memcached没有的功能)
  • 丰富的特性。 Redis还支持订阅和发布(subscribe/publish)。通知。key过期等特性。

Redis与其他key-value存储有什么不同?

  • Redis有着更为复杂的数据结构并且提供对他们的原子性操作、这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同事对程序员透明,无需进行额外的抽象。
  • Redis虽然是运行在内存中但是可以持久化到磁盘。所以在对不同数据集进行高速读写的时候需要权衡内存。因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是:相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单。这样redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的形式产生的(aof的全程 append only file)。因为他们并不需要进行随机访问。

2. Redis的数据类型?

Redis支持五种数据类型: String 字符串。 Hash 哈希。 List 列表。Set 集合。 zsetsorted set 有序集合。

我们实际项目中比较常用的是String。而且在Spring boot整合Redis的时候也提供两种bean:一种是RedisTemplate。还有一种就是专门字符串的StringRedisTemplate。
另外如果你对Redis用的比较熟练,应该还知道一些数据结构: HyperLogLog。Geo,pub/sub.bitmap等

  • HyperLogLog:这个其实是也是用来去重和统计的。基于HLL算法实现的。好像是分桶思想。这个数据结构只有三个api:
    增加集合(自动去重)。合并集合(自动去重)。查看当前集合中元素数(去重后结果)
    和set相比优点是当数据量很大,set的判断不方便,而HLL占用的内存是一定的。但是其有一些误差。
  • GEO:地理信息定位,存储经纬度,计算两地距离,范围计算等
  • bitmap:用于统计的,底层好像是二进制。用位操作来统计。比如签到。
    关于redis的数据结构我之前整理过并且还有一些api的调用方法和简单的理解。感兴趣的可以去看下我另一篇文章:https://www.jianshu.com/p/58a77ee1a77f
  • pub/sub:这个是不是数据结构,而是一个功能,发布订阅。

3. 使用Redis有哪些好处?

  1. 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1).
  2. 支持丰富的数据类型:String,List,Set,Zset,Hash.
  3. 支持事务。操作都是原子性的,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。
  4. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期自动删除。

4. Redis相比于Memcached有哪些优势?

  1. Memcached所有的值都是简单的字符串、Redis支持更为丰富 数据类型。
  2. Redis的速度比Memcached快(这个快慢其实要看数据结构,但是因为Redis是单核的。Memcached是多核的。所以数据量小的情况下redis优于Memcached)。
  3. Redis支持持久化数据。

4. Memcacahed与Redis的去被都有哪些?

(可能是因为我这两个东西是接连整理的,只能说两者的区别被翻来覆去的说。。)

  1. 存储方式。 Memcached是完全数据存在内存的,断电即失。而且数据不能超过内存大小。Redis有持久化功能。
  2. 数据类型中Redis支持多种数据类型。而Memcached只支持字符串。
  3. 使用的底层模型不同。他们之间的底层实现方式以及客户端之间的通讯的应用协议都不一样。
    Redis直接自己构建了vm机制。因为一般的系统。调用系统函数的话会浪费一定的时间去请求。

6. Redis是单进程单线程的?

对的。Redis是单进程单线程的。Redis利用队列技术将并发访问变为串行访问。消除了传统数据库串行控制的开销。

7. 一个字符串类型的值能存储最大容量是多少?

512M(这里可以回忆一下Memcached,单节点最大1MB,单个key最长250字节)

8. Redis的持久化机制是什么?各自的优缺点是什么?

Redis提供两种持久化机制。分别是RDB和AOF、
RDB持久化:这个是指数据集快照的方式半持久化模式。记录Redis数据库的所有当前键值对。在某个时间点将数据写入一个临时文件。持久化结束后,用这个临时文件替换上次持久化的文件。达到数据恢复
RDB的优点:

  1. 只有一个dump.rdb,方便持久化
  2. 容灾性好,一个文件可以保存到安全的磁盘
  3. 性能最大化。fork子进程来完成写操作。主进程可以继续处理命令。所以是IO最大化。使用单独的子进程进行持久化,主进程不会有任何IO操作,保证了Redis的高性能
  4. 相对于数据集比较大的时候,比AOF的启动效率更高

RDB的缺点:
数据安全性低。RDB是隔一段时间持久化一次。比如五分钟持久化一次。但是如果在4分50秒的时候redis宕机了,那么这4分50秒的数据没有持久化,也就是会丢失。
AOF持久化:全称是append - only - file。也就是所有的命令行记录以redis命令请求协议的格式完全持久化存储。保存为aof文件。
AOF的优点:

  1. 数据安全。aof持久化可以配置appendfsync属性。如果设置为always。则每一次命令操作都记录到aof文件中。
  2. 通过append模式写文件。及时中途服务器宕机。也可以通过redis-check-aof工具解决数据一致性问题。
  3. AOF机制的rewrite模式。文件过大时会对命令进行合并重写,可以删除其中的某些指令(比如误操作的flushall)

AOF的缺点:

  1. AOF文件比RDB文件大,而且恢复速度慢
  2. 数据集大的时候,AOF是不断追加,会越来越大、比RDB启动效率低。

当然了,在实际工作中,我们一般都是AOF和RDB配合使用的。

9. Redis常用性能问题和解决方案

  1. Master最好不要写内存快照。因为如果Master写内存快照,save命令调用rdbSave函数会阻塞主线程的工作。当快照比较大时对性能影响是非常大的。会间断性暂停服务。
  2. 如果数据比较重要。某个Slave开启AOF备份数据。策略可以设置为每秒同步一次。
  3. 为了主从复制的速度和连接的稳定性。Master和Slave最好在同一个局域网内。
  4. 尽量避免在压力很大的主库上增加从。
  5. 主从复制不要用图状结构而用单向链表结构更为稳定。即
    Master<-Slave1<-Slave2<-Slave3这种。这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他的保持不变。

10. Redis过期键的删除策略?

  1. 定时删除。在设置键的过期时间的同时,创建一个定时器timer。让定时器在键的过期时间来临时,立即执行对键的删除操作。
  2. 惰性删除。放任键过期不管,但是每次从键空间中获取键的时候都检查取得的键是否过期,如果过期的话,就删除该键。如果没过期则返回该键。
  3. 定期删除。每隔一段时间程序就对数据库进行一次检查,删除里面过期的键。至于删除多少过期键或者检查多少个数据库都由算法决定。

11. Redis的回收策略(淘汰策略)?

  • volatile-LRU:从已经设置过期时间的数据集中挑选最近最少使用的数据淘汰。
  • volatile-TTL:从已经设置过期时间的数据集中挑选将要过期的数据淘汰。
  • volatile-random:从已经设置过期时间的数据集中任意选择数据淘汰。
  • allkeys-LRU: 从所有数据集中挑选最近最少使用的数据淘汰
  • allkeys-random: 从所有数据集中任意选择数据淘汰
  • no-enviction:禁止删除数据

注意上面六种机制:volatile和allkeys是规定选择的key的范围。而TTL,LRU,RANDOM是三种不同的淘汰策略。最后一种是永不回收策略。
而使用策略的规则或者说应该怎么选?

  1. 如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则建议使用allkeys-lru
  2. 如果数据呈现平等分布,也就是所有数据访问频率差不多相同,则建议使用allkeys-random。

12. 为什么Redis需要把所有数据放到内存中?

RedisEileen达到最快的读写速度所以将数据都读到内存中。并通过异步的方式将数据写入磁盘。
所以redis同时具有快速和数据持久化的特征。如果不讲数据放在内存中,磁盘I/O速度会严重影响Redis性能。在内存越来越便宜的今天,redis将会越来越受欢迎。
如果设置了最大使用的内存,则数据已有记录数达到内存限制值后将不能继续插入新值了。

13. Redis的同步机制?

其实Redis可以使用主从同步,丛丛同步。
第一次同步时,主节点做一次bgsave,并且同时将后续修改操作记录到内存buffer。待完成后将rdb文件全量同步到复制节点,复制节点接收完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程(其实这里可以说一些别的:比如mysql的迁库:我们也可以采用类似的思路:首先当前数据库备份。然后拿着这个备份去新的数据库运行。如果数据量很大这个会时间比较长。但是等备份数据库结束以后可以暂停当前项目。然后再次备份原库。因为之前有备份,所以再次备份会在上一个的基础上操作,也就是这期间新插入的数据会同步,但是时间会短很多。然后同理把这个备份在新库中运行。然后项目指向新数据库。完成迁移)。

14. Pipeline有什么好处?为什么要用pipeline?

其可以将多次IO往返的时间缩减为一次。前提是pipeline执行的指令之间没有因果关系。

15. Redis集群的原理是什么?

这个答案说的问题有点大。我们知道Redis本身可以实现主从。但是单纯的主从其实是有问题的。主机可以写,从机不可以写只能读(默认的)。主机中的所有内容都会被同步到从机中。默认情况下,主机宕机了,从机也只能是从机。
这样其实整个redis都崩了。所以这样肯定是不对的。然后进化版就是哨兵模式。这也是很出名的所谓的redis的一主二从三哨兵的顺口溜。继续说这个题:
Redis Sentinal(哨兵)着眼于高可用。在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster(集群)着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

16. Redis集群方案什么情况下会导致整个集群不可用?

如果有A,B,C三个节点的集群。如果都没有从机,那么节点B宕机(redis集群的key的分配不是一致性hash算法,而是xxxx..反正是哈希槽的概念。Redis中有16384个哈希槽。计算方法大概是key通过CRC16校验后对16384取模判断是哪个槽)总而言之就是根据key算出落在哪个节点上,那么B宕机则落在B节点上的都不可用。
当然如果A,B,C有从节点,主宕机后从节点会上位。如果从节点也宕机则还是不可用。

17. Redis支持的java客户端都有什么?

Redisson,Jedis,Lettuce。
好像之前Jedis用的比较多。但是现在spring boot 默认使用的是Lettuce(spring boot 2版本。目前是2021/3.不知道以后会不会变)

18. Jedis与Redisson对比有什么优缺点?

Jedis其实就好像这个名字一样。java redis。是Redis的Java实现的客户端。其API提供了比较全面的Redis命令的支持。
Redisson实现了分布式和可扩展的Java数据结构。和Jedis相比功能比较简单。不支持字符串操作,不支持排序,事务,管道,分区等Redis特性。
Redisson的宗旨是促进使用者对Redis的关注分离。从而让使用者能够将精力集中的放在处理业务逻辑上。

19. Redis如何设置密码以及验证密码的?

设置密码有两种方式:

  • 控制台config set requirepass 123456
  • 配置文件中配置后启动


    1000道互联网java面试题(六)Redis面试题,第1张
    配置文件配置密码

    验证密码:auto 123456

20. 说说Redis哈希槽的概念?

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

21. Redis集群的主从复制模型是怎样的?

为了使在部分节点失败或者大部分节点无法通讯的情况下集群仍然可以使用,所以集群使用了主从复制模型。每个节点会有N-1个复制品。(这个因为redis集群的特性是每个节点负责一部分哈希槽,所以集群中一个节点宕机就会出问题。所以一定要有备用的,也就是主从复制。主宕机从可以上位)

22. Redis集群会有写操作丢失么?为什么?

因为Redis并不能保证数据的强一致性。这意味着在实际工作中集群在特定的条件下可能会丢失写操作。

23. Redis集群之间是如何复制的?

异步复制

24. Redis集群的最大节点个数的多少?

16384个(这个是因为哈希槽只有16384个。所以最大只能一个槽分给一个节点。不可能出现两个槽共用一个节点。所以最大节点数也是16384)

25. Redis集群如何选择数据库?

Redis集群目前无法做数据库选择,默认在0数据库。

26. 如何测试Redis的连通性?

使用ping命令

27. 怎么理解Redis事务?

事务是一个单独的隔离操作。事务中所有的命令都会被序列化。按顺序的执行。
事务在执行的过程中,不会被其它客户端发送过来的命令请求打断。
而且事务是一个原子操作,食物中的命令要么全部被执行,要么全部都不执行。

28. Redis事务相关的命令有哪些?

MULTI/EXEC 这两个其实是一对。
DISCARD 取消事务
WATCH 监视
整体而言我们可以理解为如果想要开始事务:MULTI
然后后面输入的命令都会被写入队列而不是一个命令一个命令的执行。
EXEC 命令 是可以开始执行队列中的命令了(这里要注意不执行和执行报错是两个概念)
DISCARD 是说不执行队列中的命令了。
WATCH 就比较简单了,用来监视一些key。在命令执行前如果这些key被别的线程改动过,则这整个事务就不生效了。

29. Redis key的过期时间和永久有效分别怎么设置?

EXPIRE是设置过期时间,不设置的话默认是永久有效的

30. Redis如何做内存优化?

尽可能的使用散列表。散列表使用的内存非常小,所以应该尽可能的将你的数据模型抽象到一个散列表里面。
比如有一个用户对象,不要每一个属性豆豆设置单独的key,而应该把这个用户的所有信息存储到一张散列表里。

31. Redis回收进程如何工作的?

一个客户端运行了新的命令,添加了新的数据。Redis检查内存使用情况,如果大于maxmemory的限制,则根据设定好的策略进行回收。一个新的命令被执行等。
大概意思就类似倒脾酒:发现要倒满了就喝一口,空出地方继续到。再发现要满了溢出了再喝一口。。。
总而言之不断的穿越内存限制的边界。然后到了边界不断的回收到边界以下。差不多就是这么个回收过程。

32. 都有哪些办法可以降低Redis的内存使用情况?

可以好好利用hash,list,sorted set,set等集合类型数据结构。因为通常很多小的key-value可以用更紧凑的方式存放到一起。
比如一个用户:有id,userName,age,三个字段。如果存储成三个key。并对应三个value。和存储成一个hash类型的key,zhegekey中有三个kv。那么是hash类型的更加节省内存。

33. Redis的内存用完了会发生什么?

如果达到设置的上限,Redis的写命令会返回错误信息。但是读命令还是可以正常返回的。
或者可以将Redis当缓存来使用配置淘汰机制。就是当Redis达到内存上限时会删除掉一些旧的内容。

34. 一个Redis实例最多能存放多少的keys?List,Set,Sorted Set他们最多能存放多少个元素?

据说理论上Redis可以处理2的32次方的keys。在实际中测试,每个实例至少可以存放2.5亿的keys。任何的list,set,zset也都是2的32次方。换句话说:Redis的存储极限是系统中的可用内存值。

35. MySQL中有2000w数据,redis中只有20w数据,如何保证redis中的数据都是热点数据?

其实这个完全可以用redis的淘汰策略保证。上面就提到过redis内存达到上限会删除旧数据。我们可以设置一些淘汰策略。这个和Memcached类似,而且上文提到过redis的淘汰策略。可以酌情选择。Redis提供的六种数据淘汰策略:

  • volatile-lru:从设置过期时间的数据集中挑选最近最少使用的淘汰。
  • volatile-ttl:从设置过期时间的数据集中挑选过期时间最近的淘汰。
  • volatile-random:从设置过期时间的数据集中随机挑选淘汰。
  • allkeys-lru:所有key中挑选最近最少使用的淘汰
  • allkeys-random:所有key中随机挑选淘汰
  • no-enviction:从不淘汰

36. Redis最适合的场景?

  1. 会话缓存(Session Cache)
    最常用的一种使用Redis的情景是会话缓存。用Redis缓存会话比其他存储的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人会不高兴的。但是如果只刚刚加购的商品丢失,很多人都不会很在意。

  2. 全页缓存(FPC)
    除了基本的会话token之外,Redis还提供很简单的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降。这是一个极大的改进。类似PHP的本地FPC。再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。

  3. 队列
    Redis在内存存储引擎领域的一大优点是提供list和set操作。这使得Redis可以作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言对list的push/pop操作。

  4. 排行榜/计数器
    Redis在内存中对数字进行递增/递减的操作实现非常好。集合和有序集合也使得我们在执行这些操作的时候变得非常简单。Redis只是正好提供了这两种数据结构,所以我们要从排序集合中获取到排名最靠前的10个用户。我们其实就已经实现了排行榜。

  5. 发布/订阅
    Redis的发布/订阅功能的使用场景也非常多。其可以在人们社交网络连接中使用。可以作为脚本触发器,还可以建立聊天系统。

37. 假如Redis中有一亿个key,其中有10w个key是某个固定的一直的前缀开头的,如何将他们全部找出来?

使用keys指令可以模糊搜索、当然了keys * 是查询全部的key。
追问:如果这个Redis正在给线上的业务提供服务,使用keys指令会有什么问题?
这个时候有一个很重要的问题:Redis是单线程的。keys指令会导致线程阻塞一段时间。尤其是上面说到数据量很大的时候,所以线上服务会停顿,直到指令执行完毕服务才能恢复。
这个时候可以使用scan指令。scan指令可以无阻塞的提取出指定模式的key列表。但是有一定的重复概率(可以客户端去重)。而且整体的花费时间会比keys指令长。

38. 如果有大量的key需要设置同一时间过期,一般需要注意什么?

如果大量的key过期时间设置的过于集中,到了那个过期的时间点redis可能会出现短暂的卡顿现象。(而且从使用的角度也容易造成缓存雪崩)。这里建议在过期时间上加一个随机值,使得过期时间分散一些。

39. 使用过Redis做异步队列么?怎么用的?

这里先简单复习一下redis中关于list 的操作:


1000道互联网java面试题(六)Redis面试题,第2张
redis中list的操作

一般使用list结构作为队列,rpush生产消息(从右插入),lpop消费消息(从左消费)。当lpop没有消息的时候,适当的sleep一会再重试!(其实我觉得这里只要保证先插先走就行了,所以从左插入从右消费也是ok 的)
追问:如果不使用sleep要怎么实现?
list还有个指令叫blpop/brpop。在没有消息的时候,会阻塞住直到消息到来。(b可以理解为blocking)
追问:能不能生产一次消费多次呢?
这个可以使用pub/sub订阅者模式,可以实现1:N的消息队列
追问:pub/sub有什么缺点?
在消费者下线的情况下,生产的消息会丢失。专业的消息队列RabbitMQ就不会。
追问:Redis如何实现延时队列?
这个可以使用sorted set来实现。因为sorted set插入的时候可以拿时间戳作为score。消息内容作为key。而消费者想要获取N秒前的消息时,用zrangebyscore命令获取N秒钱的数据。

40. Redis分布式锁是怎么回事?

先拿setnx来争抢suo.抢到之后用expire给锁加个过期时间防止忘了释放锁。
当然为了防止在setnx之后expire之前进程carch或者重启(这种情况锁会一直得不到释放),我们可以把setnx和expire合成一条指令来用。

至此,1000道互联网java面试题中Redis部分就结束了,其实我真正记录一遍后会发现这些问题很杂,而且回答几乎都很浅显。虽然之前我自认对redis有一定的了解,并且前不久才系统的整理过redis知识点。但是看这些题目有的还需要额外去百度一些附加知识。我只能说这些面试题适合作为一个大纲来记录。单绝对不止是背下来上面这些文字就万事大吉了!因为如果是死记硬背上面的文字的话会非常经不起考验!稍微细问就容易卡住。这里还是建议每一道题往深了看,或者多看看基础的东西之类的。
如果本篇笔记稍微帮到了你请记得点个喜欢点个关注。也祝大家工作顺顺利利!最近看群里聊天,一个人说学的越多越发现自己浅薄,其实是很有道理的话。但是哪怕如此多学,多看,我也相信依旧是有用的。无论是不是在面试的朋友们,要相信努力不会骗人!


https://www.xamrdz.com/backend/3cn1936903.html

相关文章: