Redis(详细)

目录

Redis是什么

Redis的主要特点

Redis的使用场景

会话存储

缓存存储

实现分布式锁

Redis为什么这么快

基于内存操作

高效的数据结构

多路I/O复用模型

单线程执行

Redis常见的数据结构

Redis有序列表的实现

跳跃表的执行流程

Redis分布式锁实现

使用分布式锁存在的问题

产生死锁

锁误删

Redis数据不丢失策略

RDB和AOF的区别

RDB

AOF

缓存雪崩

解决方案:

缓存击穿

解决方案

缓存穿透

 解决方案:

小结


前言

Redis作为目前最火的缓存中间件,开发人员对Redis的要求也越来越高.熟练的掌握Redis的基础知识,是一个开发人员能开发高性能,高可用系统的基石.

Redis是什么

Redis是一个开源的内存数据存储系统,通常被称为缓存存储和键值存储,是一个高性能,轻量级数据库,支持丰富的数据类型和各种高级的功能而闻名.是最受欢迎的NoSQL数据库之一.因此被许多应用程序采用.

Redis的主要特点

  • 内存存储
  • 键值存储
  • 数据类型
  • 持久性
  • 发布-订阅
  • 事务
  • 高可用性

Redis的使用场景

  • 会话存储
  • 缓存存储
  • 实现分布式锁

会话存储

redis可以用于存储用户的会话数据.将会话存储到redis中,可以轻松的实现分布式,高可用性的会话管理,确保用户在多个服务器之间的会话一致.

缓存存储

缓存是redis最常见的使用场景之一,将频繁访问的数据存储到redis中.可以提高整个应用程序的效率,减少对后端数据库服务器的压力.

实现分布式锁

由于redis天生支持分布式系统,所以在redis上加锁操作就是加的分布式锁,可以确保多个客户端的互斥和共享资源.

Redis为什么这么快

Redis之所以快速的原因主要有以下几点:

  • 基于内存操作
  • 高效数据结构
  • 多路I/O复用模型
  • 单线程执行

基于内存操作

redis的所有操作都是基于内存的,而且redis的大多数操作都是简单的读取和写入功能,而存取和大部分操作都是消耗在了I/O上,而进行I/O最快的就是内存了.因为内存的存取操作要远远快于硬盘的读取操作的.

高效的数据结构

redis通过一系列的数据机构来保证redis的效率,其中主要使用动态字符串,哈希表,双向链表,压缩列表,跳跃表,集合,有序集合等高效的数据结构.这样就能将数据高效的存储和获取,这是保证redis性能高的基本条件

多路I/O复用模型

redis采用多路I/O复用模型,多路是指多个网络连接,复用是指多个I/O复用一个线程进行操作,这就使得redis在单线程的基础上能够进行处理并发的请求,多路复用I/O模型是内部使用epool代理实现的,epool会同时监测多个I/O流事件,当没有事件时,就会进行阻塞.

单线程执行

redis的单线程执行就完美的避免了在多线程中出现的问题,例如没有锁竞争和线程的创建和销毁以及线程的调度和切换带来的时间消耗.这就使得redis在单线程中的效率就远远高于多线程执行.

Redis常见的数据结构

redis常见的数据结构有5种:分别是String字符串,List列表,Hash哈希表,Set集合类型,Sorted set有序集合列表.

这5种类型的常用用途如下:

1. String字符串 ,常见的使用场景有存储用户的会话信息,存储缓存信息,存储整数信息,可以使用incr 实现整数+1,decr实现整数-1.

2. List列表类型,常见的使用场景有实现简单的消息队列,存储某项列表的数据.

3. hash哈希类型,常见的使用场景有存储 Session 信息、存储商品的购物车,购物车非 常适合用哈希字典表示,使用人员唯一编号作为字典的 key,value 值可以存储商品的 id 和数量等信息、存储详情页信息

4. Set集合类型,是一个无效且唯一的键值集合,它的使用场景有用户的关注功能,可以用集合存储,保证用户信息不重复.

5. Sorted Set集合类型,是一个有序且唯一的键值集合,常见的使用场景有用来存储排名信息,关注列表功能.

Redis有序列表的实现

有序列表是有ziplist压缩列表和skiplist跳跃表实现的.

  1. 压缩列表是字节数组实现的,是redis为了节省内存而设计的一种线性的数据结构,可以包含多个元素,每一个元素可以是一个字节数组或者整数.
  2. 跳跃表是一种有序的数据结构,它是通过在每个节点中维持指向多个节点的地址,从而能够快速的访问节点的目的.

