Reids面试问题以及答案

文章目录


1. 什么是 Redis?

Redis(Remote Dictionary Server)是一个内存数据库,类似于 memcached,采用键值对存储数据,但它的数据库全部加载在内存中进行操作,并定期通过异步操作将数据刷新到硬盘上进行持久化保存。Redis以其出色的性能而闻名,每秒可以处理超过 10 万次读写操作,是已知性能最快的键值型数据库之一。除了性能,Redis还支持保存多种数据结构,并且单个 value 的最大限制是 1GB,这使得它可以实现多种有用的功能,比如实现消息队列、高性能的 tag 系统等。

2. Redis 的优缺点

优点:

  • 出色的性能,每秒处理超过 10 万次读写操作。
  • 支持多种数据结构,如 String、List、Set、Sorted Set、Hashes。
  • 单个 value 最大限制为 1GB。
  • 支持数据持久化,可以将数据保存到硬盘上。
  • 可以设置过期时间,用作缓存。

缺点:

  • 数据库容量受物理内存限制,不适合海量数据的高性能读写。
  • 内存消耗较大。
  • 不支持复杂的查询语句。

3. Redis 与 Memcached 的优势比较

  1. 数据类型支持:Redis 支持丰富的数据类型,如 String、List、Set、Sorted Set、Hashes,而 Memcached 的值都是简单的字符串。
  2. 速度:Redis 比 Memcached 快很多。
  3. 数据持久化:Redis 可以持久化其数据,而 Memcached 不支持持久化。

4. Redis 支持的数据类型

Redis 支持以下数据类型:

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

5. Redis 主要消耗的物理资源

Redis 主要消耗内存资源,因为它的数据库全部加载在内存中进行操作。

6. Redis 的数据淘汰策略

Redis 支持以下几种数据淘汰策略:

  1. noeviction:当内存限制达到时,拒绝执行可能会增加内存使用的命令。
  2. allkeys-lru:尝试回收最近最少使用的键(LRU),以便新的数据有空间存放。
  3. volatile-lru:尝试回收最近最少使用的键(LRU),但仅限于过期集合的键,以便新的数据有空间存放。
  4. allkeys-random:随机回收键,以便新的数据有空间存放。
  5. volatile-random:随机回收键,但仅限于过期集合的键,以便新的数据有空间存放。
  6. volatile-ttl:回收在过期集合的键,并优先回收存活时间(TTL)较短的键,以便新的数据有空间存放。

7. Redis 官方为什么不提供 Windows 版本?

Redis 官方不提供 Windows 版本的主要原因是因为目前 Linux 版本已经相当稳定,并且拥有庞大的用户群体,不需要额外开发和维护 Windows 版本。开发和维护 Windows 版本会增加兼容性等问题,而且 Linux 版本已经能够满足大多数用户的需求。

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

一个字符串类型的值最大容量是 512MB。

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

Redis 将数据放到内存中主要是为了达到最快的读写速度,并通过异步的方式将数据写入磁盘以实现持久化。如果不将数据放在内存中,磁盘 I/O 速度将严重影响 Redis 的性能。随着内存价格的不断下降,Redis 在内存中存储数据已成为一种常见且高效的做法。但需要注意的是,如果设置了最大使用的内存,当数据量达到内存限制时就不能继续插入新值。

10. Redis 集群方案应该怎么做?都有哪些方案?

Redis 集群方案有几种不同的实现方式:

  1. Codis: Codis 是一个比较常见的集群方案,与 Twemproxy 类似,但支持在节点数量改变时进行数据迁移。
  2. Redis Cluster: Redis 3.0 开始自带的集群方案,采用哈希槽的分布式算法,支持节点设置从节点。
  3. 业务代码层实现: 通过在业务代码层实现哈希计算,将数据存储在不同的 Redis 实例中。这种方式需要在代码层处理节点失效、数据迁移等问题,对哈希层代码要求较高。

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

在没有复制模型的情况下,如果集群中某个节点失效,而且数据没有被复制到其他节点,整个集群可能会认为缺少某些哈希槽的数据而变得不可用。这种情况下,需要进行数据迁移或者重新配置集群。

12. MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据?

Redis 内存数据集大小上升到一定大小时会施行数据淘汰策略,可以通过合理设置淘汰策略和数据过期时间,以及根据业务需求将热点数据放入 Redis 中,来保证 Redis 中的数据都是热点数据。

13. Redis 支持的 Java 客户端

Redis 支持的 Java 客户端包括 Redisson、Jedis、Lettuce 等,其中官方推荐使用 Redisson。

14. Redis 和 Redisson 的关系

Redisson 是 Redis 的高级分布式协调客户端,帮助用户在分布式环境中轻松实现各种 Java 对象。它是 Redis 的一个 Java 客户端的实现。

15. Jedis 和 Redisson 对比

Jedis

  • 提供了全面的 Redis 命令支持。
  • 功能较为丰富,支持字符串操作、排序、事务、管道、分区等 Redis 特性。

Redisson

  • 实现了分布式和可扩展的 Java 数据结构。
  • 功能相对简单,不支持字符串操作等,但更专注于分布式环境下的对象操作。

