【Redis】redis常见面试题

redis为什么这么快

(1)纯内存操作
(2)多路复用io
多路I/O复用模型是利用select、poll、epoll可以同时监察多个流的I/O事件的能力,在空闲的时候会把当前线程阻塞掉,当有一个或者多个流有I/O事件时,就从阻塞中唤醒,于是程序就会轮询一遍所有的流(epoll只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法避免了大量的无用操作
(3)单线程,避免了频繁的上下文切换

memcache与Redis比较

在这里插入图片描述

redis基本数据类型

(1)String
Redis 中的字符串是一种 动态字符串,这意味着使用者可以修改,它的底层实现有点类似于 Java 中的 ArrayList,有一个字符数组,从源码的 sds.h/sdshdr 文件 中可以看到 Redis 底层对于字符串的定义 SDS,即 Simple Dynamic String 结构。

(2)Hash
类似一种Map的结构,可以将结构化的数据(比如对象)缓存进去,每次读写的时候可以就操作hash里的某个字段。

(3)List
有序列表,irange命令可以从某个元素开始读取多少个元素,实现list分页

(4)Set
无序集合,自动去重
set有序的情况:(redis里集合的编码有两种,intset(有序)和hashtable(无序))①保存的所有元素都是整数 ②元素数量不超过512个

(5)ZSet
有序set
内部结构:①压缩列表,键和分值紧凑排在一起,分值小的排在前面,(集合元素小于128个,集合每个元素的键和分值都小于64k,否则升级为跳跃表 ②跳跃表,跳跃表每个节点都包含分值和键。

redis主从、哨兵、集群

redis主从同步原理:
redis的复制分为全量复制(快照复制)和增量复制
全量复制有三种场景:
(1)从节点刚加入到集群中
(2)从节点宕机后恢复时,从节点之前复制的主节点和现在的主节点不一致
(3)从节点宕机恢复后,从节点的offset偏移量在主节点的复制积压缓冲区已经不存在
全量复制的执行流程:
(1)主服务器执行bgsave操作,生成rdb文件,将rdb文件发送给从服务器
(2)从服务器接收rdb文件,载入数据到内存中
(3)在发送的过程中,主服务器记录发送过程中所有的写命令到缓冲区中
(4)从服务器载入rdb文件完成后通知主服务器,主服务器将缓冲区中的数据发送给从服务
(5)从服务执行命令将自己的数据库状态更新到主服务器对应的状态
(6)之后主从进行命令传播

哨兵组件的主要功能:
(1)集群监控:负责监控redis master和slave进程是否正常工作
(2)消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
(3)故障转移:如果redis master挂掉了,会自动转移到slave node上(三个实例才能保证健壮性)
(4)配置中心:如果故障转移发生了,通知client新的master地址

redis集群:
Redis集群是一个由多个主从节点群组成的分布式服务集群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。
原理分析:
Redis Cluster 将所有数据划分为 16384 个 slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。只有master节点会被分配槽位,slave节点不会分配槽位。
当Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息,并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。同时因为槽位的信息可能会存在客户端与服务器不一致的情况,还需要纠正机制来实现槽位信息的校验调整。

redis持久化

RDB机制:
RDB其实就是把数据以快照的形式保存在磁盘上,快照可以理解成把当前时刻的数据拍成一张照片保存下来。
RDB持久化是指在指定的时间间隔内将内存的数据集快照写入磁盘,也是默认的持久化方式,这种方式就是将内存中数据以快照的方式(fork子进程)写入到二进制文件中,默认的文件名为dump.rdb。

RDB优势:
(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
RDB劣势:
RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
在这里插入图片描述

AOF机制:
全量备份总是耗时的,redis为我们提供一种更加高效的方式AOF,redis会将每一个收到的写命令都通过write函数追加到文件中,通俗理解就是日志记录。
在这里插入图片描述
AOF优势:
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
(4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据
AOF劣势:
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

skiplist(跳表)与平衡树、哈希表的比较

(1)skiplist和各种平衡树(如AVL、红黑树等)的元素是有序排列的,而哈希表不是有序的。因此,在哈希表上只能做单个key的查找,不适宜做范围查找。所谓范围查找,指的是查找那些大小在指定的两个值之间的所有节点。
(2)在做范围查找的时候,平衡树比skiplist操作要复杂。在平衡树上,我们找到指定范围的小值之后,还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造,这里的中序遍历并不容易实现。而在skiplist上进行范围查找就非常简单,只需要在找到小值之后,对第1层链表进行若干步的遍历就可以实现。
(3)平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。
(4)从内存占用上来说,skiplist比平衡树更灵活一些。一般来说,平衡树每个节点包含2个指针(分别指向左右子树),而skiplist每个节点包含的指针数目平均为1/(1-p),具体取决于参数p的大小。如果像Redis里的实现一样,取p=1/4,那么平均每个节点包含1.33个指针,比平衡树更有优势。
(5)查找单个key,skiplist和平衡树的时间复杂度都为O(log n),大体相当;而哈希表在保持较低的哈希值冲突概率的前提下,查找时间复杂度接近O(1),性能更高一些。所以我们平常使用的各种Map或dictionary结构,大都是基于哈希表实现的。
(6)从算法实现难度上来比较,skiplist比平衡树要简单得多。

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

缓存雪崩解决方式:把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效;或者设置热点数据永不过期,有更新操作就更新缓存就好了(比如运维更新了首页商品,那你刷下缓存就ok了,不要设置过期时间)。

缓存穿透解决方式:在接口层增加校验,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return;或者查询不出数据也可以缓存起来,缓存有效时间可以设置短点。
布隆过滤器(Bloom Filter)这个也能很好的防止缓存穿透的发生,它是利用高效的数据结构(bitmap)和算法快速(类似hash)判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。

缓存击穿解决方式:设置热点数据永不过期,或者加上互斥锁就行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值