redis面试题(一)

1 篇文章 0 订阅

redis面试题(一)❤

1、Redis的高并发和快速原因

1.redis是基于内存的,内存的读写速度非常快;
2.redis是单线程的,省去了很多上下文切换线程的时间;
3.redis使用I/O多路复用技术,可以处理并发的连接。(客户端的连接不占用线程资源,只有当命令成功发送的时候,才会进入单线程,然后依次执行)
解释:多路:多个socket、多个客户端、多个黑窗口
复用:复用那一个线程

在这里插入图片描述

2、为什么Redis是单线程的

官方答案

因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。

3、 Redis单线程的优劣势

  1. 单进程单线程优势 代码更清晰,处理逻辑更简单
  2. 单进程单线程弊端 无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来完善。

4、redis中的数据类型有哪些?

  1. String:字符串类型,一个key对应一个值,可以存储任何内,图片、视频都行,但是大小限制在512m以内
  2. List:一个key对应多个值,值可以重复
  3. set:一个key对应多个值,值不可以重复
  4. Hash:key后面继续跟field属性,从而确定一个值
  5. zSet:有序不重复集合,可以自动排序,一个key对应多个值

5、跳表的原理是什么?

答:跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。跳表不仅能提高搜索性能,同时也可以提高插入删除操作的性能。
rediszset*类型的底层就是用了这种数据结构*

6.redis关键命令

Redis key
1.exists key判断某个key是否存在
2.expire key 10 10秒钟:为给定的key设置过期时间

String
1.setnx key value :只有在key不存在的时候设置key的值
常用来做分布式锁
2.incrby / decrby <步长>将 key 中储存的数字值增减。自定义步长

List
1.lpop/rpop 从左边/右边吐出一个值。值在键在,值光键亡。
2.lrange

Set
1.sadd …
将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
2.smembers 。
3.set类型数据的扩展操作
sinter 返回两个集合的交集元素。
sunion 返回两个集合的并集元素。
sdiff 返回两个集合的差集元素(key1中的,不包含key2中的)
smove value把集合中一个值从一个集合移动到另一个集合

Hash
1.hset 给集合中的 键赋值
2.hget 从集合取出 value
3.hexists 查看哈希表 key 中,给定域 field 是否存在。

Zset
1.zrangebyscore key minmax [withscores] [limit offset count]返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
2…zrevrangebyscore key maxmin [withscores] [limit offset count] 同上,改为从大到小排列。
3.zincrby 为元素的score加上增量
4.zcount 统计该集合,分数区间内的元素个数

7.持久化方式有哪些?有什么区别?

redis持久化方案分为RDB和AOF两种。

RDB:

RDB持久化可以手动执行也可以根据配置定期执行,它的作用是将某个时间点上的数据库状态保存到RDB文件中,RDB文件是一个压缩的二进制文件,通过它可以还原某个时刻数据库的状态。由于RDB文件是保存在硬盘上的,所以即使redis崩溃或者退出,只要RDB文件存在,就可以用它来恢复还原数据库的状态。

可以通过SAVE或者BGSAVE来生成RDB文件。
SAVE命令会阻塞redis进程,直到RDB文件生成完毕,在进程阻塞期间,redis不能处理任何命令请求,这显然是不合适的。
BGSAVE则是会fork出一个子进程,然后由子进程去负责生成RDB文件,父进程还可以继续处理命令请求,不会阻塞进程。

AOF:

AOF和RDB不同,AOF是通过保存redis服务器所执行的写命令来记录数据库状态的。 AOF通过追加、写入、同步三个步骤来实现持久化机制。

1.当AOF持久化处于激活状态,服务器执行完写命令之后,写命令将会被追加append到aof_buf缓冲区的末尾
2.在服务器每结束一个事件循环之前,将会调用flushAppendOnlyFile函数决定是否要将aof_buf的内容保存到AOF文件中,可以通过配置appendfsync来决定。

配置如下:

alwaysaof_buf内容写入并同步到AOF文件
everysec将aof_buf中内容写入到AOF文件,如果上次同步AOF文件时间距离现在超过1秒,则再次对AOF文件进行同步
no将aof_buf内容写入AOF文件,但是并不对AOF文件进行同步,同步时间由操作系统决定

如果不设置,默认选项将会是everysec,因为always来说虽然最安全(只会丢失一次事件循环的写命令),但是性能较差,而everysec模式只不过会可能丢失1秒钟的数据,而no模式的效率和everysec相仿,但是会丢失上次同步AOF文件之后的所有写命令数据。

8.了解Redis事务机制吗?

redis通过MULTI、EXEC、WATCH等命令来实现事务机制,事务执行过程将一系列多个命令按照顺序一次性执行,并且在执行期间,事务不会被中断,也不会去执行客户端的其他请求,直到所有命令执行完毕。事务的执行过程如下:

1.服务端收到客户端请求,事务以MULTI开始
2.如果客户端正处于事务状态,则会把事务放入队列同时返回给客户端QUEUED,反之则直接执行这个命令
3.当收到客户端EXEC命令时,WATCH命令监视整个事务中的key是否有被修改,如果有则返回空回复到客户端表示失败,否则redis会遍历整个事务队列,执行队列中保存的所有命令,最后返回结果给客户端

WATCH的机制本身是一个CAS的机制,被监视的key会被保存到一个链表中,如果某个key被修改,那么REDIS_DIRTY_CAS标志将会被打开,这时服务器会拒绝执行事务。

9.什么是悲观锁?什么是乐观锁?

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。

