使用场景
什么是缓存穿透?怎么解决?
- 大量的请求去查询一个不存在的数据,每次请求都查数据库
- 布隆过滤器:底层首先初始化一个比较大的数组,里面存放0/1。在一开始为0,当一个key经过三次hash计算, 找到数据下标然后把0修改为1。通过三个数据的位置来标明一个key是否存在
- 缺点:会产生误判
什么是缓存击穿 ? 怎么解决?
- 给一个key设置了过期时间,恰好在过期时间时有大量的并发请求访问这个key,这些并发请求可能会导致DB宕机
- 互斥锁:当缓存失效时,使用互斥锁来确保只有一个请求能够访问数据库,其他请求会获取锁失败,找到数据被重新加载到缓存中
- 设置逻辑过期时间:设置key的时候,设置一个过期时间的字段存入缓存,当查询的时候,检测时间是否过期,如果过期则新开一个线程进行数据同步,当前线程返回数据(不是最新的)
什么是缓存雪崩 ? 怎么解决 ?
- 同一时间缓存中大量的key同时失效,导致大量请求到达数据库
- 给不同的key添加随机的过期时间
- 给业务添加多级缓存
redis作为缓存,mysql的数据如何与redis的数据进行同步的?(双写一致)
- 双写一致是指数据库的数据发生了修改要同步更新缓存的数据
- 可以采用redisson实现的读写锁:在读的时候添加共享锁,可以保证读不互斥,读写互斥。在写数据的时候添加排他锁,它能保证读写和读读互斥,这样可以保证在进行写操作时不会让其他线程读数据。
那这个排他锁是如何保证读写、读读互斥的呢?
- 排他锁底层使用也是setnx,保证了同时只能有一个线程持有锁
你听说过延时双删吗?为什么不用它呢?
- 如果是写操作,先删除缓存中的数据,然后更新数据库,最后在延时删除缓存中的数据。由于延迟时间不好确定,在延时过程中有可能会出现脏读
redis做为缓存,数据的持久化是怎么做的?
可以通过RDB和AOF进行持久化
RDB:
- 是默认的持久化方式。定期的将内存中的数据保存到磁盘上的RDB文件当中。当redis宕机后通过该文件来恢复数据
AOF:
- 是将Redis所有的写命令记录到一个日志文件当中。当redis宕机后通过该文件的命令来恢复数据
这两种方式,哪种恢复的比较快呢?
- RDB因为是二进制文件,恢复速度较快,但是有数据丢失的风险
- 虽然AOF恢复的速度慢一些,但是它丢数据的风险要小很多
Redis中数据过期后,其删除策略有哪些?
- 惰性删除:设置key过期时间后,不去管它,当需要该key时去检查其是否过期,如果过期就将它删除
- 定期删除:每隔一段时间,去检查key,对过期的key进行删除
Redis的数据淘汰策略有哪些 ?
- noeviction(默认):不删除任何数据,内存不足直接报错
- LRU:最近最少用。(在redis配置文件中配置)
- LFU:最少频率使用
数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的 数据都是热点数据 ?
- 可以使用LRU数据淘汰策略:将最近最少使用的数据淘汰,留下来的就是热点数据
Redis的内存用完了会发生什么?
- 这个取决于采用的那种数据淘汰策略,如果是默认的,将会报错,如果是LRU会留下热点数据LFU会留下频率较高的数据
Redis分布式锁如何实现 ?
- Redis中提供了一个命令setnx,该命令只允许一个客服端对某一个key设置值,在没有过期或者删除key的时候其他客服端是不能设置该key的。
- 但是redis的setnx指令不好控制锁的有效时长,所以可以采用redisson来实现redis分布式锁
Redisson实现分布式锁?
- Redisson中需要手动加锁,并且可以控制锁的失效时间和等待时间。当锁住的业务还没有执行完成时,redisson会提供一个看门狗机制,每隔一段时间(10s)就会检测当前业务是否还持有锁,如果持有就增加持有时间(releaseTime/3),当业务执行完释放锁即可。如果在一个业务持有锁另一个业务也来获取锁时,不会立刻被拒绝,而是不停地自旋尝试获取锁
Redisson实现分布式锁是可重入的吗?
- 可重入锁是指一个线程可以多次获取同一把锁,而不会发生死锁。Redisson 的分布式锁支持可重入的主要原理是使用了 ThreadLocal 来存储当前线程已经获取锁的次数。当线程再次尝试获取锁时,Redisson 会检查当前线程是否已经持有该锁,如果是则增加锁的持有计数.
redisson实现的分布式锁能解决主从一致性的问题吗?
- 不能
- 分布式锁主要确保在多个节点上同时操作共享资源的数据一致性和正确性。
- 而主从不一致是指由于主节点和从节点之间的数据同步延迟等原因,可能会导致主节点和从节点数据不一致问题。
- 比如当主节点执行写操作后,尚未同步到从节点之前,主节点宕机了,这时从节点可能不具备最新的数据。
- 可以使用红锁来解决上述问题。红锁:不能只在一个redis实例上上锁,应该在多个redis实例上创建锁(n/2+1)。但是加锁成功后需要在多个节点上进行加锁,其效率就会变差,所以在项目中很少使用红锁
如果业务非要保证数据的强一致性,这个该怎么解决呢?
- 如果业务中非要保证数据的强一致性,建议采用zookeeper实现的分布式锁
其他面试题
Redis集群有哪些方案, 知道吗?
- 主从复制
- 哨兵模式
- 分片集群
介绍一下主从同步?
- 单节点redis并发能力有限,要进一步提高redis并发能力,需要搭建主从集群,来实现读写分离。一般是一主多从,主节点负责写操作,从节点负责读操作
主从同步的具体流程?
主要包含全量同步和增量同步
全局同步:
- 从节点向主节点发送自己id和offset请求数据同步
- 主节点通过id来判断是否是第一次请求,如果是第一次,主节点就把自己的id和offset发送给从节点。同时主节点会执行bgsave命令来生成rdb文件,发送给从节点执行
- 从节点先把自己的数据清空,然后执行reb文件。(要从节点执行过程中,依然有请求到达了主节点,主节点以命令的方式记录到缓冲区(日志文件),最后把这个日志文件发送给从节点,保证主从一致)
增量同步:
- 若不是第一次请求,就获取从节点的offset。主节点只需要发送offset之后的数据即可
怎么保证redis的高并发可用?
- 搭建主从集群+哨兵模式
- 哨兵模式的作用:
- 监控:可用不断的检查你的主从节点是否按期工作
- 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障恢复后也以新master为主
- 通知:当集群发生故障转移时,会将最新信息推送给Redis的客户端
你们使用redis是单点还是集群,哪种集群?
- 我们在项目中时使用的是主从(1主1从)加哨兵。
为什么不采用分片集群?
- 因为分片集群维护起来比较麻烦,并且集群之间的心跳检测和数据通信会消耗大量的网络带宽
redis集群脑裂,该怎么解决呢?
- 脑裂是由于网络等原因,导致系统中的节点分成多个孤立的子集,每个子集都以为自己是整个系统的正常节点,并且可能继续对外提供服务。
- 解决方案:
- 设置最少从节点个数。
- 使用Zookeeper来对集群进行管理和故障恢复
redis的分片集群有什么作用?
- 分片集群主要解决的是,海量数据存储的问题
- 集群中有多个 master,每个master设置多个slave 节点,就可以增大集群的高并发能力。同时每个master之间通过ping监测彼此健康状态,就类似于哨兵模式了。当客户端请求可以访问集群任意节点,最终都会被转发到正确节点
Redis分片集群中数据是怎么存储和读取的?
- Redis 集群引入了哈希槽的概念,集群中每个主节点绑 定了一定范围的哈希槽范围,key通过后对哈希槽取模来决定放置哪个槽,通过槽找到对应的节点进行存储
Redis是单线程的,但是为什么还那么快?
- 完全基于内存的
- 采用单线程,避免不必要的上下文切换可竞争条件
- 使用多路I/O复用模型,非阻塞IO
解释一下I/O多路复用模型?
- 是一种高效的 I/O 模型,通过单个线程同时监听多个I/O 事件,并在事件就绪时进行处理,以提高效率。