Redis的87道高质量面试题

本文详细介绍了Redis的复制、哨兵和集群的优缺点,探讨了Redis速度快的原因,解释了哨兵系统的工作原理及其功能。文章还讨论了Redis在项目中的应用场景,如缓存数据、消息队列、计数器等,并阐述了如何确保MySQL与Redis之间的数据一致性。此外,还详细讲解了内存淘汰策略、Key的过期删除机制以及缓存穿透、缓存击穿和缓存雪崩问题。文章深入讨论了Redis的事务、数据类型、分布式锁的实现以及如何使用Redis实现乐观锁。最后,文章提供了Redis的多种客户端选择、数据扩容方法以及如何优化内存使用。
摘要由CSDN通过智能技术生成

(1)请回答一下:复制,哨兵,集群的优缺点?

(1)复制:复制是高可用Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
(2)哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷是写操作无法负载均衡;存储能力受到单机的限制。
在主从复制的基础上,哨兵引入了主节点的自动故障转移,进一步提高了Redis的高可用性;但是哨兵的缺陷同样很明显:哨兵无法对从节点进行自动故障转移,在读写分离场景下,从节点故障会导致读服务不可用,需要我们对从节点做额外的监控、切换操作。
此外,哨兵仍然没有解决写操作无法负载均衡、及存储能力受到单机限制的问题;这些问题的解决需要使用集群。
总结缺点:读从的时候不能故障转移,写主的时候不能负载均衡。
(3)集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

(2)Redis为什么会这么快?

1、Redis是纯内存操作,需要的时候可以以手动或自动化的方式将数据持久化到硬盘中
2、Redis是单线程,从而避开了多线程中上下文频繁切换而浪费CPU时间片的操作。
3、Redis中存储数据的数据类型大量使用高效率的数据结构算法,对数据的操作更加快捷高效
4、使用底层协议不同,比如Redis自创RESP通讯协议,即保证了运行效率又保证了数据通讯
5、使用多路I/O复用模型,非阻塞I/O

(3)哨兵有哪些功能?

(1)监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。
(2)自动故障转移(Automatic Failover):当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
(3)配置提供者(Configuration Provider):客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址。
(4)通知(Notification):哨兵可以将故障转移的结果发送给客户端。其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则需要在与客户端的交互中才能体现。

(4)介绍一下哨兵的工作原理?

(1)定时任务:每个哨兵节点维护了3个定时任务。定时任务的功能分别如下:通过向主从节点发送info命令获取最新的主从结构;通过发布订阅功能获取其他哨兵节点的信息;通过向其他节点发送ping命令进行心跳检测,判断是否下线。
(2)主观下线:在心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主观下线相对应的是客观下线。
(3)客观下线:哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对该主节点进行客观下线。需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。
(4)选举领导者哨兵节点:当主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。
(5)故障转移:选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:
(A)在从节点中选择新的主节点:选择的原则是,首先过滤掉不健康的从节点;然后选择优先级最高的从节点(由slave-priority指定);如果优先级无法区分,则选择复制偏移量最大的从节点;如果仍无法区分,则选择runid最小的从节点。
(B)更新主从状态:通过slaveof no one命令,让选出来的从节点成为主节点;并通过slaveof命令让其他节点成为其从节点。
(C)将已经下线的主节点(即6379)设置为新的主节点的从节点,当6379重新上线后,它会成为新的主节点的从节点。

(5)项目中哪里用到了Redis?

1、缓存数据:最常用,对经常需要查询且变动不是很频繁的数据存储进Redis,这些数据常称作热点数据。
2、消息队列:相当于消息订阅系统,比如ActiveMQ、RocketMQ。如果对数据有较高一致性要求时,还是建议使用专门的MQ框架)
3、计数器:比如统计点击率、点赞率,Redis具有原子性,可以避免并发问题
4、电商单页信息:商品单页面信息可以存储进Redis。
5、热点数据:比如新闻网站实时热点、微博热搜等,需要频繁更新。总数据量比较大的时候直接从数据库查询会影响性能。
6、地理位置:比如查询附近有哪些人,哪个商家等需求
7、可以结合自己的项目的使用情况进行解答

(6)项目中如何保障MySQL和Redis中的数据一致性的?

真正意义上或从项目运行效率上或从突然出现异常等原因来分析,数据库中的数据和缓存中的数据是不可能做到实时一致的,数据分为最终一致和强一致两类。如果业务中对数据的要求必须强一致,那么就不能使用缓存。缓存能做的只能保证数据的最终一致性。MySQL和Redis中的数据只能尽可能的保证数据的最终一致性。不管是先删库再删缓存,还是先删缓存再删库,都可能出现数据不一致的情况,只保障最终一致性即可。

(7)介绍一下内存淘汰?

内存淘汰是指用户存储的一部分key是可以根据不同的策略被Redis自动的删除,以释放内存资源,从而会出现从缓存中查不到数据的情况。
内存淘汰策略有2种算法
(1)LRU:最近最少使用Least Recently Used,删除很久没有访问的数据。
(2)LFU:最近最不常用Least Frequently Used,删除访问频率最少的数据。
Redis支持的内存淘汰方式有如下8种
(1)noeviction:不淘汰策略,存放的数据大于最大内存限制时会返回异常信息。
(2)volatile-lru:对具有过期的key使用lru。
(3)volatile-lfu:对具有过期的key使用lfu。
(4)volatile-random:对具有过期的key使用随机删除。
(5)volatile-ttl:对具有过期的key使用ttl最小值删除。
(6)allkeys-lru:对所有key采用lru。
(7)allkeys-lfu:对所有key采用lfu。
(8)allkeys-random:对所有key使用随机删除。

