Redis相关面试题

什么是布隆过滤器?
布隆过滤器简介
1970 年布隆提出了一种布隆过滤器的算法,用来判断一个元素是否在一个集合中。
这种算法由一个二进制数组和一个 Hash 算法组成。

本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。

相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。

实际上,布隆过滤器广泛应用于网页黑名单系统、垃圾邮件过滤系统、爬虫网址判重系统等,Google 著名的分布式数据库 Bigtable 使用了布隆过滤器来查找不存在的行或列,以减少磁盘查找的IO次数,Google Chrome浏览器使用了布隆过滤器加速安全浏览服务。


什么是缓存穿透?如何解决?
缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题

解决办法;
最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴。

什么是缓存击穿?如何解决?
缓存击穿:当一份访问量非常大的热点数据缓存失效的瞬间,大量的请求直达存储层,导致服务崩溃。
解决方案:
缓存击穿可以通过热点数据不设置过期时间来解决,这样就不会出现上述的问题,这是“物理”上的永不过期。或者为每个数据设置逻辑过期时间,当发现该数据逻辑过期时,使用单独的线程重建缓存。除了永不过期的方式,我们也可以通过加互斥锁的方式来解决缓存击穿,即对数据的访问加互斥锁,当一个线程访问该数据时,其他线程只能等待。这个线程访问过后,缓存中的数据将被重建,届时其他线程就可以直接从缓存中取值。

什么是缓存雪崩?如何解决?
我们可以简单的理解为:由于原有缓存失效,新缓存未到期间 (例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成
整个系统崩溃。

解决办法: 大多数系统设计者考虑用加锁( 最多的解决方案)或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时将缓存失效时间分散开。

Redis存储字符串,最大不能超过少?
Redis中用int来修饰字符串字段,int为4个字节,也就是32位,那么最大能表示2^32
次方。所以2^32/8/1024/1024=512M

Redis 集群最大节点个数是多少?
Redis 集群最大节点个数是16384,这个是一个死的限定

Redis主要消耗什么物理资源?
redis是基于内存数据,主要消耗内存资源

Redis中对象的回收使用的是什么算法?
由于Redis是使用ANSI C语言编写的,C语言本身并没有具备自动的内存回收机制,因此Redis自己做了一套针对对象的内存回收系统----通过使用 引用计数(reference counting ) 来使程序在正确的时机自动释放对象并进行内存回收

什么情况下可能会导致Redis 阻塞?
redis 产生阻塞的原因主要有内部和外部两个原因导致:

内部原因
如果 Redis 主机的 CPU 负载过高,也会导致系统崩溃;
数据持久化占用资源过多;
对Redis 的 API 或指令使用不合理,导致 Redis 出现问题。
外部原因
外部原因主要是服务器的原因,例如服务器的 CPU 线程在切换过程中竞争过大,内存出现问题、网络问题等。
Redis有哪些高级功能?
Redis有消息队列、事务、数据持久化、分布式锁、慢查询、 sentinel、集群等多项高级功能

怎么提高缓存命中率?
提前加载数据到缓存中;
分析热点数据,优先访问最好的数据进缓存
调整缓存的存储数据类型;
提升缓存的更新频率。
RDB的持久化是如何触发的?
RDB 的持久化触发方式有两类:一类是手动触发,另一类是自动触发。

手动触发(执行 save 或者 bgsave 命令)
手动触发持久化的操作有两个命令: save 和 bgsave ,它们主要区别体现在:是否阻塞 Redis 主线程的执行。
save命令
redis 127.0.0.1:6379> SAVE
在客户端中执行 save 命令,就会触发 Redis 的持久化,但同时也是使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令

自动触发
自动触发的含义就是不用我们手动命令去触发持久化,而是通过配置当满足某一规则的时候自动去执行 bgsave 命令。
Redis的配置文件就默认设置了3个保存点:
– 900秒内有1个key发生了变化,则触发保存RDB文件
save 900 1
– 服务器在300秒之内被修改了10次
save 300 10
– 服务器在60秒之内被修改了10000次
save 60 10000

Redis设计分布式锁,要注意以下哪些问题?
互斥性。在任何时刻,只有一个客户端能持有。
不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁
Redis有哪些适合的场景?
会话缓存(Session Cache):最常用的一种使用 Redis 的情景是会话缓存(sessioncache),用 Redis 缓存会话比其他存储(如Memcached)的优势在于:Redis 提供持久化

排行榜/计数器:Redis 在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使得我们在执行这些操作的时候变的非常简单,Redis 只是正好提供了这两种数据结构

Redis的持久化有哪几种?
Redis 提供两种持久化机制 RDB 和 AOF 机制:

RDB 持久化方式是指用数据集快照的方式半持久化模式)记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复

AOF持久化是指所有的命令行记录以 Redis 命令请求协议的格式完全持久化存储,保存为 AOF 文件

Redis 有哪几种数据淘汰策略?
Redis支持一下的内存淘汰策略:

noeviction:当内存达到限制返回错误,并且客户端尝试执行会让更多内存被使用的命令。
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
Redis与Memcache有哪些区别?
存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,redis可以持久化其数据。

