Redis面试题汇总

目录

一、动力节点Redis的书

7. Redis持久化

二、马士兵李瑾老师

2.1 Redis高级特性和应用

1)发布订阅:

2)Stream

延伸:Redis中几种消息队列实现的总结

3)慢查询

4)Pipeline流水线

5)事务

6)Lua

延伸:Redis与限流★★★

2.2 Redis底层原理

1)持久化

2)分布式锁

2.3 Redis高并发高可用

1)集群

2)主从复制

3)哨兵

2.4 Redis缓存使用问题及互联网运用

1)Redis缓存使用的数据不一致问题

2)缓存穿透、击穿、雪崩

3)热点Key

4)BigKey

2.5 Redis设计、实现

1)数据结构和内部编码

2)Redis中的线程和IO模型

3)缓存淘汰算法

4)过期策略和惰性删除


一、动力节点Redis的书

1. Redis有哪些特性?

2. Redis的IO模型是单线程还是多线程?

  • Redis4.0版本以前是纯粹的单线程模型;从4.0版本开始,处理客户端请求的仍然是单线程模型,但像持久化、对AOF的rewrite、对失效连接的清理等由后台的线程进行处理。
  • 从6.0开始才是真正意义上的多线程模型,对客户端请求的处理采用的才是多线程模型,但“多线程”仅用于接收、解析客户端的请求,然后将解析出的请求写入任务队列。而对任务(命令)的处理,仍然由单线程处理。这样做的好处:用户不需要考虑线程安全问题,不需要考虑事务控制。

3. Redis的内存移除策略有哪些?(P31)

4. Redis有哪些数据类型?(P3)

5. 典型应用场景?

  • String类型:缓存计数器(如视频播放次数);共享Session(如用户登录session保存在Redis中避免分布式应用中重新登录的问题,token令牌实现接口幂等性);限速器(如用于接口防刷)。
  • Hash类型:适合存储对象数据。key为对象名称,value为描述对象属性的Map,对对象属性的修改在redis中就可以直接完成,无需序列化。
  • List类型:栈、队列、阻塞式消息队列、动态有限集合。
  • Set类型:标签;抽奖;随机选人等。
  • 有序Set类型:排行榜。
  • BitMap:一般用于大数据量的二值性统计。

6. Redis命令

1)Redis基本命令

2)key操作命令

        keys、exists、del、rename、move、type、expire/pexpire、ttl/pttl、persist、scan

3)String型value操作命令(值最大存512M)

  • SET key value [EX seconds | PX milliseconds] [NX | XX]    (NX时等同于setnx)
  • setex/psetex key 过期时间秒/毫秒 value
  • setnx
  • getset 
  • mset/msetnx key value  [key value ...]
  • mget key [key ...]
  • append key value
  • incr/decr key
  • incrby/decrby key increment     (increment为增/减的数值,不能是小数)
  • incrbyfloat key increment     (没有decrbyfloat命令)
  • strlen key           返回key所存字符串的长度
  • getrange key start end        返回key所存字符串的子字符串(start、end为起始偏移量)
  • setrange key offset value     

4)Hash型value操作命令

特点:所有命令都带h

  • HSET key field value [field value ...]

        例如:hset user:001 name Lucy sex male age 18 hobbies read

  • HGET key field
  • hmset key field value [field value ...]
  • hmget key field [field...]
  • hgetall key         返回哈希表key中所有的域和值
  • hsetnx key field value   
  • hdel key field [field...]
  • hexists key field
  • hincrby/hincrbyfloat key field increment
  • hkeys key / hvals key    返回哈希表key中的所有域/值
  • hlen key    返回hash表key中域的数量
  • hstrlen key field     返回关联值字符串的长度

5)List型value操作命令

  • lpush/rpush key value [value...]             将一个或多个值value插入到列表key的表头/表尾
  • llen key       返回列表key的长度
  • lindex key index    返回列表key中下标为index的元素。列表从0开始计数
  • lset key index value       将列表key下标为index的元素的值设置为value
  • lpop/rpop key [count]       从列表key的表头/表尾移除count个元素,并返回移除的元素,count默认值为1
  • blpop/brpop key [key...] timeout      是lpop/rpop命令的阻塞式版本
  • lrange、lpushx/rpushx、linsert、rpoplpush、brpoplpush、lrem、ltrim

6)Set型value操作命令

set类型所有命令均以s开头。

  • sadd key member [member...]
  • smembers key      返回集合key中的所有成员
  • 其他命令略

6)Set型value操作命令

     

7. Redis持久化

