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简历中项目的功能进行提问,大家可以在评论区中解答/讨论;同时提供八股文