注意:当数据比较少时,就使用压缩列表来存储,反之当数据比较多,就使用压缩列表来存储.使用压缩列表必须满足以下两个条件:

1. 有序集合的元素个数要小于128个

2. 有序集合中存储的每个元素成员长度必须小于64字节.

如果不满足上述的任意一个条件,就会使用跳跃表存储.

跳跃表的执行流程

跳跃表的底层使用多个链表实现的.

使用跳跃表的时候,查询效率就会很高.

跳跃表的查询:

我们以上述图中查询32为例:

先是从最上面的第2层链表开始找,1比32小,向后移动一位,7比32小,继续向后移动一位,发现为空,就以7为目标,移动到下一层第1层进行查找,18比32小,就继续向后移动一位,发现是77比32大,就会以18为目标,移动到下一层进行查询,再第0层对比18后面的数据,就找到了32.

从上面的流程可以看出,跳跃表的查询是先从最上面的一层开始查找,如果本层节点的值大于要查询节点的值,或者本层的节点为null之后,就会以上一个节点为目标,移动到下一层进行并循环的进行查询,直到知道该节点或者为null然后返回.

Redis分布式锁实现

redis天生就支持分布式系统,所以在redis里面加的锁就是分布式锁,所谓的分布式锁在redis这里是一个逻辑概念.

使用命令 setnx [key value] 加锁 执行结果为1表示成功

使用命令 del [key value] 释放锁

通过setnx多客户端1进行加锁

 

此时再次使用客户端2进行加锁,就会加锁失败.

 

我在客户端1中进行解锁,客户端2就能加锁成功了. 

使用分布式锁存在的问题

产生死锁

会产生死锁:得到锁的线程下线了,锁没有被释放,得到锁的线程就会一只占用锁,导致死锁.

解决方案: 添加超时时间,(模仿MySQL 模式为10s) 使用expire命令.

通过设置超时时间来解决,如果超过超时时间没有释放锁,就会自动释放锁对象,也就不会存在死锁问题了.

锁误删

锁误删问题:某个线程的执行时间大于超时时间,就会产生锁误删问题.

当线程1 获取到lock锁,并设置超时时间为10s,线程2就会自旋等待,但是线程1实际执行需要15s,于是在第10秒的时候,由于超时时间到了,线程1就会把锁释放,线程2就会得到这把锁,当线程1全部15s执行完成之后,就会进行锁的删除操作,由于这会这把锁已经是线程2获取到了,所以线程1就会把线程2的锁删除掉.

解决方案:给锁增加标识,在进行删除的时候,判断这个锁是否属于当前线程,如果是当前线程,则删除,如果不是则不删除.

Redis数据不丢失策略

以为redis的数据是存储在内存中,在内存中的数据断电后就会丢失,而redis使用了持久化技术来解决这个问题.

redis持久化的三种方式:

  • 快照方法(RDB) 将某一个时刻的的内存数据,以二进制的方式写入磁盘
  • 文件追加方式(AOF) 记录所有的操作指令(set del),并于文本的形式追加到文件中,
  • 混合持久化 结合了RDB和AOF的优点,在写入时,会把当前的数据以RDB的方式写入,在后续数据中,使用AOF的方式进行写入.

RDB和AOF的区别

RDB和AOF都是Redis持久化的两种策略

RDB

工作原理:记录某一时刻内存的数据,以二进制的方式写入硬盘

优点:

  • 执行效率比较高,因为是二进制的数据,所以在写入硬盘的时候速度比较快.在恢复时,效率也是很高.
  • 文件比较小,占用较小的硬盘空间.

缺点:

由于是记录某一时刻的数据,所以如果在redis快照期间发生了故障,可能会导致这一时刻的数据都丢失.

AOF

工作原理:将redis的日志文件以文本的形式追加到硬盘文件中去,当redis需要重启的时候,通过回放硬盘文件的内容来恢复数据.

优点:

  • 数据完整性比较好.
  • 由于文件是文本文件,所以在查看时会很方便.

缺点:

  • 由于是追加的方式,硬盘文件会随着时间越来越大,当redis需要重启时,就会影响重启的效率.
  • 对硬盘访问比较频繁,需要频繁的写入文件,可能会对硬盘造成压力.

缓存雪崩

短时间内,有大量的缓存同时过期,导致大量的请求全部访问数据库,从而对数据库服务器造成压力,严重情况下导致数据库服务器宕机.