redis提供list,set,zset,hash等数据结构的存储、memcached所有的值均是简单的字符串

redis内部执行命令是单线程。

单线程的redis为什么这么快?
纯内存操作

单线程操作,避免了频繁的上下文切换

采用了非阻塞I/O多路复用机制

pipeline 有什么好处,为什么要用 pipeline?
使用 pipeline(管道)的好处在于可以将多次 I/O 往返的时间缩短为一次,但是要求管道中执行的指令间没有因果关系。
用 pipeline 的原因在于可以实现请求/响应服务器的功能,当客户端尚未读取旧响应时,它也可以处理新的请求。如果客户端存在多个命令发送到服务器时,那么客户端无需等待服务端的每次响应才能执行下个命令,只需最后一步从服务端读取回复即可。

Redis6.0之前为什么一直不使用多线程?
Redis主要受限于内存和网络。例如在一个普通的Linux系统上,Redis通过使用pipelining每秒可以处理100万个请求,所以如果应用程序主要使用O(N)或O(log(N))的命令,它几乎不会占用太多CPU,而线程的切换换占用大量的CPU,所以说不会占用太多的CPU。
使用了单线程后,可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。Redis通过AE事件模型以及IO多路复用等技术,处理性能非常高,因此没有必要使用多线程。单线程机制使得 Redis 内部实现的复杂度大大降低,Hash 的惰性 Rehash、Lpush 等等,“线程不安全” 的命令都可以无锁进行。
Redis如何禁用RDB的持久化
配置文件设置

config set save ""
1
Redis持久化有两种,那应该怎么选择呢?
不要仅仅使用 RDB ,因为那样会导致你丢失很多数据。
也不要仅仅使用 AOF ,因为那样有两个问题:第一,你通过 AOF 做冷备,但是没有 RDB 做冷备的恢复速度更快; 第二, RDB 每次简单粗暴生成数据快照,更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug 。
Redis 支持同时开启开启两种持久化方式,我们可以综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。
如果同时使用 RDB 和 AOF 两种持久化机制,那么在 Redis 重启的时候,会使用 AOF 来重新构建数据,因为 AOF 中的数据更加完整。

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

为什么Redis在持久化的时候用子进程?为什么不用后台线程的方式?为什么后台处理(如异步删除任务)用要后台线程?
用子进程主要是从数据的复制去考虑的,当数据被修改时会触发写时复制子进程,会复制父进程被修改的数据页。

而任务处理是用BIO的方式进行的,后台数据可以用内存共享的方式来处理数据,不用拷贝数据。

为什么主从库间的复制不使用 AOF?
RDB 文件是二进制文件,无论是要把 RDB 写入磁盘,还是要通过网络传输 RDB,IO效率都比记录和传输 AOF 的高。
在从库端进行恢复时,用 RDB 的恢复效率要高于用 AOF。
为什么AOF要先把命令追加到缓冲区(AOF_BUf)中?
Redis是使用单线程响应命令,如何每次写入文件命令都直接追加到磁盘,性能会受很大影响。

如果使用缓冲区,redis提供多种缓冲区策略,在性能和安全性方面做平衡

为什么Redis的操作是原子性的,怎么保证原子性的?
对于Redis而言,命令的原子性指的是:

一个操作的不可以再分,操作要么执行,要么不执行。

Redis的操作之所以是原子性的,是因为Redis是单线程的。

Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。

多个命令在并发中也是原子性的吗? 不一定, 将get和set改成单命令操作,incr 。

使用Redis的事务,或者使用Redis+Lua==的方式实现.

使用Redis如何设计分布式锁?
方案一:SETNX + EXPIRE
方案二:SETNX + value值是(系统时间+过期时间)
方案三:使用Lua脚本(包含SETNX + EXPIRE两条指令)
方案四:SET的扩展命令(SET EX PX NX)
方案五:SET EX PX NX + 校验唯一随机值,再释放锁
方案六: 开源框架~Redisson
方案七:多机实现的分布式锁Redlock

可以看一下这篇博客
https://www.cnblogs.com/wangyingshuo/p/14510524.html

Redis官方为什么不提供 Windows 版本?
因为目前 Linux 版本已经相当稳定,而且用户量很大,无需开发 windows 版本,反而会带来兼容性等问题。

操作系统机制的轮询是不太一样的。linxu轮询用epoll,window 用selector

但是性能上来说 epoll是高于selector 的。所以redis推荐使用linux版本。

什么是 bigkey?会存在什么影响?
bigkey 是指键值占用内存空间非常大的 key。例如一个字符串 a 存储了 200M 的数据。
bigkey 的主要影响有:
网络阻塞:获取 bigkey 时,传输的数据量比较大,会增加带宽的压力。
超时阻塞:因为 bigkey 占用的空间比较大,所以操作起来效率会比较低,导致出现阻塞的可能性增加。
导致内存空间不平衡:一个 bigkey 存储数据量比较大,同一个 key 在同一个节点或服务器中存储,会造成一定影响。

Redis 内存不足怎么处理?
修改配置文件 redis.conf 的 maxmemory 参数,增加 Redis 可用内存;
设置缓存淘汰策略,提高内存的使用效率;

