当前位置: 首页 > news >正文

Redis相关面试题(二)

一、Bit中不同命令使用的场景

请添加图片描述

二、什么是缓存击穿,缓存穿透,缓存雪崩?

缓存击穿:是指当某一个key的缓存过期时大并发量的请求同时访问key,瞬间击穿服务器直接访问到数据库,使得数据库处于负载情况
缓存穿透:是指缓存服务器中没有缓存数据,数据库中也没用符合条件的数据,导致业务系统每次都绕过缓存服务器查询下游的数据库,缓存服务器完全失去作用
缓存击穿是只击穿服务器端访问数据库,而缓存穿透是服务器端和数据库都没有的情况
缓存雪崩:是指当大量缓存同时过期或者缓存服务宕机,所有请求都直接访问数据库,造成数据高负载,影响性能,甚至数据库宕机
请添加图片描述

对于缓存击穿可以用异步加载、互斥锁和提前预热的办法解决

对于缓存穿透的防止常用的是布隆过滤器和黑名单的方式
布隆过滤器是一种比较巧妙的概率性数据结构,它可以告诉你数据一定不存在或可能存在,相比Map、Set、List等传统的数据结构,它占用的内存少、结构更高效

对于缓存雪崩的情况可以设置不同的过期时间和集群的方法实现

三、Redis的集群方式是什么?

典型回答

Redis有三种主要的集群模式,用于在分布式环境中实现高可用性和数据复制,模式主要是:主从模式、哨兵模式和Redis Cluster模式

1. 主从模式

主从模式是Redis中最简单的集群模式,这个模式主要是为了解决单点故障的问题,所以将数据复制多个副本中,这样即使有一台服务器出现故障,其他服务器依旧可以继续提供服务。

主从模式中主要包括一个主节点和多个从节点,主节点负责处理所有读和写操作,而从节点则复制主节点的数据,并且只处理读操作,当主节点出现故障时,可以将包含数据较多的从节点升级为主节点,实现故障转移,但是这个步骤需要手动实现

优点:简单明了,适用于读多写少的场景
缺点:不具备自动转移功能的能力,没办法容错和恢复

2.哨兵模式

为了解决主从模式的不能自动容错及恢复的问题,Redis引入了一种哨兵模式的集群架构。

哨兵模式是在主从模式的基础上加入了哨兵节点,哨兵节点是一种特殊的Redis节点,用于监控主节点和从节点的状态。当主节点出现故障时,哨兵节点可以自动进行故障转移,选择一个包含数据较多的从节点升级为主节点,并通知其他节点和应用程序进行更新。

优点:解决了主从模式的不能自动转移故障的问题,提供了自动化监控和故障恢复机制
缺点:虽然可以自动故障转移但是还是不支持自动的数据分区,并且随着节点数量的增加,管理和配置的复杂性会增大

3.Cluster模式

Redis Cluster模式是Redis中推荐的一种分布式集群解决方案,它将数据自动分片到多个节点上,每个节点负责一部分数据

优点:真正实现了分布式存储,每个节点都可以处理读写请求,具备良好的水平扩展能力,内置数据分割、故障排查、和转移能力
缺点:相比于其他模式,更加复杂,需要更多的网络资源和配置管理,客户端需要支持集群特性,跨slot的数据操作可能涉及多个节点,有一定的复杂度

四、Redis过期键的删除策略?

Redis的Key是可以设置过期时间的,Redis的key有着两种删除策略:1.惰性删除,2.定期删除
1. 惰性删除:当key过期时,先放着不管,当每次从键空间中获取key时,检查取得的键是否已经过期,如果已过期的话,就删除该键,如果没有过期,就返回该键
2.定期删除:每隔一段时间就对数据库进行一次扫描检查,删除里面的过期键,至于要删除多少键,检查多少数据库,要由算法决定

五、Redis的内存删除策略有哪些?

Redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
Redis提供了8种数据淘汰策略

LRU全称Least recently used, 淘汰的是最近最少被使用的数据项。(时间概念) 最近最少
LFU全称Least-frequently used,淘汰的是访问频率最低的数据项。 一直最少

  1. 默认策略
    noeviction 不淘汰数据,写不进去返回错误
  2. 只针对设置过期的keys
    1. volatile-lru 根据LRU算法挑选数据淘汰
    2. volatile-lfu 根据LFU算法挑选数据淘汰
    3. volatile-random 随机挑选数据淘汰
    4. volatile-ttl 挑选越早过期的数据进行删除
  3. 所有keys
    1. allkeys-lru 根据LRU算法挑选数据淘汰
    2. allkeys-lfu LFU算法挑选数据淘汰
    3. allkeys-random 随机挑选数据淘汰

六、阐述Redis的主从同步机制?