(8)介绍一下KEY的过期删除?

Redis存储数据时可以对KEY设置TTL过期时间,但并不只是单一的使用定时扫描删除策略,因为如果这样做,就需要一个定时器来不断的负责监控这些key,虽然内存释放了,但是非常消耗cpu资源。
Redis中对过期的key进行删除主要有两种方式
(1)定期删除:默认每100ms检测一次,遇到过期的key则进行删除,这里的检测并不是顺序检测,而是随机检测。那这样会不会有漏网之鱼没有被删除?肯定会有,这时可以采用惰性删除策略。
(2)惰性删除:当读或写一个已经过期的key时,会触发Redis的惰性删除策略,会删除过期的key。

(9)什么是缓存穿透?

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
(1)接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
(2)从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

(10)什么是缓存击穿?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案
(1)设置热点数据永远不过期。
(2)加互斥锁,互斥锁参考代码如下:
在这里插入图片描述
1)缓存中有数据,直接走代码13行后就返回结果了
2)缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待100ms,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
原理就是:缓存中没有数据时,排队操作数据库,降低数据库访问的压力,缺点是比较卡,可以采用限流的方式来进行优化,比如最多只能20个客户端一起访问。

(11)什么是缓存雪崩?

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
(1)缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
(2)如果缓存数据库是分布式部署,多区域查询。比如A集群KEY采用过期时间一样,而B集群中的KEY过期时间是随机的,当查询A集群没有数据时,到B集群进行查询。使用IF语句判断进行集群查询的切换。
(3)设置热点数据永远不过期。
(4)二级缓存,原始缓存失效时从复本缓存中读取数据。
(5)利用加锁或者队列方式避免过多请求同时对服务器进行读写操作。

(12)介绍一下Redis的优势?

1.)非常丰富的数据类型;
2.)Redis提供了事务的功能,可以保证一串命令的原子性,中间不会被任何操作打断;
3.)数据存在内存中,读写非常的高速,可以达到10w/s的频率。

(13)介绍一下主从复制?

(1)数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
(2)故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复。
(3)负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
(4)高可用基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
(5)全量复制:用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。
(6)部分复制:用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。

(14)介绍一下RDB?

RDB持久化是将当前进程中的数据生成快照保存到硬盘(因此也称作快照持久化),保存的文件后缀是rdb;当Redis重新启动时,可以读取快照文件恢复数据。RDB文件是经过压缩的二进制文件。
RDB是快照备份。

(15)介绍一下AOF?

RDB持久化是将进程数据写入文件,而AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录到单独的日志文件中(有点像MySQL的binlog);当Redis重启时再次执行AOF文件中的命令来恢复数据。
AOF是增量备份。

(16)介绍一下AOF中的appendfsync同步数据的3种策略?

AOF缓存区的同步文件策略由参数appendfsync控制,各个值的含义如下:
(1)always:命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下,每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。
每执行一个命令就开始备份。
(2)no:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
根据操作系统来决定什么时候备份。
(3)everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是推荐的配置。
每隔一秒一备份。

(17)什么是AOF重写

随着时间流逝,Redis服务器执行的写命令越来越多,AOF文件也会越来越大;过大的AOF文件不仅会影响服务器的正常运行,也会导致数据恢复需要的时间过长。
文件重写是指定期重写AOF文件,减小AOF文件的体积。需要注意的是,AOF重写是把Redis进程内的数据转化为写命令,同步到新的AOF文件,不会对旧的AOF文件进行任何读取、写入操作。创建完新的AOF文件后会把旧的AOF文件覆盖掉。

(18)RDB和AOF的优缺点

RDB持久化
优点:RDB文件紧凑,体积小,网络传输快,适合全量复制;恢复速度比AOF快很多。当然,与AOF相比,RDB最重要的优点之一是对性能的影响相对较小。
缺点:RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。此外,RDB文件需要满足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。

AOF持久化
优点:支持秒级持久化、兼容性好。
缺点:文件大、恢复速度慢、对性能影响大。

使用bgsave命令实现全量备份持久化,而aof做增量持久化。bgsave会耗费较长时间,不够实时,如果有新的数据在没有备份的情况下有可能因为宕机,停电等原因会出现数据丢失,所以需要aof来配合使用。在Redis实例重启时,优先使用aof来恢复内存的状态,如果没有aof日志,就会使用rdb文件来恢复。

(19)如何用Redis实现乐观锁

在IT技术中,实现乐观锁大多数是基于数据版本(version)来进行实现的,也就是对数据增加一个版本标识。
在基于数据库表的版本version解决方案中,一般是通过为数据库表增加一个”version”列,来实现读取出数据时将此version版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。
Redis中可以使用watch命令来监视给定的key,当执行exec的时候,如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。
注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了exec,discard,unwatch命令都会清除连接中的所有监视。

(20)介绍一下在Redis中实现乐观锁的步骤

在Redis中实现乐观锁的原理:使用watch监视一个key的值是否发生改变。
比如有两个客户端A和B,还有key为mykey,value为oldvalue。
(1)A客户端使用watch对mykey的值oldvalue进行监视
(2)A客户端执行MULTI
(3)A客户端执行set x xx
(4)A客户端执行set y yy
(5)B客户端set mykey newvalue
(6)A客户端执行EXEC时发现mykey的值已经由oldvalue改成newvalue,说明mykey的值被B客户端所更改。
(7)A客户端回滚事务,不再提交

(21)介绍一下Redis中的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值