Redis(详细)

news2025/1/20 22:48:16

目录

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.coloradmin.cn/o/996968.html

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

相关文章

vue学习之属性绑定

内容渲染 采用 &#xff1a;进行属性渲染创建 demo3.html,内容如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&…

Kafka/Spark-01消费topic到写出到topic

1 Kafka的工具类 1.1 从kafka消费数据的方法 消费者代码 def getKafkaDStream(ssc : StreamingContext , topic: String , groupId:String ) {consumerConfigs.put(ConsumerConfig.GROUP_ID_CONFIG , groupId)val kafkaDStream: InputDStream[ConsumerRecord[String, Strin…

centos7安装airflow2.7.1

python3安装 版本 Python-3.9.17 ./configure --prefix/usr/local/python3 make && make install随后用ln -s短链接python3和pip3 airflow安装 版本2.7.1 export AIRFLOW_HOME~/airflow编写一个sh文件 AIRFLOW_VERSION2.7.1# Extract the version of Python you…

C 风格文件输入/输出---直接输入/输出---(std::fread)---(std::fwrite)

C 标准库的 C I/O 子集实现 C 风格流输入/输出操作。 <cstdio> 头文件提供通用文件支持并提供有窄和多字节字符输入/输出能力的函数&#xff0c;而 <cwchar>头文件提供有宽字符输入/输出能力的函数。 从直接输入/输出 文件读取 std::fread 从给定输入流 stream …

基于ESP32设计可以通过 WiFi 控制的基于 ESP32 的定制四轴飞行器

介绍 我想选择一个涉及物联网概念的项目,例如无线通信和服务器端脚本编写。我最终决定建造一架四轴飞行器,使用定制的机载飞行控制器进行飞行,该控制器通过 WiFi 从触摸屏平板电脑接收操纵命令。该项目的最终目标是让四轴飞行器从相机图像中跟踪移动物体并跟随它。 硬件 对…

正则表达式:实数

正则表达式&#xff1a;实数 校验字符串&#xff0c;为有效的实数。 可以为&#xff1a;正数或负数&#xff1b; 可以为&#xff1a;整数或小数&#xff1b; 但是&#xff0c;不可以为非数值型的字符串&#xff0c;不可以是一连串的“0” 。 原始正则表达式 ^-?(0|[1-9]\d…

高可用Kuberbetes部署Prometheus + Grafana

概述 阅读官方文档部署部署Prometheus Grafana GitHub - prometheus-operator/kube-prometheus at release-0.10 环境 步骤 下周官方github仓库 git clone https://github.com/prometheus-operator/kube-prometheus.git git checkout release-0.10 进入工作目录 cd kube…

GDB的C++调试方法

本文记录基础的GDB调试过程&#xff0c;包含指令如下&#xff1a; 文章目录 准备编译文件GDB启动GDB开启代码行设置断点运行程序查看pc的指令查看监视的变量以及断点设置快照checkpoint实验1实验2 nextnextistepx/i $pcfinishinfo break 和 delete Numrefbreak col. if condit…

浅谈原型链

一.在掌握原型链之前首先要了解这三点 1.每个函数都有prototype这个属性我们称为原型对象 2.每个对象都有__proto__这个属性 3.对象的__proto__可以访问原型对象上的方法和变量,如果访问不了,就会向上进行查找,直到找不到为止,会出现报错的情况l。 二.例子 1.代码: let arr …

云计算与虚拟化

一、概念 什么是云计算&#xff1f; 云计算&#xff08;cloud computing&#xff09;是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;通过多部服务器组成的系统进行处理和分析这些小程序得到结果…

基于folium绘制黑河腾冲线,胡焕庸线

背景 黑河腾冲线&#xff0c;又名胡焕庸线&#xff0c;是我们人口密度分布的的近似分界线。今天基于folium&#xff0c;使用python来绘制这条线。 代码 # -*- coding:UTF-8 -*-# region 引入必要依赖 from selfPyTools.mapModule import * # endregion# 准备一个地图类对象,…

学习Bootstrap 5的第十一天

折叠 基础的折叠 在 Bootstrap 5 中&#xff0c;折叠效果可以通过添加特定的属性和类来轻松实现内容的显示和隐藏。具体步骤如下&#xff1a; 1、创建一个可折叠的元素&#xff0c;通常使用 <div> 标签&#xff0c;并为其添加 .collapse 类&#xff0c;以指示它是可折…

智能化时代前端开发使用Amazon CodeWhisperer在vscode中编写代码

目录 一、概述 1.Amazon CodeWhisperer使用您的 AI 编码配套应用程序更快、更安全地构建应用程序。 2.CodeWhisperer 经过数十亿行代码的训练&#xff0c;可以根据您的评论和现有代码实时生成从代码片段到全函数的代码建议。绕过耗时的编码任务&#xff0c;加速使用不熟悉的 …

【自学开发之旅】Flask-数据查询-数据序列化-数据库关系(四)

db.session ProductInfo.query filter() 灵活查询 filter_by() limit() 限制输出条目 offset() 偏移量 order_by() 排序 group_by() 分组聚合 <模型类>.query.<过滤方法> 过滤方法 查询方法 “牛”字开头且&#xff08;“,”默认&#xff09;价格大于5的 &g…

JS判断当前是早上,中午,下午还是晚上

<!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title></head><body><div></div><script>function getTimeState() {// 获取当前时间let timeNow new Date();// 获取当前小时let…

Pytest系列-fixture的详细使用和结合conftest.py的详细使用(3)

介绍 前面一篇讲了setup、teardown可以实现在执行用例前或结束后加入一些操作&#xff0c;但这种都是针对整个脚本全局生效的。 Fixture是pytest的非常核心功能之一&#xff0c;在不改变被装饰函数的前提下对函数进行功能增强&#xff0c;经常用于自定义测试用例前置和后置工作…

【C++】string类模拟实现上篇(附完整源码)

目录 前言1. string的基本结构2. 构造函数、析构函数2.1 构造函数的实现2.1.1带参构造函数 2.2析构函数2.3无参构造函数2.4无参和带参构造函数合并 3. string的遍历3.1 operator[ ]3.2迭代器模拟实现 (简单实现&#xff09;3.3 const迭代器模拟实现 4. 数据的增删查改4.1 reser…

最经典的解析LSA数据库(第六课)

初步认识OSPF的大致内容(第三课)_IHOPEDREAM的博客-CSDN博客 1 OSPF 工作过程 建立领居表 同步数据库 今天来 说一说数据库概念 计算路由表 2 什么是数据库&#xff1f; 数据库是一个组织化的数据集合&#xff0c;用于存储、管理和检索数据。它是一个可访问的集合&#x…

[SICTF 2023 #Round2] Crypto,PWN,Reverse

似乎很久没写了。 周五到周日&#xff0c;两天的这个比赛&#xff0c;有些东西还真是头回用&#xff0c;值得纪录一下。 Crypto 密码这块这届还是比较简单的&#xff0c;没有复杂的题&#xff0c;但量大分多。 【签到】古典大杂烩 给了一堆emoji的图 &#x1f429;&#x…

英国私校的艺术奖学金有哪些?申请要求和申请流程详解!

众所周知&#xff0c;英国私校不仅学术拔尖&#xff0c;在对学生艺术方面的培养也是毫不逊色的。几乎打开每一所英国私校的官网&#xff0c;都可以看到学校罗列的提供的各类课外艺术活动的精彩照片。      每个英国私校除了课后开设的五花八门的兴趣课外&#xff0c;还有各…