面试集中营—Redis面试题

一、Redis的线程模型

        Redis是基于非阻塞的IO复用模型,内部使用文件事件处理器(file event handler),这个文件事件处理器是单线程的,所以Redis才叫做单线程的模型,它采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器进行处理。

        文件事件处理器的结构包括四个部分

       1、多个socket;

       2、IO多路复用程序

       3、文件事件分排器

       4、事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

       多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程 序会 监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理

二、客户端与Redis服务器的一次通讯过程

        一次通讯的过程如下图所示:

       1、客户端socket01发起建立连接的请求,此时Server Socket会产生一个AE_READABLE事件,IO多路复用程序监听到这个事件后把事件压入事件队列中;

       2、文件事件分派器从队列中拿到事件,根据事件的类型分发给连接应答处理器,创建socket01,并将socket01的AE_READABLE事件与命令请求处理器关联,这样下次的AE_READABLE事件就不是由连接应答处理器处理而是由命令请求处理器处理;

       3、连接建立成功后,客户端发送set key  value 请求,Server Socket会再产生一个AE_READABLE事件,IO多路复用程序监听到这个事件后把事件压入事件队列中,文件事件分派器从队列中拿到事件,交由命令请求处理器处理;

       4、命令请求处理器从socket01中的读取key value请求,并完成key value的设置,将socket01的AE_WRITABLE事件与命令回复处理器关联;

       5、如果此时客户端准备好接收返回结果了,那么Server Socket会产生AE_WRITABLE事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,向socket01输出本次操作的一个结果,最后将AE_WRITABLE事件与命令回复处理器解除关联;

       本次请求完成

三、Redis Cluster的原理

        Redis集群中内置了16384个哈希槽,当需要在Redis集群中放置一个key-value时,redis先对key使用crc16算法算出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号0-16384之间的哈希槽,redis会根据节点数量大致均等的将哈希槽映射到不同的节点上。

        1、所有节点相互是连接的,客户端连接任意节点都可以操作所有的数据;

        2、集群消息通信通过集群总线通信,集群总线端口大小为客户端服务端口 + 10000;

3、 节点与节点之间通过二进制协议进行通信
        4、数据按照 Slot 存储分布在多个 Redis 实例上
 
        5、集群节点挂掉会自动故障转移
        6、可以相对平滑扩/ 缩容节点

四、如果有大量的key需要设置同一时间过期,需要注意什么

        如果有大量的 key 在同一时间过期,那么可能同一秒都从数据库获取数据,给数据库造成很大的压力,导致数据库崩溃,系统出现 502 问题。也有可能同时失效,那一刻不用都访问数据库,压力不够大的话,那么 Redis 会出现短暂的卡顿问题。所以为了预防这种问题的发生,最好给 数据的过期 时间加一个随机值,让过期时间更加分散。

五、缓存和数据库的读写一致性问题

        这里比较简单的方法就是当一个更新请求过来的时候,先删除缓存数据,再更新数据库,最后再更新缓存。

        写请求删除缓存成功,则更新数据库,如果更新数据库失败,则直接返回,写请求结束,此 时数据库中的值依旧是旧值,读请求过来后,发现缓存中没有数据, 则会直接向数据库中请求, 同时将数据写入到缓存中,此时也不会出现数据一致性的问题。

        更新数据成功之后,再更新缓存,如果此时更新缓存失败,则缓存中没有数据,数据库中是 新值,写请求结束,此时读请求还是一样,发现缓存中没有数据,同样会从数据库中读取数据, 并且存入到缓存中,其实这里不管更新缓存成功还是失败,都不会出现数据一致性的问题。

       以上其实没啥问题,问题在于,如果一个更新请求还没有结束,比如刚删了缓存,读请求进来了,此时数据库还没有更新,那么读取的就是老的数据,这就要看是否容忍这种问题。如果不能容忍那么就必须要针对同id数据的读写请求进行排队,写请求进来先进入队列,读请求排在后面等写请求完成了,再处理读请求。

六、缓存雪崩、缓存穿透、缓存预热