16. Redis 哈希槽的概念

Redis 集群引入了哈希槽的概念,共有 16384 个哈希槽,每个键通过 CRC16 校验后对 16384 取模来决定放置哪个槽。每个节点负责管理一部分哈希槽。

17. Redis 集群的主从复制模型

Redis 集群采用主从复制模型,每个节点都有 N-1 个复制品,确保在部分节点失败或大部分节点无法通信的情况下集群仍然可用。

18. Redis 集群的写操作丢失情况

Redis 无法保证数据的强一致性,因此在特定条件下,集群可能会丢失写操作。

19. Redis 集群之间的复制方式

Redis 集群之间的复制方式为异步复制,即主节点将数据变更发送给从节点,但不等待从节点完成确认。

20. Redis 集群最大节点个数

Redis 集群最大节点个数是 16384 个。

21. Redis 集群如何选择数据库

Redis 集群目前无法选择数据库,默认使用 0 号数据库。

22. Redis 中的管道的作用

Redis 中的管道(pipelining)可以将多个命令一次性发送给服务器,而无需等待每个命令的回复。这样可以大大提高命令的执行效率,尤其在需要频繁通信的场景下,如批量写入或读取操作。

23. 理解 Redis 事务

Redis 事务是一组命令的集合,它们被序列化并按顺序执行。事务中的命令要么全部执行,要么全部不执行,具有原子性。事务在执行期间不会受到其他客户端命令的干扰。

24. Redis 事务相关命令

Redis 事务相关的命令包括:

  • MULTI:标记事务的开始。
  • EXEC:执行事务中的所有命令。
  • DISCARD:取消事务,放弃事务中的所有命令。
  • WATCH:监视一个或多个键,如果在事务执行前这些键被其他客户端修改,则事务将被打断。

25. Redis key 的过期时间和永久有效设置方式

  • 过期时间:使用 EXPIRE 命令设置键的过期时间,例如 EXPIRE key seconds
  • 永久有效:使用 PERSIST 命令移除键的过期时间,使其永久有效,例如 PERSIST key

26. Redis 内存优化

尽可能使用散列表(hashes)存储数据,将相关信息存储在同一个散列表中,而不是单独设置多个键。这样可以减少内存占用,提高内存利用率。

27. Redis 回收进程工作原理

Redis 回收进程工作方式如下:

  1. 当一个客户端执行新的命令并添加了新的数据时,Redis 检查内存使用情况。
  2. 如果内存使用量超过了 maxmemory 的限制,则根据设定好的策略进行回收。
  3. 在执行新命令的过程中,不断地穿越内存限制的边界,通过回收来保持内存使用在限制范围内。

这样可以确保 Redis 在不断变化的内存使用情况下仍能保持稳定运行。

28. Redis 适合的场景

  1. 会话缓存(Session Cache):用于缓存会话信息,Redis 提供持久化,确保数据不丢失。
  2. 全页缓存(FPC):Redis 提供简便的全页缓存平台,可用于加速页面加载速度。
  3. 队列:利用 Redis 的 list 和 set 操作实现消息队列,适用于各种队列需求。
  4. 排行榜/计数器:Redis 提供良好的递增/递减操作,适用于实时排行榜等场景。
  5. 发布/订阅:Redis 的发布/订阅功能适用于社交网络连接、脚本触发器、聊天系统等。

29.Redis 如何实现延时队列

使用 sortedset,使用时间戳做 score, 消息内容作为 key,调用 zadd 来生产消息,消费者使用 zrangbyscore 获取 n 秒之前的数据做轮询处理。

30.主从数据库不一致的解决方案

当主从数据库更新同步存在时差时,可以采取以下解决方案:

  1. 忽略数据不一致

    • 对于数据一致性要求不高的业务,可以选择忽略主从库数据不一致的情况。
    • 这种方案适用于不需要实时一致性的场景,可以接受一定程度的数据延迟。
  2. 强制读取主库

    • 使用一个高可用的主库,将数据库的读写操作都集中在主库进行。
    • 添加一个缓存层,用于提升数据读取的性能。
    • 通过强制读取主库,可以避免因为主从同步延迟而导致的数据不一致问题。
  3. 选择性读取主库

    • 添加一个缓存层,用来记录必须从主库读取的数据。
    • 将哪个库、哪个表、哪个主键作为缓存的键。
    • 设置缓存的失效时间为主从库同步的时间间隔。
    • 当需要读取数据时,首先检查缓存中是否存在该数据,如果缓存中存在,则直接从主库读取;如果缓存中不存在,则从对应的从库中读取。
    • 这种方式可以在保证一定的实时性的同时,降低对主库的访问压力,提高系统的整体性能。

28.缓存与数据库不一致的处理方案