Redis持久化有几种方式?默认是哪种?哪种优先级更高?

RDB持久化:RDB持久化的执行方式有几种?是否会阻塞主线程?

                      RDB持久化过程?

AOF持久化:Append Only File,是指Redis将每一次的写操作都以日志的形式记录到一个AOF文件中。

AOF的工作流程主要是4个部分:命令写入( append)、文件同步( sync)、文件重写(rewrite)、重启加载( load)。

命令写入:

  • AOF为什么把命令追加到aof_buf中?(李瑾老师讲义)
  • Redis提供了多种AOF缓冲区同步文件策略有哪几种?

重写机制:用于压缩日志文件大小的。

对比:RDB文件较小,保存的是快照,数据恢复较快,实时性差,数据安全性低;

           AOF保存的是写操作的日志,实时性好,文件可读性强。

二、马士兵李瑾老师

2.1 Redis高级特性和应用

1)发布订阅:

使用场景和缺点:

  • 需要消息解耦又并不关注消息可靠性的地方都可以使用发布订阅模式。
  • PubSub 的生产者传递过来一个消息,Redis会直接找到相应的消费者传递过去。如果一个消费者都没有,那么消息直接丢弃。如果开始有三个消费者,一个消费者突然挂掉了,生产者会继续发送消息,另外两个消费者可以持续收到消息。但是挂掉的消费者重新连上的时候,这断连期间生产者发送的消息,对于这个消费者来说就是彻底丢失了。
  • 所以和很多专业的消息队列系统(例如Kafka、RocketMQ)相比,Redis 的发布订阅很粗糙,例如无法实现消息堆积和回溯。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择。
  • 正是因为 Pub/Sub 有这些缺点,它的应用场景其实是非常狭窄的。从Redis5.0 新增了 Stream 数据结构,这个功能给 Redis 带来了持久化消息队列。

2)Stream

Redis5.0 最大的新特性就是多出了一个数据结构 Stream,它是一个新的强大的支持多播的可持久化的消息队列,借鉴了 Kafka 的设计。

延伸:Redis中几种消息队列实现的总结

  • 基于List的 LPUSH+BRPOP 的实现
  • 基于Sorted-Set的实现
  • PUB/SUB,订阅/发布模式
  • 基于Stream类型的实现

3)慢查询

默认慢查询时间是10毫秒,可以在配置文件中配置slowlog-log-slower-than参数,单位是微秒。可以持久化,后期可以查询慢查询。慢查询只记录命令执行时间,并不包括命令排队和网络传输时间。因此客户端执行命令的时间会大于命令实际执行时间。

4)Pipeline流水线

Redis客户端执行一条命令分为如下4个部分: 1)发送命令2)命令排队3)命令执行4)返回结果。

其中1和4花费的时间称为Round Trip Time (RTT,往返时间),也就是数据在网络上传输的时间。

Redis提供了批量操作命令(例如mget、mset等),有效地节约RTT。

但大部分命令是不支持批量操作的,例如要执行n次 hgetall命令,并没有mhgetall命令存在,需要消耗n次RTT。

举例:Redis的客户端和服务端可能部署在不同的机器上。例如客户端在本地,Redis服务器在阿里云的广州,两地直线距离约为800公里,那么1次RTT时间=800 x2/ ( 300000×2/3 ) =8毫秒,(光在真空中传输速度为每秒30万公里,这里假设光纤为光速的2/3 )。而Redis命令真正执行的时间通常在微秒(1000微妙=1毫秒)级别,所以才会有Redis 性能瓶颈是网络这样的说法。

Pipeline(流水线)机制能改善上面这类问题,它能将一组 Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令的执行结果按顺序返回给客户端,而没有使用Pipeline则需要执行n条命令,整个过程需要n次RTT。

5)事务

事务原理:

  • MULTI用于开启事务,EXEC用于提交事务。discard命令是回滚(discard也只是丢弃这个缓存队列中的未执行命令,并不会回滚已经操作过的数据,这一点要和关系型数据库的Rollback操作区分开)。
  • Redis提供了简单的事务,之所以说它简单,主要是因为它不支持事务中的回滚特性,同时无法实现命令之间的逻辑关系计算。

Redis的watch命令:

  • 有些应用场景需要在事务之前,确保事务中的key没有被其他客户端修改过,才执行事务,否则不执行(类似乐观锁)。Redis 提供了watch命令来解决这类问题。

6)Lua

通过使用LUA脚本:

1、减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行;

2、原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入(Redis执行命令是单线程)。

3、复用性,客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑。

