redis面试题(持续更新)
Posted 小黄鸡1992
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis面试题(持续更新)相关的知识,希望对你有一定的参考价值。
1.为什么使用redis
大量的数据请求可能造成数据库的宕机(如秒杀,热点数据,),redis是使用内存存贮,每秒的运行次数可以达到10w+,可以减少数据库的压力。
2.Redis有哪些数据结构?
String、Hash、List、Set、SortedSet。
3.如果有大量的key需要设置同一时间过期,一般需要注意什么?
要设置随机的过期时间,否则造成雪崩。
4.Redis分布式锁怎么实现?
使用set语法,加入jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
也可以用setnx然后在使用expire设置过期时间,但是如果在setnx后服务挂掉了,就会造成死锁。
5.假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?
使用keys指令。
6.如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。
7.Redis怎么做异步队列?
使用rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
8.可不可以不用sleep呢?
list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
9.能不能生产一次消费多次呢?
使用pub/sub主题订阅者模式,可以实现 1:N 的消息队列。
10.pub/sub有什么缺点?
在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如RocketMQ等。
11.Redis如何实现延时队列?
使用zset score放入要延时的时间 ,然后使用rangebyscore轮询获取。
12.能不能生产一次消费多次呢?
使用pub/sub。
redisTemplate.convertAndSend(“testkafka”, data); 放入队列。
13.缓存雪崩,缓存击穿,缓存穿透?
请参考上文。
14.怎么保持系统高可用?
Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
本地 ehcache 缓存 + Hystrix 限流+降级,避免** mysql** 被打死。
Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
15.Redis是怎么持久化的?服务主从数据怎么交互的?
请参考上文。
16.是否使用过Redis集群,集群的高可用怎么保证,集群的原理是什么?
Redis Cluster:主要为扩展分片 当内存不足使用Cluster扩展。
Redis Sentinal:高可用,当主机死掉后选举从机为主机。
17.Redis的同步机制?
首先进行RDB全局持久化存放于内存,然后将RDB文件发送给从机,同时,在接下来使用AOF逐步同步。
18.Pipeline有什么好处,为什么要用pipeline?
redis管道,可以将多次请求放于pipeline,然后一起读取出来,这样可以增加redis吞吐量。
19.缓存有哪些类型?
-
本地缓存就是在进程的内存中进行缓存,比如我们的 JVM 堆中,可以用 LRUMap 来实现,也可以使用 Ehcache 这样的工具来实现。本地缓存是内存访问,没有远程交互开销,性能最好,但是受限于单机容量,一般缓存较小且无法扩展。
-
分布式缓存一般都具有良好的水平扩展能力,对较大数据量的场景也能应付自如。缺点就是需要进行远程请求,性能不如本地缓存。
-
为了平衡这种情况,实际业务中一般采用多级缓存,本地缓存只保存访问频率最高的部分热点数据,其他的热点数据放在分布式缓存中。
20.淘汰策略?
不管是本地缓存还是分布式缓存,为了保证较高性能,都是使用内存来保存数据,由于成本和内存限制,当存储的数据超过缓存容量时,需要对缓存的数据进行剔除。
一般的剔除策略有 FIFO 淘汰最早数据、LRU 剔除最近最少使用、和 LFU 剔除最近使用频率最低的数据几种策略。
-
noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
-
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
-
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
-
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
-
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
-
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。
21.怎么解决redis瓶颈?
使用Redis cluster,主从同步读写分离,类似Mysql的主从同步,Redis cluster 支撑 N 个 Redis master node,每个master node都可以挂载多个 slave node。
22.主从同步,能说一下主从之间的数据怎么同步的么?
你启动一台slave 的时候,他会发送一个psync命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。
23.Redis的过期策略?
是有定期删除+惰性删除两种。
- 定期好理解,默认100ms就随机抽一些设置了过期时间的key,去检查是否过期,过期了就删了。
- 惰性策略:请求时判断是否过去。
24.为啥不扫描全部设置了过期时间的key呢?
假如Redis里面所有的key都有过期时间,都扫描一遍?那太恐怖了,而且我们线上基本上也都是会设置一定的过期时间的。全扫描跟你去查数据库不带where条件不走索引全表扫描一样,100ms一次,Redis累都累死了。
25.如果一直没随机到很多key,里面不就存在大量的无效key了?
好问题,惰性删除,见名知意,惰性嘛,我不主动删,我懒,我等你来查询了我看看你过期没,过期就删了还不给你返回,没过期该怎么样就怎么样。
26.数据传输的时候断网了或者服务器挂了怎么办啊?
传输过程中有什么网络问题啥的,会自动重连的,并且连接之后会把缺少的数据补上的。
27.如果你多个系统同时操作(并发)Redis带来的数据问题?
如果第一个请求网络延迟了 可能覆盖之后的请求,造成数据不一致
28.这样应该怎么办 ?
1 使用分布式锁
2 输入时加入时间戳 通过时间戳判断
29.数据一致性问题怎么解决?
在不要求效率的情况下,可以放入队列中。 但是会引起阻塞。
30.你了解最经典的KV、DB读写模式么?
读缓存 ,缓存没有读db,保存到缓存
更新 先更新数据库在删除缓存
31.为什么是删除缓存,而不是更新缓存?
缓存来源不一定是一个操作,而且如果多次操作db,同时多次操作db同时多次更新缓存会造成很多冷数据。
32.Redis 的线程模型了解么?
Redis 内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 Socket,根据 Socket 上的事件来选择对应的事件处理器进行处理。
文件事件处理器的结构包含 4 个部分:
多个 Socket
IO 多路复用程序
文件事件分派器
事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个 Socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 Socket,会将 Socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
33.缓存的问题
1.数据不一致
第二个问题是数据不一致的问题,可以说只要使用缓存,就要考虑如何面对这个问题。缓存不一致产生的原因一般是主动更新失败,例如更新 DB 后,更新 Redis 因为网络原因请求超时;或者是异步更新失败导致。
解决的办法是,如果服务对耗时不是特别敏感可以增加重试;如果服务对耗时敏感可以通过异步补偿任务来处理失败的更新,或者短期的数据不一致不会影响业务,那么只要下次更新时可以成功,能保证最终一致性就可以。
2.部署
比如 Redis 是单线程处理请求,应尽量避免耗时较高的单个请求任务,防止相互影响;Redis 服务应避免和其他 CPU 密集型的进程部署在同一机器;或者禁用 Swap 内存交换,防止 Redis 的缓存数据交换到硬盘上,影响性能。
以上是关于redis面试题(持续更新)的主要内容,如果未能解决你的问题,请参考以下文章