说说Redis哈希槽的概念?
Redis 集群并没有使用一致性 hash,而是引入了哈希槽的概念。Redis 集群有 16384(2^14)个哈希槽,每个key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分hash 槽。

Redis6.0为什么要引入多线程呢?
Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,对于小数据包,Redis服务器可以处理80,000到100,000 QPS,这也是Redis处理的极限了,对于80%的公司来说,单线程的Redis已经足够使用了。

但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的QPS。常见的解决方案是在分布式架构中对数据进行分区并采用多个服务器,但该方案有非常大的缺点,例如要管理的Redis服务器太多,维护代价大;某些适用于单个Redis服务器的命令不适用于数据分区;数据分区无法解决热点读/写问题;数据偏斜,重新分配和放大/缩小变得更加复杂等等。

为什么 Redis 要缓存系统时间戳
我们平时使用系统时间戳时,常常是不假思索地使用System.currentTimeInMillis或者time.time()来获取系统的毫秒时间戳。Redis不能这样,因为每一次获取系统时间戳都是一次系统调用,系统调用相对来说是比较费时间的,作为单线程的Redis承受不起,所以它需要对时间进行缓存,由一个定时任务,每毫秒更新一次时间缓存,获取时间都是从缓存中直接拿。

讲一讲Redis中的HyperLogLog?
HyperLogLog可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等。
比如一个爆款页面几千万的 UV,如果使用set集合来统计,1个月的存储会占到2.4G,而HyperLogLog只需要450k的存储。
HyperLogLog基于概率论中伯努利试验并结合了极大似然估算方法,并做了分桶优化。

Redis中的Key和Value是使用全局哈希表组织存储,底层实现是数组,那么Redis是如何解决数组扩容带来的阻塞问题?
Redis 采用了渐进式 rehash。
首先、Redis 默认使用了两个全局哈希表:哈希表 1 和哈希表 2。一开始,当你刚插入数据时,默认使用哈希表 1,此时的哈希表 2 并没有被分配空间。随着数据逐步增多,Redis 开始执行 rehash。
1、给哈希表 2 分配更大的空间,例如是当前哈希表 1 大小的两倍
2、把哈希表 1 中的数据重新映射并拷贝到哈希表 2 中
3、释放哈希表 1 的空间
在上面的第二步涉及大量的数据拷贝,如果一次性把哈希表 1 中的数据都迁移完,会造成 Redis 线程阻塞,无法服务其他请求。此时,Redis 就无法快速访问数据了。
在Redis 开始执行 rehash,Redis仍然正常处理客户端请求,但是要加入一个额外的处理:
处理第1个请求时,把哈希表 1中的第1个索引位置上的所有 entries 拷贝到哈希表 2 中
处理第2个请求时,把哈希表 1中的第2个索引位置上的所有 entries 拷贝到哈希表 2 中
如此循环,直到把所有的索引位置的数据都拷贝到哈希表 2 中。
这样就巧妙地把一次性大量拷贝的开销,分摊到了多次处理请求的过程中,避免了耗时操作,保证了数据的快速访问。
所以这里基本上也可以确保根据key找value的操作在O(1)左右。
————————————————
版权声明:本文为CSDN博主「硕风和炜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Coder_ljw/article/details/128536607

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Redis相关面试题涵盖了以下几个方面: 1. Redis的基本概念和特性:面试官可能会问到你对Redis的理解和熟悉程度。你可以回答Redis是一个开源的内存键值存储系统,具有高性能和持久化能力。它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合等。 2. Redis的数据持久化方式:Redis提供了两种方式来将数据持久化到磁盘上,分别是RDB(Redis Database)和AOF(Append Only File)。RDB是一种快照方式,可以将数据以二进制形式保存到硬盘上,而AOF则是将每个写操作追加到文件末尾。你可以解释一下这两种方式的优缺点,并说明在不同场景下应该选择哪种方式。 3. Redis的线程模型:在Redis 6.0之前,Redis是单线程的。而在Redis 6.0之后开始支持多线程。Redis内部使用基于epoll的多路复用来处理网络IO,而执行命令的核心模块仍然是单线程的。你可以简要介绍一下Redis的线程模型以及引入多线程的原因。 4. Redis的扩展模块:Redis支持通过扩展模块来增加额外的功能。例如,BloomFilter、RedisSearch和Redis-ML等扩展模块可以用于实现不同的功能需求。你可以提到一些常用的Redis扩展模块,并解释一下它们的作用和用途。 总结起来,面试中关于Redis问题主要包括对Redis的基本概念和特性的理解、数据持久化方式、线程模型以及扩展模块的使用等方面。通过对这些问题的了解和回答,可以展示出你对Redis的熟悉程度和实际应用能力。同时,你还可以结合自己的经验和实际项目,给出一些实际的应用场景和解决方案,从而更好地回答面试官的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [面试 Redis 没底?这 40 道面试题让你不再慌(附答案)](https://blog.csdn.net/xmt1139057136/article/details/115423283)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [redis面试题总结(附答案)](https://blog.csdn.net/guorui_java/article/details/117194603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值