缓存正常的访问:

缓存雪崩之后的访问 

 

解决方案:

  1. 加锁排队:可以通过synchronized进行加锁排队,可以起到缓冲作用,防止大量用户同时访问数据库,但缺点就是增加了系统的响应时间.
  2. 随机化缓存的过期时间:为了避免大量缓存同时过期,可以设置缓存的随机过期时间. 这样就避免了大量的缓存同时过期.
  3. 采用二级缓存:除了redis本身,再去设置一个缓存(例如,hash表,),当redis失效后,先去查询二级缓存.

我们主要采用随机化缓存的过期时间

缓存击穿

缓存击穿是指某个热点缓存,在某一时刻真好失效了,然后此时正好有大量的并发请求,此时这些大量的并发请求将会直接访问数据库,会给数据库造成巨大的压力.这种情况就叫做缓存击穿.

解决方案

  1. 加锁排队: 类似于缓存雪崩的解决方案,都是在查询数据库时加锁排队,缓冲操作请求以此来减少服务器的运行压力。
  2. 设置永不过期:对于某些热点缓存,我们可以设置永不过期,这样就能保证缓存的稳定性,但需要注意在数据更改之后,要及时更新此热点缓存,不然就会造成查询结果的误差。

 我们主要采用设置永不过期

缓存穿透

缓存穿透是指在查询数据库和缓存都没有数据,因为数据库没有数据,出于容错考虑,不会将结果保存到redis中,因此每次请求都会查询数据库,这种情况就是缓存穿透.

 解决方案:

不管有没有查询到数据库,都将结果保存到redis中.

小结

本文为redis最常见的面试题.

如今我努力奔跑,不过是为了追上那个曾经被寄予厚望的自己.

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

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

相关文章

【iOS】MVC

文章目录 前言一、MVC各层职责1.1、controller层1.2、model层1.3、view层 二、总结三、优缺点3.1、优点3.2、缺点 四、代码示例 前言 MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此…

win10自带wifi共享功能

1、按下【wini】组合键打开windows设置,点击【网络和internet】; 2、按照下图,打开个移动热点,设置名称、密码。

【C++】详解std::thread

