自学内容网 自学内容网

Redis面试题——第一篇

1. Redis主从复制的实现原理是什么

Redis的主从复制是指一个Redis实例可以将数据复制到一个或者多个从节点,从节点从主节点获取数据并保持同步。

复制流程

  • 连接:从节点通过向主节点发送PSYNC命令建立连接。
  • 全量复制:如果是第一次连接或者之前的连接失效,从节点会请求全量复制,主节点将当前数据快照发送给从节点。
  • 增量复制:全量复制完毕后,主从之间会保持一个长连接,主节点通过这个连接将后续的写操作传递给从节点执行,来保证数据的一致。

2. Redis集群的实现原理是什么

Redis集群是通过多个Redis实例组成,每个实例存储部分的数据(即每个实例之间的数据是不重复的)

具体是由哈希槽机制来分配数据,将整个键空间划分为16384个槽,每个Redis实例负责一定范围的哈希槽,数据的key经过哈希计算后对16384取余即可定位到对应的节点。

客户端在发送请求时,会通过集群的任意节点进行连接,如果该节点存储了对应的数据则直接返回,反之该节点会根据请求的键值计算哈希槽并路由到正确的节点。

简单来说,集群就是通过多台机器分担单台机器上的压力。

1. Redis集群中节点之间的信息如何同步
Redis集群内每个节点都会保存集群的完整拓扑信息,包括每个节点的ID、IP地址、端口、负责的哈希槽范围等。
节点之间采用Gossip协议进行状态交换,以保持集群的一致性和故障检测,每个节点周期性的发送PING和PONG消息,交换集群信息,使得集群信息得以同步。
Gossip的优点

  • 快速收敛:Gossip协议能够快速传播消息,确保集群状态的迅速更新。
  • 降低网络负担:由于信息是以随机节点间的对话方式传播,避免了集中式的状态查询,从而降低了网络流量。

2. Gossip协议
2.1 Gossip主要特点

  • 分布式信息传播:每个节点定期向其他节点发送状态信息,确保所有节点对集群的状态有一致的视图。
  • 低延迟和高效率:Gossip协议设计为轻量级的通信方式,能够快速传播信息,减少单点故障带来的风险。
  • 去中心化:没有中心节点,所有节点平等的参与信息传播,提高了系统的鲁棒性。

2.2 工作原理

  • 状态报告:每个节点在特定的时间间隔内,向随机选择的其他节点发送自身的状态信息,包括节点的主从关系、槽位分布等。
  • 信息更新:接收到状态信息的节点会根据所接受到的数据更新自己的状态,并将更新后的状态继续传播给其他节点。
  • 节点检测:通过周期性交换状态信息,节点可以检测到其他节点的存活状态。如果某个节点未能在预定时间内响应,则该节点会被标记为故障节点。
  • 容错处理:在检测到节点故障后,集群中的其他节点可以采取措施以保持系统的高可用性。

3. Redis 集群分片原理
Redis集群会将数据分散到16384个哈希槽中,集群中的每个节点负责一定范围的哈希槽,在Redis集群中,使用CRC16哈希算法计算键的哈希值,已确定该键应存储在哪个节点。

集群哈希槽分片如图所示
在这里插入图片描述
每个节点会拥有一部分的槽位,然后对应的键值会根据其本身的key,映射到一个哈希槽中,主要流程如下:

  • 根据键值的key,按照CRC16算法计算一个16bit的值,然后将16 bit的值对16384进行取余运算,最后得到一个对应的哈希槽编号。
  • 根据每个节点分配的哈希槽区间,对应编号的数据落在对应的区间上,就能找到对应的分片实例。

3.1 Redis集群中请求key示例
查询过程

  1. 计算哈希槽
  • 客户端使用CRC16算法计算user:1001的哈希槽(假设为12345)
  • 计算哈希槽:12345%16384 = 12345
  1. 查询请求
  • 因为客户端连接的是集群中的node1,所以客户端发送查询命令到Node1.
  1. Node1响应
  • Node1检测到请求的键user:1001属于Node2,返回一个Moved指令,指示客户端请求的键在另一个节点上。Moved错误中会返回目标节点信息(例如,Node2的IP和端口)
  1. 重新连接
  • 客户端根据返回的目标节点信息,建立与Node2的连接。
  1. 再次发送查询请求
  2. 获取结果

