redis面试题整理

文章目录

    • 1、什么是Redis?简述它的优缺点?
    • 2为什么使用redis
      • 1)速度快
      • 2)支持多种数据结构
      • 3)功能丰富
      • 4)服务器简单
      • 5)客户端语言多
      • 6)支持持久化
      • 7)主从复制,空可用/分布式
    • 3、redis的数据类型,以及每种数据类型的使用场景
    • 4、redis相比memcached有哪些优势?
    • 5、单线程的redis为什么这么快?
    • 6、redis如何确保里面的数据都是热点数据
    • 7、**使用过Redis分布式锁么,它是什么回事?**
    • 8、如何应对redis的击穿问题?
    • 9、redis的缓存雪崩问题
    • 10、redis集群架构
      • 1)Replication+Sentinel
      • 2)Redis Cluster

1、什么是Redis?简述它的优缺点?

  • Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。
  • 因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能。
  • 比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。
  • 另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。

2为什么使用redis

1)速度快

  • 速度快,完全基于内存,使用C语言实现,网络层使用epoll解决高并发问题,单线程模型避免了不必要的上下文切换及竞争条件;
  • 注意:单线程仅仅是说在网络请求这一模块上用一个线程处理客户端的请求,像持久化它就会重开一个线程/进程去进行处理

2)支持多种数据结构

  • 当然常用的主要是 String、Hash、List、Set、 SortSet 这5种类型,他们都是基于键值的方式组织数据。每一种数据类型提供了非常丰富的操作命令,可以满足绝大部分需求,
  • Redis的代码开源在GitHub,代码非常简单优雅,任何人都能够吃透它的源码;它的编译安装也是非常的简单,没有任何的系统依赖;有非常活跃的社区,各种客户端的语言支持也是非常完善。另外它还支持事务(没用过)、持久化、主从复制让高可用、分布式成为可能。

3)功能丰富

  • 可以设置键过期
  • 基于发布订阅可实现简单的消息队列
  • 通过lua创建新命令,具有原子性
  • pipeline功能,减少网络消耗

4)服务器简单

  • 代码优雅,下功夫都能吃透
  • 采用单线程模型,减少竞争,规模并发问题
  • 不依赖操作系统(多路复用redis自己实现了)

5)客户端语言多

  • 支持java/php等

6)支持持久化

  • RDB

  • RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘。

  • RDB是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:

    保存增删,不保存查询

     save 900 1        900内1次操作
     save 300 10
     save 60 10000
    
  • AOF

  • AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。

7)主从复制,空可用/分布式

3、redis的数据类型,以及每种数据类型的使用场景

  • 回答:一共五种
  • (一)String
  • 这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。
  • (二)hash
  • 这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。
  • (三)list
  • 使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。
  • (四)set
  • 因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。
  • 另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能
  • (五)sorted set
    sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。另外,参照另一篇《分布式之延时任务方案解析》,该文指出了sorted set可以用来做延时任务。最后一个应用就是可以做范围查找

4、redis相比memcached有哪些优势?

  • (1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
  • (2) redis的速度比memcached快很多
  • (3) redis可以持久化其数据

5、单线程的redis为什么这么快?

  • 1)完全基于内存,绝大不部分请求是纯粹基于内存,非常快速。数据存在内存中,类似HashMap,HashMap的优势就是查找和查找的时间复杂度都是O(1)
  • 2)数据结构简单,对数据操作也简单,redis中的数据结构是专门进行设计的
  • 3)采用单线程,避免不必要的上下文切化和竞争条件,也不存在多线程或多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
  • 多路I/O复用模型
  • 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
  • 这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

6、redis如何确保里面的数据都是热点数据

  • 1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。应该没人用吧。
  • 2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。
  • 3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。
  • 4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。不推荐
  • 5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。依然不推荐
  • 6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。不推荐
  • ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。

7、使用过Redis分布式锁么,它是什么回事?

  • 先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
  • 这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样
  • 然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容,心里开始默念:摁,这小子还不错。

8、如何应对redis的击穿问题?

  • 缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
  • 解决方案:
  • (一)利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试
  • (二)采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
  • (三)提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。

9、redis的缓存雪崩问题

  • 缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
  • 解决方案:
  • (一)给缓存的失效时间,加上一个随机值,避免集体失效。
  • (二)使用互斥锁,但是该方案吞吐量明显下降了。
  • (三)双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点
    • I 从缓存A读数据库,有则直接返回
    • II A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
    • III 更新线程同时更新缓存A和缓存B。

10、redis集群架构

1)Replication+Sentinel

img

  • 这里Sentinel的作用有三个:

  • 监控:Sentinel 会不断的检查主服务器和从服务器是否正常运行。

  • 通知:当被监控的某个redis服务器出现问题,Sentinel通过API脚本向管理员或者其他的应用程序发送通知。

  • 自动故障转移:当主节点不能正常工作时,Sentinel会开始一次自动的故障转移操作,它会将与失效主节点是主从关系 的其中一个从节点升级为新的主节点,并且将其他的从节点指向新的主节点。

  • 工作原理就是,当Master宕机的时候,Sentinel会选举出新的Master,并根据Sentinel中client-reconfig-script脚本配置的内容,去动态修改VIP(虚拟IP),将VIP(虚拟IP)指向新的Master。我们的客户端就连向指定的VIP即可!

  • 缺陷:

  • (1)主从切换的过程中会丢数据

  • (2)Redis只能单点写,不能水平扩容

2)Redis Cluster

img

  • 工作原理如下

  • 客户端与Redis节点直连,不需要中间Proxy层,直接连接任意一个Master节点

  • Redis集群有16384个哈希槽

  • 公式HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作

  • 具有如下优点:

  • (1)无需Sentinel哨兵监控,如果Master挂了,Redis Cluster内部自动将Slave切换Master

  • (2)可以进行水平扩容

  • (3)支持自动化迁移,当出现某个Slave宕机了,那么就只有Master了,这时候的高可用性就无法很好的保证了,万一master也宕机了,咋办呢? 针对这种情况,如果说其他Master有多余的Slave ,集群自动把多余的Slave迁移到没有Slave的Master 中。

  • 缺点:
    (1)批量操作是个坑
    (2)资源隔离性较差,容易出现相互影响的情况。

你可能感兴趣的:(面试题整理,大数据,面试,redis,Redis的雪崩问题,redis的击穿问题)