Redis的主从同步机制是一种特别重要的特性,它允许数据从一个Redis主服务器复制到一个或多个从服务器。这种机制不仅可以提高系统的读取性能,还可以用于数据备份和高可用架构的设计
主要步骤:
第1-4步属于全量,第5步属于增量

  1. 从服务器向主服务器发送同步命令:sync
  2. 主服务器接收到同步命令后,会执行bgsave命令,在后台生成一个rdb文件,并使用一个缓存区记录从现在开始执行的所有写命令
  3. 当主服务器执行完bgsave命令后,会将生成的rdb文件发送给从服务器
  4. 从服务器接收到这个rdb文件,然后加载到内存;之后主服务器会把刚刚在缓存区的命令同步过来,从服务器就会执行这些命令
  5. 以上处理完之后,主数据库每执行一个写命令,都将写命令发送给从数据库

七、Redis和Mysql数据库数据如何保持一致性?

我们在实际项目中经常使用到Redis缓存用来缓解数据库压力,但是当更新数据库时,我们一般采用延时双删策略。目前常用的做法是查询一个接口,先查询Redis,如果不存在则查询数据库,并将结果放入到Rdis中。

7.1 常见的更新策略

  1. 先删缓存,再更新数据库
  2. 先更新数据库,再删缓存
  3. 普通双删
  4. 延时双删

7.1.1 先删缓存,再更新数据库

在这里插入图片描述

  1. 线程A删除缓存数据,此时还没有更新数据库
  2. 线程B 查询缓存没有数据,查询数据库还是旧数据,放入缓存
  3. 线程C以及其他线程使用旧缓存数据,缓存和数据库不一致

7.1.2 先更新数据库,再删除缓存

请添加图片描述

  1. 线程A更新数据库,此时还没有删除缓存
  2. 线程B以及其他线程此时还是使用的旧缓存数据,和数据库不一致

7.1.3 普通双删

请添加图片描述

  1. 线程A先删除缓存,再更新数据库,然后再删除一次缓存
  2. 线程B查询缓存时没有数据,在线程A更新数据库之前,查询到旧数据,此时系统时间切换到线程A执行删除缓存,然后又到线程B放入缓存旧数据
  3. 线程C针对线程A,查询到缓存没有数据,查询数据库的旧数据,然后将旧数据放入到缓存中
    这些都不能满足缓存和数据一致性

7.1.4 延时双删

请添加图片描述

  1. 线程A先删除缓存,之后再更新数据库
  2. 线程B和线程C查询数据时,才发现缓存中没有数据,就去查询数据库,线程B查询到的是旧数据,线程C查询到的是新数据,之后都放入到缓存中。
  3. 线程A延时3-5秒(时间一般要大于SQL执行时间+线程切换时间)后,再将缓存删除。之后其他线程再次查询缓存,发现没有数据,再去查询数据库并且放入缓存都是新数据
  4. 极端情况下,就是如线程D,延时时间超过线程A的延时时间后,再次将旧数据放入到缓存中,这时缓存和数据库的数据还不是一致的,所以延时双删也不是一定能够保证缓存和数据保持一致的

7.2 建议的解决方案

  1. 当发现缓存没有数据后,在执行查询数据库前,对该key进行加锁,查询数据库并放入缓存后再解锁,这样可以避免缓存击穿问题,当某个redis数据不存在时,大量线程并发查询数据库。
  2. 在需要执行双删前,对该Key进行加锁,之后执行删除缓存,更新数据库,放入新数据到缓存,在解锁。保证缓存和数据一致性。
  3. 加锁的Key都需要设置过期时间,避免因为宕机造成死锁。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Go框架选战:Gin、Echo、Fiber的终极较量
  • 力扣 | 递增子序列 | 动态规划 | 最长递增子序列、最长递增子序列的个数、及其变式
  • Python-调用pymysql库,执行插入语句
  • 3个月,从Web前端到鸿蒙应用高手
  • 67、ceph
  • Go语言+Vue3开发前后端后台管理系统实战 用户管理的前端界面和表结构分析
  • MySQl 中对数据表的增删改查(基础)
  • 软件测试下的AI之路(6)
  • Python万字长文基础教程第四章:函数
  • 用openssl 创建自签名证书用于内网HTTPS
  • 云原生与微服务
  • 【CS.DB】数据库-关系型数据库-MySQL-3.3.创建和管理表
  • 【NPM】使用教程
  • Prometheus监控的搭建(ansible安装——超详细)
  • 力扣第五十七题——插入区间
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Android开源项目规范总结
  • docker容器内的网络抓包
  • es6(二):字符串的扩展
  • Java反射-动态类加载和重新加载
  • React的组件模式
  • 阿里云购买磁盘后挂载
  • 基于游标的分页接口实现
  • 模型微调
  • 排序算法之--选择排序
  • 判断客户端类型,Android,iOS,PC
  • 前端攻城师
  • 区块链共识机制优缺点对比都是什么
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 一道闭包题引发的思考
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • Spring Batch JSON 支持
  • 翻译 | The Principles of OOD 面向对象设计原则
  • # 计算机视觉入门
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #Lua:Lua调用C++生成的DLL库
  • ( 10 )MySQL中的外键
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (31)对象的克隆
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (7)svelte 教程: Props(属性)
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (三)mysql_MYSQL(三)
  • (未解决)macOS matplotlib 中文是方框
  • (五)关系数据库标准语言SQL
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • .form文件_一篇文章学会文件上传
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境