Redis--高频面试题

183 阅读8分钟

1. SQL | NoSQL 之间的区别?

  1. 干货 | SQL 与 NoSQL还在傻傻分不清?
  2. MongoDB与 MySQL:什么时候使用?mongodb的数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,这样会提高查询效率,所以mongodb本身很吃内存
  3. redis和memcached的区别和使用场景。mc的核心职能是key-value键值对数据管理,value最大为1M,value只支持String类型,不支持复杂的数据结构(set,list,zset)。mc数据完全存储在内存中,不支持持久化到磁盘中

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

面试官:你确定 Redis 是单线程的进程吗?

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

  1. 主要考察字符串底层实现:SDS 结构,其中有一个字段记录了字符串的长度,int类型,因此理论上支持2^32-1字节,即4GB,但在Redis中,字符串类型的值除了存储数据外,还需要存储一些元数据信息(例如长度等),所以实际上字符串类型的值能存储的最大容量是512MB
  2. 简单动态字符串(SDS)

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

Redis--简述RDB与AOF持久化

5. Redis 常见性能问题和解决方案?

内存压力、热key、网络带宽不够等,解决方案:redis集群、持久化 | LRU 淘汰释放内存、主从复制读写分离。

6. Redis 过期键删除策略与内存淘汰策略?

Redis 过期删除策略和内存淘汰策略有什么区别?

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

为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以Redis具有快速和数据持久化的特性。如果不将数据放到内存中,磁盘的I/O速度会严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。

8. Redis 的主从同步机制?

  1. 一文让你明白Redis主从同步
  2. Redis进阶 - 高可用:哨兵机制(Redis Sentinel)详解

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

redis 中 pipeline 有什么好处,为什么要用 pipeline?

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

Redis集群原理详解

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

答案见上一问题。

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

  1. Redis支持的 java 客户端都有哪些?
  2. Jedis vs Redisson,到底怎么选?

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

答案见第10问。

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

会,主从同步过程中如果发生故障,就可能产生数据丢失,详见:

  1. Redis 集群会有写操作丢失吗?为什么?
  2. redis中集群一致性问题

15. Redis 集群最大节点个数是多少?

  1. 最大主节点数 16384 个。因为有16384个哈希槽
  2. redis作者不建议redis cluster节点数量超过1000个,集群节点越多,心跳包的消息体内携带的数据越多。 如果节点过1000个,会导致网络拥堵
  3. 一般Redis集群至少需要3个master节点,1个master至少对应2个slave

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

通常是用select命令的,但是在集群模式下是不起作用的,集群是不支持多数据库的,只能使用数据库0。至于为什么会有多个数据库可参考下文:为什么redis有多个数据库?

17. 怎么理解Redis事务?

  1. Redis系列(九):Redis的事务机制
  2. 没有一致性、原子性,只有隔离性(事务一旦开始运行,则不再运行其他客户端请求的命令),由于Redis支持数据持久化,因此也可以理解为拥有持久性吧
  3. Redis 中的原子操作:事务与 Lua 脚本

18. Redis中哪种数据结构基于跳表实现?跳表又是什么?

有序集合,关于跳表的实现:漫画:什么是跳表?

19. Redis中的rehash过程?什么是渐进式rehash?

Redis rehash

20. 如何使用Redis实现分布式锁?实现过程中需要注意什么事情,以及锁失效场景都有哪些?

  1. 七种方案!探讨Redis分布式锁的正确使用姿势
    • 设计分布式锁时,需要注意保证锁应该有持有人标记(可以设置到value上),否则可能被别的线程释放
    • 需要保证锁有过期时间,否则可能在一些异常情况下,锁永远不会被释放,设置锁过期时间时,要保证其原子性,可以使用SET的扩展命令以及lua脚本(对于锁可能过期的问题,可以将锁的过期时间设置的长一点,或者采用Redisson的成熟方案(看门狗)去解决这个问题)
    • 除了使用Redis的Set命令可以实现分布式锁,像MySQL的唯一索引,基于CAS+缓存的思想,都可以设计一个分布式锁
  2. Redis分布式锁失效场景分析
    • 锁失效场景:锁超时时间过短,事务未执行完,就释放了锁;Redis主从切换,锁未同步slave,造成锁失效。

21. 如何设计一个秒杀系统?

  1. 基本的流程:下订单、扣库存、支付
  2. 最基本的架构:服务端 + DB(MySQL),MySQL单机TPS也就1w
  3. 高并发情况下必须保证不能超卖,考虑引入分布式锁(悲观锁),保证并发情况下商品数是正确的
  4. 考虑高性能:悲观锁优化为乐观锁(基于MySQL实现),还是直接操作DB,性能很差。考虑引入Redis,Redis单机支撑QPS 10w
  5. Redis如何实现高性能:请求量很大,但实际要做的库存扣减很少,典型的读多写少场景。考虑用Redis做限流,将大部分读请求由Redis承接,数据库承接真正的扣减库存请求即可。因此将库存扣减,以及判断库存是否足够的逻辑前移至Redis实现
    • Redis在进行库存预减的时候,要保证Redis中的数据也不要发生超卖的场景,可用Redis请求队列 + decr或lua脚本实现
    • 在Redis中预扣减成功后,在进行各种DB操作,包括创建订单记录,DB扣库存等,实际上就是一部分限流交由了Redis实现
  6. 除了高并发、高性能外,还要保障高可用,即不发生缓存击穿等情况,一旦发生缓存击穿,要注意不能将所有请求全落在数据库上,需要使用分布式锁保证一段时间内只有一个客户端访问数据库
  7. 还有就是订单少卖的问题,如果用户下单后超时未支付,那么需要对库存进行补充,有了订单记录后,虽然可以设计一个job对进行中的订单进行支付状态检测,但实时性不好,可以考虑引入mq的延迟队列,下单后即发送一个延迟消息,一定时间后对消息进行消费,判断订单是否已支付,若未支付则进行库存补充
  8. 其他的一些优化:前端的优化、防爬、负载均衡、熔断等,基本都是围绕过滤无用请求,降低并发度,提高服务可用性等方面进行的优化手段

推荐阅读:实现真正的高性能高并发的上亿级别秒杀系统!

22. 如何保证缓存和DB的数据一致性?

  1. 如何保证缓存和数据库的一致性?
  2. 数据库和缓存如何保证一致性?

23. 一个对象存储在 Redis 中,选用 str 结构还是 hash 结构?

主要看使用场景:可以将整个对象序列化为 JSON 后存储为字符串,也可以将对象中的每个字段序列化后,用 HMSET 存储在哈希表中,两种方式各有优劣,一个是读取整个对象比较方便,一个是读取对象中的单个字段比较方便。

24. Redis 缓存击穿,穿透是什么?如何解决?

什么是缓存雪崩、击穿、穿透?

25. 大Key会带来什么问题,怎么解决?

发现并处理Redis的大Key和热Key

26. Redis集群、主从架构,如何保证数据一致性?

这个问题再思考思考。

参考阅读

  1. 2023最新整理上千道Java面试攻略,近500页PDF文档