不过为了我们方便学习Lua语言,我们还是单独安装一个Lua。

在Redis使用LUA脚本的好处包括:

1、减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行;

2、原子操作,Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件;

3、复用性,客户端发送的脚本会存储在Redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑

延伸:Redis与限流★★★

  • 使用Redis+Lua语言实现限流(代码见讲义)
  • 限流算法有哪些?
    • 固定窗口算法:
    • 滑动窗口算法:
    • 漏洞算法:先有一个桶,桶的容量是固定的。以任意速率向桶流入水滴,如果桶满了则溢出(被丢弃)。桶底下有个洞,按照固定的速率从桶中流出水滴。漏桶核心是:请求来了以后,直接进桶,然后桶根据自己的漏洞大小慢慢往外面漏。
    • 令牌算法:先有一个桶,容量是固定的,是用来放令牌的。以固定速率向桶放令牌,如果桶满了就不放令牌了。处理请求是先从桶拿令牌,先拿到令牌再处理请求,拿不到令牌同样也被限流了。

2.2 Redis底层原理

1)持久化

见上面动力节点的。

2)分布式锁

1. 最简单的实现是setnx,但如果某个客户端拿到锁后进程挂了没机会释放锁就会造成死锁。如何避免呢?设置过期时间!

SETNX productIdlock 1    // 加锁
EXPIRE productIdlock 10  // 10s后自动过期

但上面两条操作不是原子性的,如果执行了一条之后宕机或者网络出现问题,依旧会有死锁的情况发生。在 Redis 2.6.12 之后,Redis 扩展了 SET 命令的参数,用这一条命令就可以了:

SET productIdlock 1 EX 10 NX
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);

2. 锁被别人释放怎么办?

3. Java代码实现分布式锁(见讲义)

4. 锁过期时间不好评估怎么办?(看门狗)

5. Redisson中的分布式锁(可重入),把上面这些工作都封装好了

这一块看看动力节点的书P243页。

     <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.3</version></dependency>
package com.msb.redis.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyRedissonConfig {/*** 所有对Redisson的使用都是通过RedissonClient*/@Bean(destroyMethod="shutdown")public RedissonClient redisson(){//1、创建配置Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");//2、根据Config创建出RedissonClient实例RedissonClient redisson = Redisson.create(config);return redisson;}
}

6. 集群下的锁还安全吗?

以上1~5是分布式场景下,锁在「单个」Redis实例中可能产生的问题,并没有涉及到 Redis 的部署架构细节。 而我们在使用 Redis 时,一般会采用主从集群 +哨兵的模式部署,这样做的好处在于,当主库异常宕机时,哨兵可以实现「故障自动切换」,把从库提升为主库,继续提供服务,以此保证可用性。

但是因为主从复制是异步的,那么就不可避免会发生的锁数据丢失问题(加了锁却没来得及同步过来)。从库被哨兵提升为新主库,这个锁在新的主库上,丢失了!

7. Redlock真的安全吗?(详见讲义)

2.3 Redis高并发高可用

1)集群

2)主从复制

①Redis主从复制原理?

3)哨兵

①哨兵机制的原理?

②Redis节点的下线判断?

③Sentinel Leader选举

2.4 Redis缓存使用问题及互联网运用

1)Redis缓存使用的数据不一致问题

针对高并发写场景。

通常选择先更新DB,再删除缓存。同时结合延时双删的处理,可以有效的避免缓存不一致的情况。“延迟双删” 伪代码如下:

redis.delKey(X)

db.update(X)

Thread.sleep(N)

redis.delKey(X)

2)缓存穿透、击穿、雪崩

针对高并发读场景。

缓存穿透:查询一个根本不存在的数据

原因:代码或业务出现问题;恶意攻击;

解决方法:缓存空对象(设置过期时间);布隆过滤器拦截。

缓存击穿:热key,过期的瞬间高并发

解决方法:使用互斥锁(mutex key);永远不过期

缓存雪崩:缓存层由于某些原因不能提供服务,比如同一时间缓存数据大面积失效。

3)热点Key

4)BigKey

2.5 Redis设计、实现

1)数据结构和内部编码

Redis存储的所有值对象在内部定义为redisobject结构体:type字段,encoding字段,lru字段,refcount字段,*ptr字段。

2)Redis中的线程和IO模型

        略。

3)缓存淘汰算法

4)过期策略和惰性删除

        略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/586877.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新发现!科学家最新成果:补充类“原知因起源金”物质可延长寿命23%

