redis的常见面试题
为什么要用redis
减少了mysql数据库的压力,
在这之前mysql一个人承受,然后要承受大量的数据请求,
大部分都是读操作。而且经常都是重复查一个东西,浪费了很多时间进行磁盘io
redis将数据都存在内存中,而不用去进行磁盘io操作。节省了很多时间
内存和硬盘的区别:
redis数据储存在内存,mysql数据储存在硬盘,所以我们要了解一下内存和硬盘的概念:
内存是计算机中硬盘数据和CPU数据交换的中转站,属于临时存储器,随操作随时改写存储内容,断电后,内存中的信息全部丢失,存储介质是集成块的RAM类型,电子读写,存储容量较小。
硬盘的存储介质是磁存储,靠磁头读写。硬盘可以长期存储数据,不受断电影响。存储容量大。
如何解决redis缓存数据过多
给缓存的内容加上一个过期时间,由应用程序设置
使用随机算法随机筛选出一些缓存,如果过期则删除 (定期删除)
在查询的时候,查到的刚好是过期的缓存数据,则直接删除(被动式触发/惰性删除)
内存不足时,内存淘汰策略

解决方式: 定时删除 + 惰性删除 + 内存淘汰
缓存穿透
接收到请求,发现缓存数据不存在,同时mysql也没有这个数据
这时候每次碰到查这种数据请求的时候都要再次发送给mysql
这时候就要用到: 布隆过滤器
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的压力
缓存击穿
一个热点数据到了过期时间,删掉的同时 有一大波查询该数据请求刚好发了过来,所以只能将请求发送给mysql
缓存雪崩
就是缓存击穿的升级版。
一大波数据刚好过期,然后同时又接收到了这些数据的大量查询请求,
就将一大波请求发送到了mysql那里。mysql直接干崩了
解决方法: 过期时间分散随机 + 热点数据永不过期
1、让应用程序在 设置缓存过期时间的时候 设置得更加分散,不那么集中,这就不会导致一大波缓存数据在同一时间过期。可以设置随机过期
2、设置热点数据永不过期
遇到电脑突然异常关机导致缓存数据丢失
数据备份
- RDB
- AOF
保存每次查询的日志...
将redis的指令记录下来,重启的时候再次执行一次
如何保证redis和数据库的数据一致?
先淘汰缓存 然后再更新数据库
Redis平时的一些应用场景
缓存数据,一些热点数据,,或者是一些定时信息,例如验证码
还可以做线程的并发的操作,比如一些 ++操作
redis分布式锁
加锁:
/**
* 加锁
* @param stringRedisTemplate Redis客户端
* @param lockKey 锁的key
* @param requestId 竞争者id
* @param expireTime 锁超时时间,超时之后锁自动释放
* @return
*/
public static boolean getDistributedLock(StringRedisTemplate stringRedisTemplate, String lockKey, String requestId, int expireTime) {
return stringRedisTemplate.opsForValue().setIfAbsent(lockKey, requestId, 30, TimeUnit.SECONDS);
}
这个setIfAbsent()方法一共五个形参:
第一个为key,我们使用key来当锁,因为key是唯一的。
第二个为value,这里写的是锁竞争者的id,在解锁时,我们需要判断当前解锁的竞争者id是否为锁持有者。
第三个为expx,这个参数我们传的是PX,意思是我们要给这个key加一个过期时间的设置,具体时间由第五个参数决定;
第四个参数为time,与第四个参数相呼应,代表key的过期时间。
总的来说,执行上面的setIfAbsent()方法就只会导致两种结果:
1.当前没有锁(key不存在),那么就进行加锁操作,并对锁设置一个有效期,同时value表示加锁的客户端。
2.已经有锁存在,不做任何操作。上述解锁请求中,缓存超时机制保证了即使一个竞争者加锁之后挂了,也不会产生死锁问题:超时之后其他竞争者依然可以获取锁。通过设置value为竞争者的id,保证了只有锁的持有者才能来解锁,否则任何竞争者都能解锁,那岂不是乱套了。
解锁:
/**
* 释放分布式锁
* @param stringRedisTemplate Redis客户端
* @param lockKey 锁
* @param requestId 锁持有者id
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(StringRedisTemplate stringRedisTemplate, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Long result = stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Collections.singletonList(lockKey), requestId);
return RELEASE_SUCCESS.equals(result);
}
解锁的步骤:
1、判断当前解锁的竞争者id是否为锁的持有者,如果不是直接返回失败,如果是则进入第2步。
2、删除key,如果删除成功,返回解锁成功,否则解锁失败。
分析
是否可重入:以上实现的锁是不可重入的,如果需要实现可重入,在SET_IF_NOT_EXIST之后,再判断key对应的value是否为当前竞争者id,如果是返回加锁成功,否则失败。
锁释放时机:加锁时我们设置了key的超时,当超时后,如果还未解锁,则自动删除key达到解锁的目的。如果一个竞争者获取锁之后挂了,我们的锁服务最多也就在超时时间的这段时间之内不可用。
Redis单点问题:如果需要保证锁服务的高可用,可以对Redis做高可用方案:Redis集群+主从切换。目前都有比较成熟的解决方案。
更详细可以看这篇文章:分布式锁的三种实现方式
Redis的五种数据类型
redis的五种数据类型为:string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)。
1、string(字符串)是redis最常用的类型,可以包含任何数据,一个key对应一个value,在Rediss中是二进制安全的。
2、hash(哈希)是一个string 类型的key和value的映射表,适合被用于存储对象。
3、list(列表)是一个链表结构,按照插入顺序排序。
4、set(集合)是 string 类型的无序集合。
5、zset(有序集合)是string类型元素的集合,zset是插入有序的,即自动排序。
Redis的哨兵机制
哨兵模式概述
需要更详细就去搜
(自动选主机的方式),哨兵模式其实就是一个类似于监视器的存在,他还可以管理主从服务器。
主从切换技术:当主机宕机后,需要手动把一台从(slave)服务器切换为主服务器,这就需要人工干预,费时费力,还回造成一段时间内服务不可用,所以推荐哨兵架构(Sentinel)来解决这个问题。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
Redis实现多服务器Seesion共享
也可以通过存放Shiro传入账号密码生成的token
//获取当前的用户
Subject currentUser = SecurityUtils.getSubject();
//封装用户的登陆数据 放入令牌加密
UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
引言
Redis的Session共享
大厂很多项目都是部署到多台服务器上,这些服务器在各个地区都存在,当我们访问服务时虽然执行的是同一个服务,但是可能是不同服务器运行的;
在我学习项目时遇到这样一个登录情景,假设有如下三台服务器,就使用session存放用户的登录信息,通过该信息可以判断用户是否登录:
假设本次登录是通过服务器01执行的,那么这次的登录session信息就存放到了内存01中;但是当我再次访问时却是服务器02执行操作,而登录session信息却在内存01中,服务器02无法获取,所以它就会判断我没有登录,返回错误的信息…
我们想要实现的就是通过一台服务器登录所生成的session可以和其他服务器共享,那么该如何实现?
解决方法 思路就是既然这几个服务器自己的内存不能共享,那么只要有一个共享空间供这几个服务器共同访问不就可以了;
具体操作
下面就通过redis配置实现共享session:
首先要下载redis,下载网上找教程;这里我直接用的在服务器上通过docker创建的redis容器(简单好用,强烈推荐):
通过可视化工具可以连接一下:
这样redis就配置好了,下面在项目代码中配置redis:
代码中配置redis
在项目中引入redis依赖和spring-session配置依赖(自动将 session 存储到 redis 中):
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.6.3</version>
</dependency>
在application.yml文件中配置连接redis和session相关配置:
spring:
# session配置
session:
timeout: 86400 # 设置session失效时间
store-type: redis # 修改spring-session存储配置,默认存储到服务器内存中,现在设置存到redis中(关键)
# redis配置
redis:
port: 8081 # redis的端口号(这里是我的redis容器在docker中对应的端口号)
host: xx.xxx.xxx.xxx # 我的云服务器ip
database: 0 # 设置存入redis的哪一个库(默认是0)
其实关键配置就一个: store-type: redis,只要配置了这个,那么代码中session就会存放到redis中而不是自己的内存中;
接下来就可以测试了:
调用登录接口,生成用户session信息,查看redis:
Redis数据同步:主从库是如何实现数据一致的
redis如何保证数据同步,
也可以一个服务器建立两个redis实例一台服务器搭建两个redis或多个redis实例
我们学习了 AOF 和 RDB,如果 Redis 发生了宕机,它们可以分别通过回放日志和重新读入 RDB 文件的方式恢复数据,从而保证尽量少丢失数据,提升可靠性。
不过,即使用了这两种方法,也依然存在服务不可用的问题。比如说,我们在实际使用时只运行了一个 Redis 实例,那么,如果这个实例宕机了,它在恢复期间,是无法服务新来的数据存取请求的。
那我们总说的 Redis 具有高可靠性,又是什么意思呢?其实,这里有两层含义:一是数据尽量少丢失,二是服务尽量少中断。AOF 和 RDB 保证了前者,而对于后者,Redis 的做法就是增加副本冗余量,将一份数据同时保存在多个实例上。即使有一个实例出现了故障,需要过一段时间才能恢复,其他实例也可以对外提供服务,不会影响业务使用。
读操作:主库、从库都可以接收;
写操作:首先到主库执行,然后,主库将写操作同步给从库。
redis监控命令及退出 monitor
大多数情况下使用redis是为了缓存消息,有的时候开发阶段进行调试或者定位问题,想知道redis进行了哪些操作,必要情况下使用monitor命令排查问题,quit退出监控(要注意不要长时间使用监控)。
可以看出什么时间,redis做出了什么操作。
不过开启监控后,比较消耗性能,不建议长时间使用,使用完成后,使用图一中 命令:QUIT 进行退出即可。
Pipeline(管道)用来存入大量数据的方法
可以大幅减少io开销、从而提升整体服务的性能
因此如果遇到大量的批处理,我们可以考虑使用Redis的pipeline(管道)。值得注意的是,管道技术并不是Redis特有的技术,管道技术往往需要客户端-服务器的共同配合,大部分工作任务其实是在客户端完成,很显然Redis支持管道技术,按照官网的意思,Redis的最低版本就考虑了管道技术的支持性设计。
如下图,多个连续的incr指令,使用pipeline(管道)后,多个连续的incr指令只会花费一次网络来回开销,这个开销会随着n数值的增大,大幅减少网络io开销,从而提升整体服务的性能。
redis的常见面试题的更多相关文章
- 测开常见面试题什么是redis
企业中redis是必备的性能优化中间件,也是常见面试题,首先Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库.Redis全称为:Rem ...
- redis知识点及常见面试题
redis知识点及常见面试题 参考: https://zm8.sm-tc.cn/?src=l4uLj4zF0NCIiIjRnJGdk5CYjNGckJLQrIqNiZaJnpOWjIvQno2Llpy ...
- 整理的最全 python常见面试题(基本必考)
整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...
- PHP常见面试题汇总(二)
PHP常见面试题汇总(二) //第51题:统计一维数组中所有值出现的次数?返回一个数组,其元素的键名是原数组的值;键值是该值在原数组中出现的次数 $array=array(4,5,1,2,3,1, ...
- python爬虫常见面试题(二)
前言 之所以在这里写下python爬虫常见面试题及解答,一是用作笔记,方便日后回忆:二是给自己一个和大家交流的机会,互相学习.进步,希望不正之处大家能给予指正:三是我也是互联网寒潮下岗的那批人之一,为 ...
- 整理的最全 python常见面试题
整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...
- java常见面试题及答案 1-10(基础篇)
java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...
- Web开发的常见面试题HTML和HTML5等
作为一名前端开发人员,HTML,HTML5以及网站优化都是必须掌握的技术,下面列举一下HTML, HTML5, 网站优化等常见的面试题: HTML常见面试题: 1. 什么是Semantic HTML( ...
- 常见面试题之ListView的复用及如何优化
经常有人问我,作为刚毕业的要去面试,关于安卓开发的问题,技术面试官会经常问哪些问题呢?我想来想去不能一股脑的全写出来,我准备把这些问题单独拿出来写,并详细的分析一下,这样对于初学者是最有帮助的.这次的 ...
- iOS常见面试题汇总
iOS常见面试题汇总 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 i ...
随机推荐
- ANSYS实体单元施加扭矩方法分析
ANSYS 结构分析单元与应用-王新敏等(P199) 此处以等截面椭圆柱为例. 对实体单元施加扭矩,主要方法如下: 引入质量单元 MASS21 并新建顶面的中心节点,随后将顶面所有节点通过 cerig ...
- 【Linux】3.5 实用指令
实用指令 1. 指定运行级别(7个级别) 0.关机[一旦开机它就会执行关机] 1.单用户[找回丢失密码] 2.多用户状态没有网络服务 3.多用户状态有网络服务 4.系统未使用保留给用户 5.图形界面 ...
- 【SpringMVC】映射请求参数 & 请求头
映射请求参数 & 请求参数 请求处理方法签名 Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应人参中. Spring MVC 对控制器处理方法签名的限制 ...
- 感觉程序员要被 AI 淘汰了?学什么才有机会?
感觉程序员要被 AI 淘汰了?学什么才有机会? ️ 推荐观看视频版:https://www.bilibili.com/video/BV1i9Z8YhEja AI 会淘汰程序员么? 我的答案是 &quo ...
- 本地学习环境minikube安装
有感于K8S太强大和自己的太无知,索性来系统学习下K8S.网上一番攻略,起码先得有个本地学习环境,所以安装一个minikube,下面记录安装过程,供有需要的人使用. 看看minikube架构: 我是在 ...
- Redis的淘汰机制
第一种情况:设置了过期时间的数据 a:挑选使用最少的数据淘汰 b:随机淘汰 c:选择时间快过期数据淘汰 第二种:没有设置过期时间的数据 a:挑选使用最少的数据淘汰 b:随机淘汰 第三种: a:禁止驱逐 ...
- 微信公众号-自定义微信分享(vue)(JS-SDK)
1.需求描述 日常公众号开发中,业务部门对于微信内置分享(右上角->分享到朋友等)效果不太满意,需要我们自定义相关分享效果 1.1微信默认分享效果展示 1.2通过自定义分享后效果展示 1.3微信 ...
- 一文速通 Python 并行计算:07 Python 多线程编程-线程池的使用和多线程的性能评估
一文速通 Python 并行计算:07 Python 多线程编程-线程池的使用和多线程的性能评估 摘要: 本文介绍了 Python 线程池(ThreadPoolExecutor)的使用方法,包括线程池 ...
- MySQL 中的 Log Buffer 是什么?它有什么作用?
MySQL 中的 Log Buffer 是什么?它有什么作用? Log Buffer 是 MySQL InnoDB 存储引擎的一部分,用于存储写入日志数据的内存区域.它主要用于记录事务的变更日志,这些 ...
- 什么条件会触发 Java 的 Young GC?
什么条件会触发 Java 的 Young GC? Young GC,即 新生代垃圾回收,是 Java 垃圾回收机制中的一种重要回收方式.它主要用于回收 新生代 中的对象,尤其是 Eden 区 和 Su ...