目录
前言
这个公众号运营了一年多了(算上自己摆烂的那大半年),跟大家分享过运维人员是如何排查定位问题的,也分享过自己的一些学习笔记
今天打算新开一个系列,叫《对线面试官》(暂时就想到这个名字)
今天打算新开一个系列,叫**《对线面试官》**(暂时就想到这个名字)
在《对线面试官》里,我会跟大家分享一下校招面试过程中面试官比较爱问的问题
这些面试题虽然比较基础,但是涉及的知识面比较广,很能体现出面试人的技术水准以及能否对自己所学的知识加以思考与总结
当然也不缺乏一些深度的面试题,要是在面试过程中全部对答如流的话是很加分的哦!
废话不多说,开始《对线面试官》系列的第一篇文章!
(PS:最近忙着准备转正答辩,文章更新速度会放缓一下下)
百分之99面试官都爱问的 Redis 面试题
1、谈下你对 Redis 的了解
Redis 是一个用 C 语言编写的、开源的 key-value 数据库
Redis 运行在内存中,所以处理数据的速度非常快,同时 Redis 还支持数据的持久化,将内存中的数据 保存在磁盘
2、Redis适用于哪些场景?不适用于哪些场景?
适用的场景:
- 会话缓存:减轻后端 sql 数据库的 IO 压力,提升系统性能
- 排行榜:利用 sortset(有序集合)可以排序且不能有重复数据的特性来实现
- 消息队列:redis 支持生产者/消费者模式、发布者/订阅者模式的消息队列
不适用场景:
- 数据量太大的业务场景,内存成本大
- 数据访问频率非常低的业务场景,浪费内存资源
3、Redis 支持的数据类型有哪些?
- string(字符串)
字符串类型是redis最基础的数据结构,而且其他集中数据结构都是在字符串类型基础上构建的 - Hash(哈希)
Redis中哈希类型是指键本身是一种键值对结构 - List(列表)
列表(list)类型是用来存储多个有序的字符串,是一种线性结构可以充当栈和队列的角色 - Set(集合)
集合(set)类型也是用来保存多个的字符串元素,集合中不允许有重复出现的元素 集合的元素是无序的,不能够通过下标来获得值 - zset(即sotred set:有序集合)
有序集合保留了集合不能有重复成员的特性,不同的是有序集合中的元素是可以排序的。和列表使用索引下标作为排序依据不同的是它给每个元素设置一个分数(score)作为排序的依据
4、既然Redis是单线程架构,但为什么这么快?
1、Reids 的数据都是存放在内存中的,绝大部分请求都是对内存进行操作,所以非常快
2、Redis 采用 epoll 作为 I/O 多路复用技术的实现,结合非阻塞 I/O 模型
3、除此之外,Redis 的自身事件处理模型将 epoll 中的连接、读写、关闭都转换成一个个事件,因此不会在网络 I/O 上浪费过多时间
4、Redis 的单线程架构避免了不必要的因上下文切换、多线程资源竞争所导致的资源消耗,更加快速
5、什么是缓存穿透?怎么解决?
- 缓存穿透
是指当去查询一个不存在的数据时,会因为缓存不命中而去数据库中查询
如果出现高并发的去查询一个不存在的数据,就会导致这个不存在的数据每次请求都会到数据库中查询,造成缓存穿透
PS:穿透,相当于穿过 Redis 直接打到后端数据库上 - 解决方法
1、将空数据缓存
如果查询一个数据返回了空值(不管是数据不存在的原因还是系统故障的原因),仍然把这个空结果缓存起来,并设置过期时间
2、布隆过滤器
将所有可能存在的数据哈希到一个足够大的bitmap 中,一定不存在的数据会被这个 bitmap 直接拦截掉,从而避免对数据库的查询
6、什么是缓存雪崩?该如何解决?
- 缓存穿透
是指数据缓存在某一段时间内集中失效,发生了大量的缓存穿透,导致所有的查询请求都打到数据库上,造成了缓存雪崩 - 解决方法
1、加锁排队
缓存失效后,通过加锁或者队列来控制对数据库进行操作的线程数量,从而避免数据库压力过大
2、数据预热
通过缓存 reload 机制,预先刷新缓存,在即将发生大并发访问前手动触发缓存,并设置不同的过期时间
3、二级缓存(双缓存)策略
Cache1 为原始缓存,Cache2 为拷贝缓存,Cache1 失效时,可以访问 Cache2,Cache1 缓存失效时间设置为短期,Cache2 设置为长期
4、其他
除此之外,还可以在缓存的时候给过期时间加上一个随机值,这样就会大幅度地减少缓存在同一时间过期
7、Redis 持久化机制有哪几种
Redis 是将数据运行在内存中的,如果出现服务挂掉或者服务器宕机都可以导致数据全部丢失
为了解决 这个问题 redis 提供了两种数据持久化机制——RDB、AOF
RDB
- RDB 是 Redis DataBase 的缩写
- RDB 按照一定时间间隔把内存中的数据以快照的形式(dump.rdb)保存到磁盘中
- 触发 RDB 持久化过程为手动触发和自动触发
- 手动触发:save 命令或 bgsave 命令
- 自动触发:配置文件添加 save 字段
AOF
- AOF 是 Append-only file 的缩写
- Redis 会将每一个收到的写命令都追加到 AOF 文件末尾,类似于 MySQL 的 binlog,Reids重启后会通过重新执行 AOF 文件中的写命令来实现数据的恢复
- 通过在配置文件里添加 appendonly yes 字段来开启 AOF
RDB 和 AOF 的区别
- RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中
- 如果 RDB 和 AOF 都配置了,那么优先采用 AOF
- AOF 提供了多种数据同步频率,最多丢失 1 秒的数据而已,RDB是隔一段时间进行持久化,所以说 AOF 的数据安全性要比 RDB 高
- -对于具有相同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大
8、在进行RDB持久化时,Redis 可以处理写请求吗
可以,Redis 使用操作系统的多进程写时复制技术 COW(Copy On Write) 来实现快照持久化,保证数据 一致性
Redis 在 RDB 持久化时会 fork 出一个子进程,由子进程来负责持久化,而父进程继续处理客户端请求
当父进程收到客户端的写请求时,就会将数据复制一份传给子进程,子进程将副本数据写到 RDB 文件里
9、谈谈 Redis 的内存回收机制吧
Redis是基于内存的数据库,常被用作缓存,以此来提高系统的响应速率与性能
因此在一些业务场景中往往会出现 Redis 消耗了大量的内存,导致系统出现性能瓶颈,为此 Redis 提供了内存回收机制(Redis默认采用noeviction策略)
-
volatile-lru:
在设置了过期时间的所有键中,选取最近最少使用的数据删除 -
volatile-lfu:
在设置了过期时间的所有键中,选取最近最不常用,也就是一定时期内被访问次数最少的数据删除 -
volatile-random:
筛选出设置了过期时间的键值对,随机删除。 -
volatile-ttl:
筛选出设置了过期时间的键值对,越早过期的越先被删除。 -
allkeys-lru:
在所有键中,选取最近最少使用的数据删除 -
allkeys-lfu:
在所有键中,选取最近最不常用,也就是一定时期内被访问次数最少的数据删除 -
allkeys-random:
采用随机淘汰策略删除所有的键值对,这个策略不常用。 -
noeviction:
不淘汰任何键值对,当内存满时,如果进行读操作,例如get命令,它将正常工作,而做写操作,它将返回错 误,也就是说,当Redis采用这个策略内存达到最大的时候,它就只能读不能写了
10、谈谈 Redis 的键过期机制吧
除了 Redis 的内存回收机制可以有效解决消耗内存过高的问题
还有一个键过期机制,通过给 key 设置一个过期时间,超过过期时间后 key 就会被删除,内存就被回收
Redis key 过期处理的方式有三种:
- 惰性删除
不管 key 有没有过期都不主动删除,等到每次去获取 key 时再判断是否过期,如果过期就删除该 key ,否则返回 key 对应的值。这种策略对内存不够友好,可能会浪费很多内存
**缺点:**若大量的 key 在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的数据占用了大量的内存) - 定时删除
给 key 设置了过期时间后,会为该 key 创建一个定时器
让定时器在 key 的过期时间来临时, 对 key 进行删除
**缺点:**定时器的创建耗时,若为每一个设置过期时间的 key 创建一个定时器(将会有大量的定时器 产生),性能影响严重,因为每个定时器都会占用一定的 CPU 资源
- 定期删除
系统每隔一段时间就定期扫描一次,发现过期的键就进行删除
以下两种方式可以触发定期删除:
1、配置redis.conf 的 hz 选项,默认为10 (即1秒执行10次,100ms一次,值越大说明刷新频率越快,对 Redis性能损耗也越大)
2、配置内存回收策略,当 Redis 消耗内存达到最大内存使用限制,就会自行对应的策略,来对过期 key 进行删除
在 Redis 当中,其选择的是策略 2 和策略 3 的综合使用
不过 Redis 的定期删除只会扫描设置了过期时间的 key,因为设置了过期时间的键 Redis 会单独存储,所以不会出现扫描所有 key 的情况
11、同一时间大量 key 都过期的话会有什么影响?
- 读写请求响应时间变长
当 key 过期后,内存管理器需要对 key 占用的内存进行回收,会产生一定的 CPU 消耗
大量的 key 过期会导致频繁回收内存,消耗 CPU 资源,导致系统响应变慢 - 缓存雪崩
缓存失效后导致所有的查询操作都落在数据库上,造成了缓存雪崩,甚至严重会导致数据库发生故障
12、slave是怎么实现键过期策略的?
slave 不会进行过期扫描, slave 对过期 key 的处理是被动的
当 master 采用定期或惰性删除过期 key 时,会同步一个 del 操作到 slave,这样 slave 也可以删除过期 key
RDB对过期Key的处理
-
持久化数据到RDB文件
- 持久化之前会检查 key 是否过期,过期的 key 不进入RDB文件
-
从RDB文件恢复数据
- 数据载入数据库之前,会对 key 进行过期检查,如果过期则不导入数据库(主库)
- 如果 RDB 文件里有过期的键,那还是会载入,但是主从在数据同步时(全量复制),slave的数据会被清空(丢弃原先所有数据),所以不影响
AOF对过期Key的处理
- 持久化数据到 AOF 文件
- 如果某个 key 过期,还没有被删除,该 key 是不会进入 aof 文件的,因为没有发生修改命令
- 当 key 过期被删除后,就会向 aof 文件追加一条 del 命令(在将来的以 aof 文件恢复数据的时候该过期的键就会被删掉)
- AOF重写
- 重写时,会先判断 key 是否过期,已过期的 key不会重写到 aof 文件