缓存雪崩

        缓存雪崩就是大量的key在同一时间过期,此时大部分请求都打到了数据库上,造成了数据库CPU和内存的压力过大可能成为数据库宕机,此时会造成更大面积的系统瘫痪,就好像雪崩一样。

        解决的方法第一种就是在读数据的时候先加一层锁,比如redis的分布式锁,只让一个请求进入数据库去查询。第二种方法就是尽量不让大量的key在同一时间过期,比如过期时间上增加一个随机时间;

缓存穿透

        缓存穿透就是指查询一个在缓存中不存在的key,由于不存在会去查询数据库,如果大量的查询不存在的key,还是会对数据库造成大量的压力。

        解决的方法第一种是如果发现数据库中不存在的key,也在redis中缓存一份,过期时间5分钟,这样5分种内同样的key查询就不会进入数据库了;第二种方式是使用布隆过滤器,这需要将所有可能的数据都存到了一个足够大的bitmap中,通过布隆过滤器可以确定请求的key是否合法;

缓存预热

        缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户
请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

七、过期策略以及内存淘汰机制

过期策略        

        针对Key过期的情况,redis采用了定期删除配合惰性删除的策略;

        定期删除:每个100ms检查过期的key,如果由过期的key就删除,但每次不是全量的检查,而是随机抽取进行检查,比如抽取100个,发现其中由20个过期了,就把这20个key删除掉。如果过期 key 的占比超过可接受的过期 key 的百分比(比如20%),则重复删除的过程,直到过期key的比例降至可接受的过期 key 的百分比以下。

        惰性删除:惰性删除是指当客户端请求某个key的时候,会检查这个key是否过期,如果过期了就删除掉;

 内存淘汰机制      

        内存总会有用完的时候,如果内存已经占满了,怎么办呢?这就需要淘汰一部分的key,那么怎么淘汰呢?     

8种内存淘汰策略

1.noeviction(默认策略): 不会删除任何数据,拒绝所有写入操作并返回客户端错误消息(error)OOM command not allowed when used memory,此时 Redis 只响应删和读操作;

2.allkeys-lru: 从所有 key 中使用 LRU 算法进行淘汰(LRU 算法:最近最少使用算法);

3.allkeys-lfu: 从所有 key 中使用 LFU 算法进行淘汰(LFU 算法:最不常用算法,根据使用频率计算,4.0 版本新增);

4.volatile-lru: 从设置了过期时间的 key 中使用 LRU 算法进行淘汰;

5.volatile-lfu: 从设置了过期时间的 key 中使用 LFU 算法进行淘汰;

6.allkeys-random: 从所有 key 中随机淘汰数据;

7.volatile-random: 从设置了过期时间的 key 中随机淘汰数据;

8.volatile-ttl: 在设置了过期时间的key中,淘汰过期时间剩余最短的。

注意: 当使用 volatile-lru、volatile-lfu、volatile-random、volatile-ttl 这四种淘汰策略时,如果没有 key 可以淘汰,则和 neoviction 一样返回错误。

怎么选择淘汰策略

一般根据经验来说:

使用 allkeys-lru 策略场景:

        1.当你期望元素的子集将比其他元素更频繁地被访问时,比如幂律分布,20%的数据占有80%的使用次数;

        2.当你不确定使用哪种策略时。

使用 allkeys-random 策略场景:

        1.当你有一个循环访问,其中所有 key 进行会被连续地访问;

        2.当你希望所有 key 的分布比较均匀。

使用 volatile-ttl 策略场景:

        1.当你大部分缓存都设有不同的 ttl 值,向 Redis 提供过期候选的提示时。

八、Redis的数据类型及使用场景

1、字符串

        String类型是一种最基本的数据类型,它是一个键值对的存储结构,其中键和值都是字符串类型。String类型的特点是快速存储和读取,适用于存储一些简单的数据,如字符串、整数或浮点数等。        

使用场景

  • 缓存:经典使用场景,把常用信息,字符串,图片或者视频等信息放到Redis中,Redis作为缓存层,MySQL做持久化层,降低MySQL的读写压力
  • 计数器:Redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
  • Session:常见方案Spring Session + Redis实现Session共享。

