Redis面试题

Redis特性

数据类型丰富;支持数据磁盘持久化;支持主从同步;支持分片

Redis为什么这么快

完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高

数据结构简单,对数据操作也简单

采用单线程,单线程也能处理高并发请求,想多核也可启动多实例

使用多路I/O复用模型,非阻塞IO

从海量的key中查询出某一固定前缀的key?

首先摸清数据规模

使用keys指令,可能会造成当前服务阻塞

使用scan 0 match k1* count 10,从下标0开始获取k1前缀开头的key,获取10条数据,返回结果集包含到达的下标,以及返回的key结果集

基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程

以0作为游标开始一次新的迭代,直到命令返回游标0完成一次遍历

不保证每次执行都返回某个给定数量的元素,支持模糊查询

一次返回的数量不可控,只能是大概率符合count参数

如何通过Redis实现分布式锁?

分布式锁需要解决的问题?

互斥性:任何时候只能被一个客户端拥有

安全性:只能由被占用的客户端删除

死锁:获取锁的客户端因为某些原因宕机,而未能释放锁。其他客户端不能再获取锁,而导致死锁

容错:当redis节点出现错误或者宕机,客户端依然能获取锁和释放锁【在redis集群中,假设当前访问的redis节点宕机,则客户端先进行解锁操作,向所有的redis节点发送解锁命令,然后重新获取锁,完成业务操作】

set key value [EX seconds] [PX milliseconds] [NX|XX]

EX second:设置键的过期时间为second秒

PX millisecond:设置键的过期时间为millisecond毫秒

NX:只在键不存在时,才对键进行设置操作

XX:只在键已经存在时,对键进行设置操作

SET操作成功完成时,返回OK,否则返回nil

首先通过set key value ex nx设置,只有键不存在时,对key进行操作。如果不存在,则进行加锁操作,value是访问客户端的ID,设置超时时间防止死锁;如果存在则判断value值是否一致,如果不一致则获取key的有效时间,继续等待,每隔一段时间进行访问,直到获取成功;如果存在则重复获取锁,并且记录获取锁的次数,释放锁的时候,需要判断是否是同一个客服端ID,并且只有当获取锁的次数为0时,才可以删除锁,防止外层业务没有锁,导致安全问题

大量的key同时过期的注意事项

集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象

解决方案:在设置key的过期时间的时候,给每个时间加上随机值

如何使用redis做异步队列

1.使用List作为队列,RPUSH生产消息,LPOP消费消息

缺点:不会等待队列里有值才去消费

弥补:可以通过在应用层引入sleep机制去调用LPOP重试

2.BLPOP key timeout:阻塞直到队列有消息或者超时

缺点:只能供一个消费者消费

3.pub/sub:主体订阅者模式

发布者(pub)发送消息,订阅者(sub)接收消息

订阅者可以订阅任意数量的频道

缺点:消息的发布是无状态的,无法保证送达

Redis如何实现持久化

AOF持久化(保存写状态):

记录下除查询以外的所有变更数据库状态的指令

以append的形式追加保存到AOF文件中【增量】

将Reids的操作日志以追加的方式写入文件

日志重写解决AOF文件大小不断增大的问题,原理如下:

随着AOF文件越来越大,里面会有大部分是重复命令或者可以合并的命令

重写的好处:减少AOF日志尺寸,减少内存占用,加快数据库恢复时间

A.调用fork()创建一个子进程

B.子进程把新的AOF写到一个临时文件里,不依赖原来的AOF文件

C.主进程持续将新的变动同时写到内存和原来的AOF里

D.主进程获取子进程重写AOF的完成信号,往新的AOF同步增量变动

E.使用新的AOF文件替换掉旧的AOF文件

redis首先fork()去产生一个子进程,子进程把新的AOF文件写到一个临时文件里,新的AOF的重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析或者进行命令的合并。主进程持续把新的变动写到内存里的buffer,同时也会把这些新的变动写到旧的AOF里面,这样即使重写失败也能保证数据的安全。当子进程完成文件的重写之后,主进程会获得一个信号,然后把内存里的buffer追加到子进程生成的新的AOF文件里。之后用新的AOF文件替换掉原先的AOF文件,这样就完成了一次日志重写的整个过程

子进程在做AOF重写时,会通过管道从父进程读取增量数据并缓存下来,在以RDB格式保存全量数据时,也会从管道读取数据,同时不会造成管道的阻塞。也就是说AOF文件的前半段是RDB格式的全量数据,而后半段是redis命令格式的增量数据。

RDB持久化:在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java之项目解析+八股文 文章被收录于专栏

针对Java简历中项目的功能进行提问,大家可以在评论区中解答/讨论;同时提供八股文

全部评论
redis基础到进阶很全了
点赞 回复
分享
发布于 02-27 19:19 浙江

相关推荐

2 16 评论
分享
牛客网
牛客企业服务