2023年9月10日,周日下午开始 2023年9月10日,周日晚上23:35完成 虽然这篇博客我今天花了很多时间去写,但是我对std::thread有了一个完整的认识 不过有些内容还没完善,以后有空再更新.... 目录 头文件类的成员类型方法(construc…

LVS DR模式负载均衡群集部署

目录 1 LVS-DR 模式的特点 1.1 数据包流向分析 1.2 DR 模式的特点 2 DR模式 LVS负载均衡群集部署 2.1 配置负载调度器 2.1.1 配置虚拟 IP 地址 2.1.2 调整 proc 响应参数 2.1.3 配置负载分配策略 2.2 部署共享存储 2.3 配置节点服务器 2.3.1 配置虚拟 IP 地址 2.3.2…

iOS IdiotAVplayer实现视频分片缓存

文章目录 IdiotAVplayer 实现视频切片缓存一 iOS视频边下边播原理一 分片下载的实现1 分片下载的思路2 IdiotAVplayer 实现架构 三 IdiotAVplayer 代码解析IdiotPlayerIdiotResourceLoaderIdiotDownLoader IdiotAVplayer 实现视频切片缓存 一 iOS视频边下边播原理 初始化AVUR…

自动化运维——ansible (五十二) (01)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 一、概述 1.1 为什么要用自动化运维软件 1.2 自动化运维 1.3 自动化运维要注意的方面 1.4 自动化运维主要关注的方面 1.5 常见的开源自动化运维软件 1.6 自动化运维软件…

K8S:kubectl陈述式及声明式资源管理

文章目录 一.陈述式资源管理方法1.陈述式资源管理概念2.基本信息查看(1)查看版本信息(2)查看资源对象简写(3)查看集群信息(4)配置kubectl自动补全(5)node节点…

外传-Midjourney的局部重绘功能

今天在抄袭。。。啊不,借鉴 midjourney 官网教程的时候,发现多了一个 局部重绘的功能,意外发觉还不错,分享一下用法。 先给大家说一下,我这段时间都在学习 SD,局部重绘是基操,而 MJ 一直是次次…

为什么要使用设计模式,以及使用设计模式的好处

在软件开发中,衡量软件质量只要包含如下指标: 正确性可维护性可读性可扩展性简洁性可测试性健壮性灵活性可复用性 然而,对于一些刚入行的新程序员来说,往往会注意不到上面这些问题,从而产生了一些让人头皮发麻的烂代…

【动态规划刷题 13】最长递增子序列 摆动序列

300. 最长递增子序列 链接: 300. 最长递增子序列 1.状态表示* dp[i] 表⽰:以 i 位置元素为结尾的「所有⼦序列」中,最⻓递增⼦序列的⻓度。 2.状态转移方程 对于 dp[i] ,我们可以根据「⼦序列的构成⽅式」,进⾏分类讨论&#…

生成树协议 STP(spanning-tree protocol)

一、STP作用 1、消除环路:通过阻断冗余链路来消除网络中可能存在的环路。 2、链路备份:当活动路径发生故障时,激活备份链路,及时恢复网络连通性。 二、STP选举机制 1、目的:找到阻塞的端口 2、STP交换机的角色&am…

MAC M1芯片安装mounty读写移动硬盘中的文件

因为移动硬盘中的文件是微软公司NTFS格式,MAC只支持自己的APFS或者HFS,与微软的NTFS不兼容,所以需要第三方的软件来支持读写硬盘中的文件,经过一上午的折腾,最终选择安装mounty这个免费的第三方软件 工具网址连接&am…

YOLO目标检测——棉花病虫害数据集+已标注txt格式标签下载分享

实际项目应用:目标检测棉花病虫害数据集的应用场景涵盖了棉花病虫害的识别与监测、研究与防治策略制定、农业智能决策支持以及农业教育和培训等领域。这些应用场景可以帮助农业从业者更好地管理棉花病虫害,提高棉花产量和质量,推动农业的可持…

线性代数的本质(二)

文章目录 线性变换与矩阵线性变换与二阶方阵常见的线性变换复合变换与矩阵乘法矩阵的定义列空间与基矩阵的秩逆变换与逆矩阵 线性变换与矩阵 线性变换与二阶方阵 本节从二维平面出发学习线性代数。通常选用平面坐标系 O x y Oxy Oxy ,基向量为 i , j \mathbf i,…

指针进阶(一)

指针进阶 1. 字符指针面试题 2. 指针数组3. 数组指针3.1 数组指针的定义3.2 &数组名VS数组名 3.3 数组指针的使用4. 数组传参和指针传参4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参 前言 指针的主题,我们在初级阶段的《指针》章节已经接…

用滑动条做调色板---cv2.getTrackbarPos(),cv2.creatTrackbar()

滑动轨迹栏作调色板 cv.createTrackbar(‘R’, ‘image’, 0, 255, nothing) 参数:哪个滑动轨迹栏,哪个窗口,最小值,最大值,回调函数 cv.getTrackbarPos(‘R’, ‘image’) 参数:轨迹栏名,窗口…

Nodejs 第十五章(child_process)

child_process 子进程 子进程是Nodejs核心API,如果你会shell命令,他会有非常大的帮助,或者你喜欢编写前端工程化工具之类的,他也有很大的用处,以及处理CPU密集型应用。 创建子进程 Nodejs创建子进程共有7个API Sync…

controller接口上带@PreAuthorize的注解如何访问 (postman请求示例)

1. 访问接口 /*** 查询时段列表*/RateLimiter(time 10,count 10)ApiOperation("查询时段列表")PreAuthorize("ss.hasPermi(ls/sy:time:list)")GetMapping("/list")public TableDataInfo list(LsTime lsTime){startPage();List<LsTime> l…

【实践篇】Redis最强Java客户端(四)之Ression分布式集合使用指南

文章目录 0. 前言1.Ression分布式集合1.1 分布式列表1.1.1 使用场景和实现原理&#xff1a;1.1.2 基本概念和使用方法&#xff1a; 1.2 分布式集合1.2.1 使用场景和实现原理&#xff1a;1.2.2 基本概念和使用方法&#xff1a; 1.3 分布式映射1.3.1 使用场景和实现原理&#xff…

rv1126之isp黑电平(BLC)校准!

前言&#xff1a; 大家好&#xff0c;今天我们继续来讲解isp第二期内容&#xff0c;这期内容主要分三个部分&#xff1a; 1、tunning的工作流程 2、利用RKISP2.x_Tuner来创建tunning工程&#xff0c;并连接上rv1126开发板进行抓图 3、BLC(黑电平校准)的原理和校准方法以及实战…