2、List

        列表是简单的字符串列表,按照插入顺序排序,底层是双向列表(压缩列表),一种快速、高效、可靠的数据存储结构,适用于实现队列、栈等常见的数据结构。

  • 消息队列:List类型的lpop和rpush(或者反过来,lpush和rpop)能实现队列的功能,故而可以用Redis的List类型实现简单的点对点的消息队列。

  • 排行榜:List类型的range命令可以分页查看队列中的数据,但是只有顶式计算的排行榜才适合使用List类型存储。

  • 最新列表:List类型的lpush命令和range命令能实现最新列表的功能.每次通过lpush的命令往列表里插入新的元素,然后通过lrange命令读取最新元素列表,如朋友圈的点赞列表、评论列表。

3、Set

        Set对外提供的功能与List类似是一个列表的功能,特殊之处在于Set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,Set是一个很好的选择,并且Set提供了判断某个成员是否在一个Set集合内的重要接口,这个也是List所不能提供的。Redis的Set是String类型的无序集合。它底层其实是一个Value为Null的Hash表,所以添加,删除,查找的复杂度都是O(1)

  • 推荐:通过sinter命令计算交集,比如美团给你推荐附近外卖时就可以根据你的外卖记录与附近商家计算交集推送安全提示:
  • 集合保存:微信群成员保存在一个set中,用户好友也保存在Set中。当用户加入群聊时可以提醒非好友用户注意安全

4、Hash

        hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

  • 结构化存储场景:一个hash结构中存储某个商品所有sku

5、ZSet(sortedSet)

        Zset与普通集合Set非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分是可以重复的 。因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

        排行榜:一个销量排行榜,就可以使用店家的订单做score,这个查询出来的结果就是有序的权重队列:score作为优先级,这样取出来的数据权重都是最大优先执行的

        延时任务:score作为任务启动执行时间,取值时判断该值执行即可。

        

 参考:

Redis学习(六)8种内存淘汰机制_redis淘汰策略-CSDN博客

redis的过期键删除策略_redis过期键删除策略-CSDN博客

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

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

相关文章

开发中的一些专业术语,POJO、PO...

在 Java 开发中,以下是常见的设计模式和概念: PO(Persistent Object):持久化对象,也称为实体类或数据对象。它是与数据库表结构对应的类,通常用于表示持久化数据的实体。PO 类的属性与数据库表的…

阿里easyExcel -- excel单元格自定义下拉选择(升级版)

背景 很久很久以前写了一篇类似的文章 阿里easyExcel – excel下载/导出/读取 (单元格自定义下拉选择、不支持图片) ,用了没多久就发现不好用,限制太多(以后遇到你就知道了),然后就有了现在迟到很久的文章&#xff0c…

python abs函数怎么用

abs()函数是Python的数字函数,用以返回数字的绝对值。 语法 以下是 abs() 方法的语法: abs( x ) 参数 x -- 数值表达式,可以是整数,浮点数,复数。 返回值 函数返回 x(数字)的绝对值&#x…

(十五)Servlet教程——Servlet文件上传

JSP和HTML标签一起使用,来允许用户把文件上传到服务器。 首先我们需要创建一个前端界面,创建上传文件表单时,需要注意以下几点: (1) 表单的method属性必须设置为POST方法, 不能使用GET方法。 (2) 表单enctype属性应该…

accelerator入门

一、目录 1 定义 2. DP、DPP的区别 3 实现 4. 测试比较 二、实现 定义 accelerator 是由大名鼎鼎的huggingface发布的,专门适用于Pytorch的分布式训练框架,是torchrun 的封装。 GitHub: https://github.com/huggingface/accelerate 官网教程:https://…

8、卷积Convolutions (CNN)

Today we finish off our study of collaborative filtering by looking closely at embeddings—a critical building block of many deep learning algorithms. Then we’ll dive into convolutional neural networks (CNNs) and see how they really work. We’ve used plen…

kaggle叶子分类比赛(易理解)

说实话网上很多关于叶子分类比赛的代码能取得的成绩都很好,但对于我这个业余人员太专业了,而且很多文章都有自己的想法,这让我这个仿写沐神代码的小菜鸡甚是头痛。 但好在我还是完成了,虽然结果并不是很好,但是如果跟着沐神走的同…

AI编码时代到来?实现编程梦想的利器—Baidu Comate测评