10.主从复制的原理:

  1. 当从服务器连接上主服务器之后,从服务器就会向主服务器发送一个sync命令进行数据同步操作
  2. 主服务器接到从服务器发过来的同步命令,先将主服务器数据进行持久化,生成rdb文件,然后把rdb文件发送给从服务器,从服务器拿到rdb进行读取,完成复制
  3. 每次主服务器进行写操作之后,和从服务器进行数据同步
  4. 全量复制:从机第一次连接主机,主机所有的数据将会同步给从机。
  5. 增量复制:主机继续将新的数据依次传给从机
  6. 但是只要是重新连接master,全量复制都会自动执行
    在这里插入图片描述

11. 主从复制的三种方式:

  • 方式一:一主多从(从机直接跟随主机)
  • 方式二:薪火相传 (从机可以作为其他机器的主机)
  • 方式三:反客为主 (主机宕机,从机可以通过slaveof no one 变成主机)

12.什么是哨兵机制?哨兵机制的工作原理是什么?

在这里插入图片描述

  1. 基于主从方案的缺点还是很明显的,假设master宕机,那么就不能写入数据,那么slave也就失去了作用,整个架构就不可用了,除非你手动切换,主要原因就是因为没有自动故障转移机制。而哨兵(sentinel)的功能比单纯的主从架构全面的多了,它具备自动故障转移、集群监控、消息通知等功能。
  2. 哨兵可以同时监视多个主从服务器,并且在被监视的master下线时,自动将某个slave提升为master,然后由新的master继续接收命令。
  3. sentinel会每隔1秒向所有实例(包括主从服务器和其他sentinel)发送ping命令,并且根据回复判断是否已经下线,这种方式叫做主观下线。当判断为主观下线时,就会向其他监视的sentinel询问,如果超过半数的投票认为已经是下线状态,则会标记为客观下线状态,同时触发故障转移。

13.知道什么是热key吗?热key问题怎么解决?

所谓热key问题就是,突然有几十万的请求去访问redis上的某个特定key,那么这样会造成流量过于集中,达到物理网卡上限,从而导致这台redis的服务器宕机引发雪崩。

在这里插入图片描述

针对热key的解决方案:

  1. 提前把热key打散到不同的服务器,降低压力
  2. 加入二级缓存,提前加载热key数据到内存中,如果redis宕机,走内存查询

14.什么是缓存击穿、缓存穿透、缓存雪崩?

缓存击穿:
缓存击穿的概念就是单个key并发访问过高,过期时导致所有请求直接打到db上,这个和热key的问题比较类似,只是说的点在于过期导致请求全部打到DB上而已。

解决方案:
1.加锁更新,比如请求查询A,发现缓存中没有,对A这个key加锁,同时去数据库查询数据,写入缓存,再返回给用户,这样后面的请求就可以从缓存中拿到数据了。
2.将过期时间组合写在value中,通过异步的方式不断的刷新过期时间,防止此类现象。

在这里插入图片描述

缓存穿透:
缓存穿透是指查询不存在缓存中的数据,每次请求都会打到DB,就像缓存不存在一样。

针对这个问题,加一层布隆过滤器。布隆过滤器的原理是在你存入数据的时候,会通过散列函数将它映射为一个位数组中的K个点,同时把他们置为1。
这样当用户再次来查询A,而A在布隆过滤器值为0,直接返回,就不会产生击穿请求打到DB了。显然,使用布隆过滤器之后会有一个问题就是误判,因为它本身是一个数组,可能会有多个值落到同一个位置,那么理论上来说只要我们的数组长度够长,误判的概率就会越低,这种问题就根据实际情况来就好了。

在这里插入图片描述

缓存雪崩
当某一时刻发生大规模的缓存失效的情况,比如你的缓存服务宕机了,会有大量的请求进来直接打到DB上,这样可能导致整个系统的崩溃,称为雪崩。雪崩和击穿、热key的问题不太一样的是,他是指大规模的缓存都过期失效了。

针对雪崩几个解决方案:
1.针对不同key设置不同的过期时间,避免同时过期
2.限流,如果redis宕机,可以限流,避免同时刻大量请求打崩DB
3.二级缓存,同热key的方案。

在这里插入图片描述

15.Redis的过期策略有哪些?

redis主要有2种过期删除策略

惰性删除
惰性删除指的是当我们查询key的时候才对key进行检测,如果已经达到过期时间,则删除。显然,他有一个缺点就是如果这些过期的key没有被访问,那么他就一直无法被删除,而且一直占用内存。

在这里插入图片描述

定期删除

定期删除指的是redis每隔一段时间对数据库做一次检查,删除里面的过期key。由于不可能对所有key去做轮询来删除,所以redis会每次随机取一些key去做检查和删除。

16.那么定期+惰性都没有删除过期的key怎么办?

假设redis每次定期随机查询key的时候没有删掉,这些key也没有做查询的话,就会导致这些key一直保存在redis里面无法被删除,这时候就会走到redis的内存淘汰机制。

  1. volatile-lru:从已设置过期时间的key中,移出最近最少使用的key进行淘汰
  2. volatile-ttl:从已设置过期时间的key中,移出将要过期的key
  3. volatile-random:从已设置过期时间的key中随机选择key淘汰
  4. allkeys-lru:从key中选择最近最少使用的进行淘汰
  5. allkeys-random:从key中随机选择key进行淘汰
  6. noeviction:当内存达到阈值的时候,新写入操作报错
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值