3. Redis通常应用于哪些场景

  1. 缓存:Redis最常用的场景是作为缓存层,以减少数据库的负载,提高数据读取速度。
  2. 实时系统:Redis支持快速的数据写入和读取,非常适合用于实时分析,如网站点击统计、实时排行榜等。
  3. 消息队列:利用Redis的List的Pub/Sub功能,可以实现轻量级的消息队列,适用于任务处理和异步消息传递。
  4. 分布式锁:Redis可以用作分布式锁的实现,确保在分布式系统中资源的安全访问。
  5. 计数器:Redis的原子性操作非常适合用于计数器。

4. Redis为什么这么快

主要有3方面的原因,分别是存储方式、优秀的线程模型以及IO模型、高效的数据结构

  • Redis将数据存储在内存中,提供快速的读写速度,相比于传统的磁盘数据库,内存访问速度快得多。
  • Redis使用单线程事件驱动模型结合IO多路复用,避免了多线程上下文切换和竞争条件,提高了并发处理效率。
  • Redis提供了多种高效的数据结构,这些结构经过优化,能够快速完成各种操作。

select、poll和epoll之间的区别
Select、Poll和Epoll是用来实现IO多路复用的机制,主要用于同时监视多个文件描述符的状态变化,包括可读、可写和异常事件。通过这些机制,可以在单个线程中同时处理多个IO操作,提高系统的性能和效率。
1. select

  • select是最古老的一种IO多路复用机制,可用于同时监视多个文件描述符的状态变化。
  • select使用了一个fd_set集合来保存需要监视的文件描述符,并提供了三个不同的集合来分别表示可读、可写和异常事件。
  • select的主要缺点是效率较低,因为他采用轮询的方式来检查每个文件描述符的状态变化,当文件描述符数量较大时,效率会明显下降。

2. Poll

  • Poll是对Select的改进,使用一个pollfd结构体数组来保存需要监视的文件描述符及其关注的事件。
  • Poll不受文件描述符数量的限制,因为他是基于链表实现的,不需要遍历整个集合。
  • Poll的效率比Select高一些,但仍然不适用于大规模的连接。

3. Epoll

  • Epoll是linux下的一种高性能IO多路复用机制,相比于Select和Poll,它具有更高的性能和更好的扩展性。
  • Epoll使用了一个事件表来保存需要监视的文件描述符,并使用回调机制来通知应用程序发生的事件。
  • Epoll采用了内核事件通知机制,可以避免轮询,只有在有事件发生时才会唤醒应用程序,因此效率更高。

5. 为什么Redis设计为单线程? 6.0版本为何引入多线程

单线程设计原因

  1. Redis的操作是基于内存的,其大多数操作的性能瓶颈主要不是CPU导致的。
  2. 使用单线程模型,代码简单的同时也减少了线程上下文切换带来的性能开销
  3. Redis在单线程的情况下,使用IO多路复用模型就可以提高Redis的IO利用率

我们所说的Redis单线程,主要指的是Redis网络IO和键值对读写这些操作是由一个线程完成的。(持久化、集群等机制是有后台线程执行的)
不过Redis并不是一直都单线程的,在4.0之后引入了多线程指令,6.0之后正式引入了多线程机制,不过,这里的 多线程其只是针对网络请求过程使用多线程,其对于数据读写命令的处理依旧是单线程的。

6. Redis中常见的数据类型有哪些

Redis常见的数据结构主要有五种,分别为:String、List、Hash、Set、Zset。

  1. String:字符串是Redis中最基本的数据类型,可以存储任何类型的数据,包括文本、数字和二进制数据。最大长度为512M。

使用场景:

  • 缓存:存储临时数据,如用户会话、页面缓存。
  • 计数器:用于统计访问量、点赞数等。
  1. Hash:Hash是一个键值对集合,适合存储对象的属性。Redis内部使用哈希表实现,适合小规模数据。

使用场景

  • 商品详情:存储商品的各个属性,方便快速检索。
  1. List:列表是有序的字符串集合,支持从两端的推入和推出元素,底层实现为双向链表。

使用场景

  • 消息队列:用于简单任务调度、消息传递等。
  • 历史记录:存储用户操作的历史记录,便于快速访问。
  1. Set
    集合是无序且不重复的字符串集合,使用哈希表实现,支持快速查找和去重操作。

使用场景:

  • 标签系统:存储用户兴趣标签。
  • 唯一用户集合
  1. Sorted Set
    有序集合类似于集合,每个元素都有一个分数,用于排序。底层使用跳表实现,支持快速的范围查询。