近日&#xff0c;美哥伦比亚大学Vijay Yadav团队在《Science》发布了一项重磅级成果&#xff1a;通过补充一种特殊氨基酸&#xff08;带有磺酸基团的全能抗衰物质&#xff09;&#xff0c;竟然惊人地将实验动物的寿命延长了23%。 而其背后的机制&#xff0c;与早已火爆电商圈的…

Pygame基础9-射击

简介 玩家用鼠标控制飞机&#xff08;白色方块&#xff09;移动&#xff0c;按下鼠标后&#xff0c;玩家所在位置出现子弹&#xff0c;子弹匀速向右飞行。 代码 没有什么新的东西&#xff0c;使用两个精灵类表示玩家和子弹。 有一个细节需要注意&#xff0c;当子弹飞出屏幕…

erp系统开发报价:企业如何选择一套合适的智能erp管理系统-亿发

在选择ERP系统时&#xff0c;企业通常希望了解上一套系统到底需要多少资金&#xff0c;但实际上这个问题并没有一个明确的答案。一般的erp系统从几万到几百万不等&#xff0c;一些简单的erp系统甚至只需要几千元。ERP系统的价格取决于多种因素&#xff0c;包括企业的业务规模、…

vs2022断点找bug出错(打上100个断点)

初步分析&#xff1a;故障出自-具体功能模块 进一步分析&#xff1a;故障出自-该功能代码流程 进一步分析&#xff1a;从该功能起点-终点&#xff0c;一路打100个断点

【学习笔记】java项目—苍穹外卖day03

文章目录 苍穹外卖-day03课程内容1. 公共字段自动填充1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3 步骤三 1.4 功能测试1.5 代码提交 2. 新增菜品2.1 需求分析与设计2.1.1 产品原型2.1.2 接口设计2.1.3 表设计 2.2 代码开发2.2.1 文件上传实现2.2.2 新…

想要做好自动化测试,离不开这5点!

最近小编在逛技术交流社区&#xff0c;在一条讨论自动化测试落地面临的痛点及可以创造的价值下面&#xff0c;有这样一条回复颇有感触&#xff0c;分享如下&#xff1a; 如果你让两个相互不认识、来自不同公司的测试工程师自由讨论&#xff0c;我猜他两寒暄的第一个问题会是&a…

时序预测 | Python实现VMD-CNN-LSTM时间序列预测

时序预测 | Python实现VMD-CNN-LSTM时间序列预测 目录 时序预测 | Python实现VMD-CNN-LSTM时间序列预测预测效果基本介绍模型描述代码设计预测效果 基本介绍 VMD-CNN-LSTM 是一种混合深度学习模型,结合了变分模态分解(VMD)、卷积神经网络(CNN)和长短期记忆网络(LSTM)的…

阿里云优惠券如何领取使用?

阿里云是阿里巴巴旗下云计算及人工智能科技公司&#xff0c;提供云服务器、云数据库、云存储等云计算服务和云解决方案。为了吸引更多的用户&#xff0c;阿里云经常推出各种优惠活动&#xff0c;其中就包括阿里云优惠券。本文将为大家详细介绍阿里云优惠券领取方法及使用教程&a…

【Leetcode】top 100 二分查找

35 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 基础写法&#xff01;&#xff01;&#xff01;牢记…

基于蚁群算法的三维路径规划(matlab实现)

作品简介 1 理论基础 1.1 三维路径规划问题概述 三维路径规划指在已知三维地图中&#xff0c;规划出一条从出发点到目标点满足某项指标最优&#xff0c;并且避开了所有三维障碍物的三维最优路径。现有的路径规划算法中&#xff0c;大部分算法是在二维规划平面或准二维规划平面…

OM6650AM支持蓝牙5.1协议栈与2.4GHz私有协议的双模无线连接SoC芯片

OM6650AM是一款超低功耗、同时支持蓝牙5.1协议栈与2.4GHz私有协议的双模无线连接SoC芯片&#xff0c;采用4.0 mm x 4.0 mm QFN32封装&#xff0c;具有丰富的资源&#xff0c;极低的功耗&#xff0c;优异的射频性能&#xff0c;可广泛应用于车载数字钥匙模组、胎压检测、PKE钥匙…

Vite,Vue3项目引入dataV报错的解决方法

错误&#xff1a; 解决方法&#xff1a; 错误&#xff1a; 解决方法&#xff1a; vite.config.js添加以下代码&#xff1a; optimizeDeps: {// 开发时 解决这些commonjs包转成esm包include: ["jiaminghi/c-render","jiaminghi/c-render/lib/plugin/util",…