在采用主从分离、读写分离的数据库架构中,当缓存与数据库不一致时,可以考虑以下处理方案:

  1. 问题描述

    • 线程A删除了缓存数据,然后将数据写入主库,但主从同步尚未完成。
    • 线程B从缓存中读取数据失败,从从库中读取到旧数据,并更新至缓存,导致缓存中的数据是旧的。
  2. 处理思路

    • 在从库有数据更新之后,立即更新缓存中的数据,保持数据的一致性。
  3. 具体实现

    • 当从库发生数据更新时,立即通知缓存更新相应的数据。
    • 可以通过在从库上设置触发器或使用消息队列等机制,监听数据更新事件。
    • 一旦从库发生数据更新,立即通知缓存进行相应的数据更新操作,保持缓存和数据库的一致性。
    • 这样可以避免由于主从同步延迟而导致的缓存数据不一致的问题。
  4. 综合考虑

    • 综合考虑业务场景和系统性能,可以选择合适的缓存更新策略。
    • 如果对数据一致性要求较高,可以采用实时更新缓存的策略;如果可以容忍一定的延迟,可以采用定时或延迟更新缓存的策略。

29.选择缓存时,什么时候选择 redis,什么时候选择 memcached

选择 Redis 的情况:

  1. 复杂数据结构需求

    • 当需要存储复杂数据结构,如哈希、列表、集合、有序集合等时,选择 Redis 更为合适。因为 Redis 支持丰富的数据结构,而 Memcached 仅支持简单的键值对存储。
  2. 数据持久化需求

    • 如果需要数据持久化功能,但又不希望将 Redis 作为主要的数据库使用,可以选择 Redis。Redis 提供持久化功能,并能够快速恢复热数据,避免将压力瞬间压在数据库上。
  3. 高可用需求

    • 当需要高可用性、集群支持、主动复制和读写分离等功能时,Redis 更为适合。Redis 提供了集群支持和主从复制功能,可以实现高可用架构。
  4. 存储内容较大

    • 如果需要存储的内容较大,超过了 Memcached 的存储限制(最大为1MB),则选择 Redis 更为合适。

选择 Memcached 的情况:

  1. 纯 KV 存储需求

    • 当仅需简单的键值对存储,并且数据量非常大时,选择 Memcached 更为适合。
  2. 高吞吐量需求

    • 如果需要处理高吞吐量的业务,由于 Memcached 的内存分配和网络模型优化,可能更适合处理大规模数据请求。
  3. 多核利用需求

    • Memcached 使用多线程模型,适用于多核利用,尽管可能存在锁冲突,但对于处理大规模数据请求时可能更有效。
  4. 对 CPU 计算需求不高

    • 如果业务不涉及复杂的 CPU 计算、排序、聚合功能等,Memcached 的网络模型和线程模型可能更适合处理简单的键值对存储请求。

30.缓存穿透、缓存击穿、缓存雪崩解决方案?

缓存穿透:

问题描述: 查询一个一定不存在的数据,导致每次请求都要到数据库查询,可能导致数据库压力过大甚至宕机。

解决方案:

  1. 查询返回的数据为空时,仍将空结果进行缓存,但设置较短的过期时间。
  2. 使用布隆过滤器:将可能存在的数据哈希到一个足够大的位图中,一定不存在的数据会被拦截掉,避免对数据库的查询。

缓存击穿:

问题描述: 缓存中的数据在某个时间点同时失效,导致大量请求直接访问数据库,可能导致数据库压力过大甚至宕机。

解决方案:

  1. 使用互斥锁:缓存失效时先使用互斥锁设置锁,成功后再进行加载数据库的操作,并回设缓存;否则重试获取缓存的操作。
  2. 永不过期:物理上不设置过期时间,但在逻辑上设置过期时间,后台异步线程负责定时刷新缓存。

缓存雪崩:

问题描述: 大量缓存在同一时刻同时失效,导致大量请求直接访问数据库,可能导致数据库压力过大甚至宕机。

解决方案:

  1. 将缓存失效时间分散开,可在原有失效时间基础上增加一个随机值,如1-5分钟的随机时间,降低缓存失效的集中度,减少雪崩风险。

相关推荐

  1. Reids面试问题以及答案

    2024-03-22 01:46:03       17 阅读
  2. memcached面试问题以及答案

    2024-03-22 01:46:03       18 阅读
  3. SpringCloud面试以及答案

    2024-03-22 01:46:03       18 阅读
  4. mysql面试相关问题答案

    2024-03-22 01:46:03       33 阅读
  5. 一些常见的Redis问题答案

    2024-03-22 01:46:03       18 阅读
  6. Redis面试高频问题

    2024-03-22 01:46:03       10 阅读
  7. 【大数据面试】MapReduce常见问题答案

    2024-03-22 01:46:03       47 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-22 01:46:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-22 01:46:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-22 01:46:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-22 01:46:03       20 阅读

热门阅读

  1. MySQL命令行导入导出数据库

    2024-03-22 01:46:03       17 阅读
  2. 拷贝函数调用时机

    2024-03-22 01:46:03       18 阅读
  3. OD C卷 - 员工派遣

    2024-03-22 01:46:03       21 阅读
  4. vue3组合式父页面调用子页面的方法

    2024-03-22 01:46:03       19 阅读
  5. 【Caddy】 Ubuntu 下卸载 Caddy

    2024-03-22 01:46:03       18 阅读