📒博客首页:崇尚学技术的科班人
🍣今天给大家带来的文章是《面试必备Redis知识 -- Redis面试题(一)》
🍣
🍣希望各位小伙伴们能够耐心的读完这篇文章🍣
🙏博主也在学习阶段,如若发现问题,请告知,非常感谢🙏
💗同时也非常感谢各位小伙伴们的支持💗
👨💻**:简单说一下 redis 是什么。**
👨💻**:比较一下 redis 和 memcached 。**
1)、共同点
2)、不同点
list,set,zset,hash
等数据结构的存储。Memcached 只支持最简单的 k/v 数据类型。👨💻**:听说你在项目中使用到了 redis,说一说你为什么要使用 redis ?**
这里我们统一说一说 redis 的优点
。👨💻**:redis有哪些应用场景 ?**
优化查询性能,减轻 MySQL 压力,提升系统整体性能。
利用Redis的 SortSet
(有序集合)实现
计数器/限速
利用Redis 中原子性的自增操作,我们可以统计类似用户点赞数、用户访问数等。
限速器比较典型的使用场景是限制某个用户访问某个API的频率,常用的有抢购时,防止用户疯狂点击带来不必要的压力
好友关系
利用集合的一些命令,比如求交集、并集、差集等。可以方便解决一些共同好友、共同爱好之类的功能
可以使用 Stream
数据结构进行实现,还有其自身所携带的 发布/订阅模式
。
set + lua 脚本。
session 是保存在服务器的文件中,如果是集群服务,同一个用户过来可能落在不同机器上,这就会导致用户频繁登陆。采用 Redis 保存 Session 后,从 Redis 中查询获取 session 信息,无论用户落在那台机器上都能够获取到对应的 Session 信息。
👨💻**:redis常见的数据结构有哪些 ?**
数据结构 | 介绍 | 常用命令 | 应用场景 |
---|---|---|---|
string | redis 构建了一种 简单动态字符串(SDS),Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出 | set,get,strlen,exists,decr,incr,setex | 一般常用在需要计数的场景,比如用户的访问次数、热点文章的点赞转发数量等 |
list | Redis 的 list 的实现为一个 双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。 | rpush,lpop,lpush,rpop,lrange,llen | 发布与订阅或者说消息队列、慢查询。 |
hash | hash 是一个 string 类型的 field 和 value 的映射表,内部实现也差不多(数组 + 链表)。 | hset,hmset,hexists,hget,hgetall,hkeys,hvals | 系统中对象数据的存储 |
set | Redis 中的 set 类型是一种无序集合,集合中的元素没有先后顺序,同时也不会出现重复数据 | sadd,spop,smembers,sismember,scard,sinterstore,sunion | 需要存放的数据不能重复以及需要获取多个数据源交集和并集等场景 |
sorted set | sorted set 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。 | zadd,zcard,zscore,zrange,zrevrange,zrem | 需要对数据根据某个权重进行排序的场景。比如在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息。 |
👨💻**:redis 是单线程还是多线程的?**
redis 4.0 之前,redis 是完全单线程的。
redis 4.0 时,redis 引入了多线程,但是额外的线程只是用于后台处理。删除对象的时候,核心线程还是单线程的。
redis 6.0 中,多线程主要用于网络 I/O 阶段。
👨💻追问道:redis 为什么是单线程的?
单线程编程容易并且更容易维护
Redis 的性能瓶颈不在 CPU ,主要在内存和网络
多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
👨💻追问道:redis 为什么在 6.0 的时候又引入多线程呢 ?
Redis6.0 引入多线程主要是为了提高网络 IO 读写性能,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。
但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了,执行命令仍然是单线程顺序执行。
👨💻**:redis 过期的 key 删除策略你了解吗?**
👨💻**:redis 内存淘汰机制你了解吗?**
volatile-lru
:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰volatile-ttl
:从已设置过期时间的数据集中挑选将要过期的数据淘汰volatile-random
:从已设置过期时间的数据集中任意选择数据淘汰allkeys-lru
:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)allkeys-random
:从数据集中任意选择数据淘汰no-eviction
:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!volatile-lfu
:从已设置过期时间的数据集中挑选最不经常使用的数据淘汰allkeys-lfu
:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key👨💻**:redis 的几种持久化机制你了解过吗?说一说各自的实现原理和优缺点呗**
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
RDB的优点
RDB 文件是是经过压缩的二进制文件,占用空间很小。
RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
RDB 可以最大化 redis 的性能。父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
RDB的缺点
数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候。
appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec #每秒钟同步一次,显式地将多个写命令同步到硬盘
appendfsync no #让操作系统决定何时进行同步
AOF的优点
AOF 比 RDB可靠,支持秒级持久化,就算发生故障停机,也最多只会丢失一秒钟的数据。
当 AOF文件太大时,Redis 会自动在后台进行重写:重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。当新文件重写完毕,Redis 会把新旧文件进行切换,然后开始把数据写到新文件上。
AOF的缺点
对于相同的数据集,AOF 文件的大小一般会比 RDB 文件大。
RDB 存储的是压缩二进制格式记录数据命令,AOF 是通过文本日志形式记录数据命令,所以采用 AOF 数据恢复比 RDB 慢。
👨💻**:redis 为什么要重写 AOF 文件?**
举个栗子, 如果你对一个计数器调用了 100 次 INCR
, 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录。然而在实际上, 只使用一条 SET
命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。
👨💻**:介绍一下AOF 后台重写存在的问题、如何解决 AOF 后台重写存在的数据不一致问题?**
为了解决上述问题,Redis 引入了 AOF 重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当 Redis 服务器执行完一个写命令之后,它会同时将这个写命令追加到 AOF 缓冲区和 AOF 重写缓冲区。
父进程检测到相关的子进程完成相关的重写工作之后,会进行以下操作:
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_56727438/article/details/123360836
内容来源于网络,如有侵权,请联系作者删除!