文章目录 Comate智能编码是什么?Comate支持的环境 Comate应用安装实际操作对话式生成代码生成代码注释智能单测项目测试调优功能 总结 Comate智能编码是什么? 在如今这个拥抱AI的时代,市面上已经产出了很多Ai代码助手,如果你还没…

【LeetCode算法】28. 找出字符串中第一个匹配项的下标

提示:此文章仅作为本人记录日常学习使用,若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、题目二、思路三、解决方案四、JAVA截取字符串的常用方法4.1 通过subString()截取字符串* 一、题目 给你两个字符串 haystack 和 needle ,请你在…

鸿蒙OpenHarmony南向:【Hi3516标准系统入门(IDE方式)】

Hi3516标准系统入门(IDE方式) 注意: 从3.2版本起,标准系统不再针对Hi3516DV300进行适配验证,建议您使用RK3568进行标准系统的设备开发。 如您仍然需要使用Hi3516DV300进行标准系统相关开发操作,则可能会出现…

CST电磁仿真查看模型的截面结构和生成Spice模型【入门教程】

通过Logfile查看仿真统计 一次性了解仿真统计! Post-Processing > Manage Results > Logfile 利用CPU Threads、Mesh Cells、Time Steps以及Total Solver Time等Logfile,可以一目了然地了解仿真统计。 (1)点击Post-Processing选项卡…

PPT如何录制视频?看这里,让你轻松上手!

在现代社会,演示文稿(ppt)已成为我们工作、学习和生活中不可或缺的一部分。无论是商务报告、教育培训还是产品展示,ppt都能以其直观、生动的形式有效地传达信息。可是你知道ppt如何录制视频吗?本文将为您介绍两种ppt录…

pycharm code行太长显示波浪线取消

实际操作如下:个人比较合适的位置为160,180时有点多 效果:

《视觉十四讲》例程运行记录(3)——运行ch6的例程中Ceres和g2o库的安装

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、安装Ceres1. 安装依赖2. 编译安装 二、安装g2o1. 安装依赖项2. 编译安装3. 可能出现的报错(1) 报错一 一、安装Ceres 1. 安装依赖 终端输入: sud…

计算有效声压

计算有效声压 clear all; %%----------------------------------------------读取文件------------------------------------------ % 从wav文件读入语音数据,该语音采样率16k,故信号最高频率8k。 [x,fs]audioread(C2_3_y.wav); % 取x的一个通道 xx(:,1)…

Google准备好了吗?OpenAI发布ChatGPT驱动搜索引擎|TodayAI

在科技界波澜壮阔的发展中,OpenAI正式宣布其最新突破——一个全新的基于ChatGPT技术的搜索引擎,旨在直接挑战谷歌在搜索领域的统治地位。这一创新将可能彻底改变用户上网搜索的方式。 据悉,这款AI驱动的搜索引擎利用了ChatGPT的强大功能&…

免费SSL证书?轻松申请攻略来了!

在当今的互联网时代,网络安全已经成为一个不容忽视的重要课题。随着在线交流和交易活动的增加,保护网站和用户信息的重要性日益突显。SSL证书,即安全套接字层证书,它为互联网通信提供了加密服务,确保数据的安全性和完整…

淘宝扭蛋机小程序开发:转动幸运,开启无限惊喜

一、探索未知,开启全新扭蛋体验 淘宝扭蛋机小程序,为您带来一场前所未有的扭蛋盛宴。在这个充满神秘与乐趣的平台上,每一次点击都将引领您走进未知的宝藏世界,每一次旋转都可能揭示出意想不到的惊喜。 二、海量商品,…

Kubernetes 教程:在 Containerd 容器中使用 GPU

原文链接:Kubernetes 教程:在 Containerd 容器中使用 GPU 云原生实验室本文介绍了如何在使用 Containerd 作为运行时的 Kubernetes 集群中使用 GPU 资源。https://fuckcloudnative.io/posts/add-nvidia-gpu-support-to-k8s-with-containerd/ 前两天闹得沸沸扬扬的事件不知道…

3D 交互展示该怎么做?

在博维数孪(Bowell)平台制作3D交互展示的流程相对简单,主要分为以下几个步骤: 1、准备3D模型:首先,你需要有一个3D模型。如果你有3D建模的经验,可以使用3ds Max或Blender等软件自行创建。如果没…