使用场景

  • 排行榜:存储用户分数,实现实时排行榜
  • 任务调度:根据任务的优先级进行排序,方便调度执行。

四种高级数据类型
BitMap、HyperLogLog、GEO、Stream

  1. BitMap
    是一种以位为单位存储数据的高效方式,适合用来表示布尔值(如存在性、状态等)。每个bit可以表示一个状态,使用空间少且操作快速。
    使用实例:假设要统计每天用户的在线状态,可以用Bitmap记录每个用户是否在线。
    在这里插入图片描述
  2. HyperLogLog
    HyperLogLog是一种概率性数据结构,主要用于估算基数,内存占用固定,适合处理大规模数据的去重和计数。
    使用示例:假设要估算访问网站的独立用户数量
    在这里插入图片描述
  3. GEO
    GEO是Redis提供的一种用于存储地理位置信息的数据结构,可以存储经纬度信息并支持空间查询。例如,计算距离和获取范围内的坐标
    使用示例:假设要存储城市的位置并查找距离某个城市在一定范围内的其他城市
    在这里插入图片描述
  4. Stream
    Stream是Redis提供的一种日志数据结构,适合于存储时间序列数据或者消息流。支持高效的消息生产和消费模式,具有持久性和序列化特性。

7. Redis中跳表的实现原理是什么

跳表主要是 通过多层链表来实现,底层链表保存所有元素,而每一层链表都是下一层的子集。

  • 插入时:首先从最高层开始查找插入元素,然后随机决定新节点的层数,最后在相应的层中插入节点并更新指针。
  • 删除时:同样从最高层开始查找要删除的节点,并在各层中更新指针,以保持跳表的结构。
  • 查找时,从最高层开始,逐层向下,直到找到目标元素或者确定元素不存在。查找效率高,时间复杂度为O(logn).

跳表原理解析
跳表,一句话概括:就是一个多层索引的链表,每一层索引的元素在最底层的链表中可以找到。如下所示
在这里插入图片描述

  1. 查询元素在这里插入图片描述
  2. 插入元素
    在这里插入图片描述

8. Redis中的哈希是什么

Redis中的Hash是一种键值对集合,适合存储对象类型的数据。每个hash由一个唯一的键和一组字段——值对组成,具有以下特点:

  1. 内存高效:适合存储小数据,使用哈希表实现,能够在内存中高效存储和操作。
  2. 灵活性强:支持快速的字段操作,如增、删、改、查,非常适合存储对象的属性。

9. Redis和Memcache有哪些区别

  1. 从数据结构上
  • Redis:支持多种数据结构,如字符串、列表、集合、有序集合、哈希表、适合存储复杂数据类型。
  • Memcache:仅支持简单的键值对存储。
  1. 从持久化上
  • Redis:支持持久化功能,可以将数据保存在磁盘上,通过RDB和AOF两种方式实现数据的持久化
  • Memcache:不支持数据持久化,重启后数据会丢失,适合临时数据存储。
  1. 从分布式架构上
  • Redis:内置支持主从复制和集群分片,能在分布式环境中提供高可用性和扩展性。
  • Memcache:没有内置分片支持
  1. 从功能上
  • Redis:支持发布订阅、Lua脚本等
  • Memcache:特性较少。

10. Redis支持事务吗?如何实现

Redis支持事务,但他的事务和MySQL中的事务有所不同。MySQL中的事务主要支持ACID特性,而Redis中的事务主要保证多个命令执行的原子性。即所有的命令在一个原子操作中 执行,不会被打断。

MySQL中的事务支持回滚,Redis不支持回滚。

1. Redis的事务
Redis支持事务,通过使用multi、exec、watch和discard等命令实现。事务中的命令会被排队并在调用exec时一次性执行,保证了事务的原子性。

具体实现流程如下:

  1. 开始事务:使用multi开始一个事务,之后所有命令都会被排队
  2. 添加命令:在事务中添加命令,这些命令不会立即执行,而是存储在队列中
  3. 执行事务:使用exec命令执行队列中的所有命令
  4. 取消事务:使用discard命令可以放弃事务,清空队列
  5. 监视键:使用watch命令可以监视一个或者多个键,如果在事务执行前这些键被修改,则exec将不会执行。

原文地址:https://blog.csdn.net/weixin_42824596/article/details/142757452

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!