[Redis] Redis基本命令与数据类型+单线程模型

news2024/11/17 11:49:00

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(96平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. Redis常见指令
  • 2. redis中的常见数据类型
    • 2.1 常见的数据类型
    • 2.2 对数据类型的优化
  • 3. Redis中的单线程模型

1. Redis常见指令

Redis中有上百个指令,但是我们只要记住常见的指令即可,剩下的指令如果不记得,可以去官方网站的文档上查阅即可.

  • Set
    set key value
    我们知道,Redis是以键值对的方式来存储数据的,set用来在Redis中设置键值对,把key和value存入.
    在这里插入图片描述
    其中redis中的value可以支持多种类型的数据结构.
  • get
    get key
    可以根据key获取到对应的value.
    在这里插入图片描述
  • keys
    查询当前服务器上符合条件的所有keys.在keys操作中,我们引入了通配符,通过通配符来描述通配符的模样,就可以把key查询出来.类似与MySQL中的模糊查询.
    keys patten
    其中patten中的通配符可以有多重类型.
    • ? 匹配任意一个字符
    • *匹配0个或任意多个字符
    • [abc]只能匹配abc三个字符中的任意一个字符,其他字符不可以匹配
    • [^e]除了e不能匹配,其他的任意一个字符都可以匹配.
    • [a-c]只能匹配a~c之间的任意一个字符,其他的字符都不可以匹配.

我们给Redis中设置一些key和value

127.0.0.1:6379> set hello 1
OK
127.0.0.1:6379> set hallo 2
OK
127.0.0.1:6379> set hbllo 3
OK
127.0.0.1:6379> set heeeeeeeeello 4
OK
127.0.0.1:6379> set hpllo 5
OK

在这里插入图片描述
我们接下来使用keys指令进行查询

127.0.0.1:6379> keys *
1) "heeeeeeeeello"
2) "hello"
3) "hbllo"
4) "hpllo"
5) "hallo"
6) "key1"
127.0.0.1:6379> keys h?llo
1) "hello"
2) "hbllo"
3) "hpllo"
4) "hallo"
127.0.0.1:6379> keys h*llo
1) "heeeeeeeeello"
2) "hello"
3) "hbllo"
4) "hpllo"
5) "hallo"
127.0.0.1:6379> keys h[a-c]llo
1) "hbllo"
2) "hallo"
127.0.0.1:6379> keys h[^a]llo
1) "hello"
2) "hbllo"
3) "hpllo"
127.0.0.1:6379> keys h[o-p]llo
1) "hpllo"
127.0.0.1:6379> keys h[abc]llo
1) "hbllo"
2) "hallo"

[注意事项] keys命令的时间复杂度是O(N),也就是把redis服务器中的所有key全部都遍历一遍,所以在公司生产环境的服务器上,我们严禁使用keys *这样的指令.这时候就会使得其他客户端的redis指令超时(发生阻塞),超时之后,就会去查询MySQL数据库,这时候MySQL就会收到一大波请求,使得MySQL搓手不及,就容易把MySQL搞挂.

拓展知识: 企业中的几种环境

  1. 办公环境: 办公环境就是公司给你发的那台电脑的本机操作系统的环境.
  2. 开发环境: 在项目未上线之前,我们需要对一款软件进行开发,我们在开发的时候所在的操作系统的环境叫做开发环境.有些情况下,我们会使用本机的环境进行开发,也就是办公环境和开发环境是一样的,但是很多时候,公司也有专门的开发环境的服务器.有些情况下,一些软件的业务逻辑比较复杂,这时候本机环境是带动不起来的,就需要性能更高的服务器来带动.
  3. 测试环境: 测试工程师用来测试项目的操作系统环境.
  4. 生产环境(线上环境): 开发完成之后项目上线,部署到生产环境上之后,项目就可以用来给用户提供服务,为外界用户直接提供服务的环境叫做生产环境,这个环境外界用户可以直接访问到.生产环境会直接影响到公司的营收.
  • exists
    exists key [key...]
    判断一个key是否存在于服务器上.**一次可以查询一个key,也可以查询多个key.最终返回的是存在key的个数,查询的时间复杂度是O(1)
127.0.0.1:6379> exists hello
(integer) 1
127.0.0.1:6379> exists hello hallo
(integer) 2

一般在想要查询多个key是否存在的时候,我们一般不使用分开多次查询的做法,我们一般使用写在一起的写法.这是因为,这其中每一次查询就是一次网络请求,网络会对数据报进行封装和分用,这其中封装和分用会占用网络资源,降低性能,所以我们建议把查询的数据放在一次网络请求中全部查询完成.**其中除了这个操作之外,redis中还有好多指令都支持一次操作多个key的操作.

  • del
    del key [key...]
    删除一个key或者是多个key.
127.0.0.1:6379> del key1 hallo
(integer) 2
127.0.0.1:6379> del hpllo
(integer) 1
127.0.0.1:6379> keys *
1) "heeeeeeeeello"
2) "hello"
3) "hbllo"

这里注意,在redis中删除键值对并不想没有MySQL中那样危险,即使不小心误删了之后依然可以从MySQL中同步过来,但是redis一次不可以删除大量的数据,这样在从MySQL恢复数据的时候,就会向MySQL发送大量请求,很容易把MySQL搞挂.

  • expire
    expire key seconds
    给一个key设置过期时间,其中时间是秒级别.这个key必须在redis中存在.在给一个key设置过期时间之后,这个key就会在指定的时间之后过期.

如果想设置毫秒级别,可以用pexpire key 时间来设置.

127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> EXPIRE key1 10
(integer) 1
127.0.0.1:6379> get key1
"value1"
127.0.0.1:6379> get key1
(nil)

这个功能使用的场景非常广泛,比如我们常用的手机验证码,还有美团优惠劵的到期时间,都是使用了redis的过期时间.

  • ttl
    ttl key
    获取指定key的过期时间,时间为秒级,如果想获取毫秒级别的,可以使用pttl.
    其中,如果key不存在过期时间的时候,返回-1,如果没有找到这个key,返回-2
127.0.0.1:6379> keys *
1) "heeeeeeeeello"
2) "hello"
3) "hbllo"
127.0.0.1:6379> ttl hello
(integer) -1
127.0.0.1:6379> set key1 val1
OK
127.0.0.1:6379> EXPIRE key1 10
(integer) 1
127.0.0.1:6379> ttl key1
(integer) 5
127.0.0.1:6379> ttl key1
(integer) -2

[常考面试题] redis中的key的过期时间是基于什么来实现的呢?
redis中有好多的键值对,redis怎么知道哪个过期了,哪个没有过期呢?绝对不是一个一个的遍历来实现的,这样的效率非常低下.redis采用了一下的策略:

  1. 惰性删除
    假设一个key已经到了过期的时间,但是我们先不要删除这个key,当下次访到这个key之后,查看这个key是否过期,如果过期了,就删除掉.
  2. 定期删除
    redis会对过期的key进行定期删除,但是这里的删除并不是吧key全部遍历之后在找到过期的key进行删除,而是抽取一些key来判断是否过期,之后进行对应的删除.
  3. 内存淘汰策略
    我们后面再详细介绍.

举例说明: 去商店买东西
当我们拿了一件商品之后,在结账的时候,我们发现这件商品过期了,这时候我们会告诉老板这件商品过期了,老板这时候就会把这件商品扔掉,这就是惰性删除.其次老板会定期抽取一部分的商品来查看商品是否过期,过期就会人掉,这就是定期删除.

[注意事项] 网上有很多人说redis的过期机制是定时删除,在redis中有一个定时器,定时器到达时间之后,redis就会将之删除,但是我们注意,redis并没有采取这种删除的方式.

拓展: 比较高效的定时器实现方式

  1. 优先级队列方式
    这个方式我们在之前多线程的部分曾经向大家介绍过.
    首先我们按照key的过期时间把这些数据组成一个优先级队列,过期时间越短,优先级越高,之后就会有一个线程去不停地检查队首的元素,只要队首的元素到达过期时间,我们就把队首结点和最后一个结点进行交换,之后删除最后一个结点,之后再对这个优先级队列进行向下调整.
    当然该线程也不是一直在对一个队首的元素进行扫描,这样就会出现忙等的状态,我们会根据过期时间设置一个线程休眠的时间,在时间差不多的时候,就会检查一次队首的元素是否过期,之后如果等待的中间来了新的请求,就唤醒一次线程,顺便检查一下队首的元素是否过期.
  2. 基于时间轮的方式实现定时器
    我们可以把时间轮上的时间划分为多个小段(具体的划分粒度,看具体的业务场景),其中每一个小段上都挂着一个链表,这个链表中是需要执行的任务,时间轮上有一个指针,指针每隔一段时间就需要向下走一格.没走一个,就要检查链表中有没有需要执行的任务.
    在这里插入图片描述
  • type
    type key
    获取该key对应value的数据类型.虽然redis中的key只有String类型,但是value可以有多种类型.常见的数据类型有:string ,list ,set ,zset ,hash, stream,如果没有这个key的时候,返回none.具体如何创建不同的数据类型,我们后面再详细介绍.
127.0.0.1:6379> type hello
string
127.0.0.1:6379> type hallo
none

2. redis中的常见数据类型

2.1 常见的数据类型

redis目前支持的数据类型有10种,常用的数据结构有5种,剩下的5种事针对特殊场景的特殊的数据结构.
在这里插入图片描述
上面的几种数据类型,首先是字符串,对应的是我们java中的String,其次Hash表对应的是java中的HashMap,列表对应的是Java中的List,集合对应的是Java中的Set,有序集合比较特殊,其中除了存储成员之外,还会存储该成员(member)的权重(score),有点像Java中的PriorityQueue.

2.2 对数据类型的优化

有时候redis在实现这些数据结构的时候,底层并不一定使用的是相应的数据结构,会在对应的数据结构上视情况进行一些优化.但是redis承诺,你在用起来的时候,和原来的数据结构是一样的效果.
比如我们现在创建的一个key其中的数据结构是Hash表,但是在数据比较少的时候,也在底层也不一定使用的是Hash表来实现的,但是我们用起来和Hash表没有什么区别,时间复杂度都是O(1).

这和前段时间的"指鼠为鸭"事件有些相似,虽然说外表长得不太像鸭脖,但是商家承诺,这个"鸭脖"吃起来和正常的"鸭脖"没有什么区别

具体优化情况如下:
在这里插入图片描述

  • raw
    这个是最基本的字符串,类似与Java中的byte[ ]数组.
  • int
    redis有时会实现一些计数的功能,当value是整数的时候,redis就会直接用int类型来保存.
  • embstr
    当字符串比较短的时候,redis就会把字符串优化为embstr.
  • hashtable
    最基本的hash表,这里不要误会,这和Java中那个线程安全的HashTable不一样.
  • ziplist
    当hash表中的元素比较少的时候,会被压缩为ziplist.
  • linkedlist
    链表
  • ziplist
    压缩列表,但是在redis3.2之后就引入了quicklist,它兼顾了linkedlist和ziplist两者的优点.
  • intset
    当set中存储的都是整数的时候,会被优化为intset.
  • skiplist
    跳表,这个跳表有点类似与链表中的复杂链表,结点中存储着下一个结点的引用,然后还存储着随机一个结点的引用.

我们可以使用object encoding来查看value中存储数据的实际类型.

127.0.0.1:6379> set key1 1
OK
127.0.0.1:6379> object encoding key1
"int"

3. Redis中的单线程模型

redis中的单线程模型指的就是,redis在处理命令的时候,都只使用一个线程来处理,说redis只有单线程,其实也有使用多线程的地方,在网络io中使用的就是多路复用的情况.
如果redis不使用单线程的情况下,就会出现线程安全问题.假如有两个客户端在连接redis服务器,他们同时向redis服务器发送了一个incr请求.
在这里插入图片描述
这时候就会出现两个客户端同时对一个变量进行++的操作.客户端先获取到服务器的value值,两个线程都获取到的是0,在线程中++之后都是1,之后再把value++之后的值赋值给value,此时两个线程++之后的值都是1,赋值之后也自然就是1.
幸好我们的redis服务器是单线程模式的,它保证了这两个客户端发送过来的请求是串行化执行的.宏观上redis同时处理了客户端的请求,微观上是串行化执行的.
在这里插入图片描述
在这里插入图片描述

就像我们在食堂打饭一样,假如说一个食堂只有一个窗口开放,这时候学生和老师就不得不排队一个一个的打饭.

因为redis是使用单线程模型的,所以我们在使用redis指令的时候要额外小心,避免一个命令长期占用redis服务器的线程.

[面试题] 既然redis是单线程的,为什么redis还是如此之快呢?

  • 首先,redis是在内存中存储数据的,内存中存储的数据要相对于硬盘中要快好几个数量级.
  • 其次,redis的业务功能主要突出的就是一个"短平快".业务逻辑比较简单.所以比较快.
  • 既然说redis是单线程的,它也避免了多线程中的线程竞争现象,线程竞争的现象会拖慢执行的效率.
  • 处理网络请求io的时候,使用的是epoll多路复用的机制.就是一个线程管理了多个Socket.

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

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

相关文章

【springboot】使用AOP

目录 1. 添加依赖2. 创建切面类1. 创建切面类2. 切点表达式3. 增强方法 3. 开启AOP4. 创建控制类5. 测试 1. 添加依赖 <!-- AOP依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop<…

【iOS】MVC入门

【iOS】MVC模式的学习 文章目录 【iOS】MVC模式的学习前言MVC模式概念MVC的交流模式MVC的一个简单实践Model层View层Controller层 MVC的优点与缺点总结 前言 笔者在暑假的学习中完成了一些小项目&#xff0c;这些小项目中间有时候出现了一个小bug都要寻找很久&#xff0c;而且会…

前端学习笔记-Web APls篇-05

Bom操作 1.Window对象 1.1BOM(浏览器对象模型&#xff09; BOM(Browser Object Model ) 是浏览器对象模型 window对象是一个全局对象&#xff0c;也可以说是JavaScript中的顶级对象像document、alert()、console.log()这些都是window的属性&#xff0c;基本BOM的属性和方法都…

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT&#xff0c;这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频&#xff0c;并利用 SAM 2 进行 3D 空间分割&#xff0c;无需进一步训练或 2D-3D 投影。 我们的框架…

ML19_GMM高斯混合模型详解

1. 中心极限定理 中心极限定理&#xff08;Central Limit Theorem, CLT&#xff09;是概率论中的一个重要定理&#xff0c;它描述了在一定条件下&#xff0c;独立同分布的随机变量序列的标准化和的分布趋向于正态分布的性质。这个定理在统计学中有着广泛的应用&#xff0c;尤其…

算法篇_C语言实现霍夫曼编码算法

一、前言 霍夫曼编码&#xff08;Huffman Coding&#xff09;是一种广泛使用的数据压缩算法&#xff0c;特别适用于无损数据压缩。它是由David A. Huffman在1952年提出的&#xff0c;并且通常用于文件压缩和传输中减少数据量。霍夫曼编码的核心思想是使用变长编码表对源数据进…

提升效率必备!学习awk命令,轻松搞定数据

在日常的工作中&#xff0c;无论是数据处理、日志分析&#xff0c;还是格式化输出&#xff0c;AWK命令都是不可或缺的利器。AWK是一种强大的文本处理工具&#xff0c;能让你轻松处理复杂的数据&#xff0c;提升工作效率。本文将为你介绍AWK的基本功能及一些实用场景&#xff0c…

树 --- 二叉树

树的物理结构和逻辑结构上都是树形结构。 树形结构&#xff1a;由一个根和若干个子节点组成的集合。 最外围的为叶子节点&#xff1a;只有前驱而没有后继。 &#xff08;一&#xff09;树的性质 • ⼦树是不相交的 • 除了根结点外&#xff0c;每个结点有且仅有⼀个⽗结点 •…

每天五分钟玩转深度学习框架PyTorch:将nn的神经网络层连接起来

本文重点 前面我们学习pytorch中已经封装好的神经网络层,有全连接层,激活层,卷积层等等,我们可以直接使用。 如代码所示我们直接使用了两个nn.Linear(),这两个linear之间并没有组合在一起,所以forward的之后,分别调用了,在实际使用中我们常常将几个神经层组合在一起…

【EI会议征稿通知】第十一届机械工程、材料和自动化技术国际会议(MMEAT 2025)

第十一届机械工程、材料和自动化技术国际会议&#xff08;MMEAT 2025&#xff09; 2025 11th International Conference on Mechanical Engineering, Materials and Automation Technology 本次大会旨在汇聚全球机械工程、材料科学及自动化技术的创新学者和行业专家&#xff0…

使用 BentoML快速实现Llama-3推理服务

介绍 近年来&#xff0c;开源大模型如雨后春笋般涌现&#xff0c;为自然语言处理领域带来了革命性的变化。从文本生成到代码编写&#xff0c;从机器翻译到问答系统&#xff0c;开源大模型展现出惊人的能力&#xff0c;吸引了越来越多的开发者和企业投身其中。 然而&#xff0…

Subclass-balancing Contrastive Learning for Long-tailed Recognition

文章目录 SCL(supervised contrastive learning)1. 监督对比学习&#xff08;SCL&#xff09;的基本概念2. SCL的损失函数3. 长尾数据集的问题4. k-正样本对比学习&#xff08;KCL&#xff09;的引入5. 总结 SBCL举例说明&#xff1a;狗的分类 关键点&#xff1a;划分为多个子类…

4-1.Android Camera 之 CameraInfo 编码模板(前后置摄像头理解、摄像头图像的自然方向理解)

一、Camera.CameraInfo Camera.CameraInfo 是用于获取设备上摄像头信息的一个类&#xff0c;它提供摄像头的各种详细信息&#xff0c;例如&#xff0c;摄像头的方向、是否支持闪光灯等&#xff0c;以下是它的常用属性 static int CAMERA_FACING_BACK&#xff1a;表示设备的后置…

Protobuf库的使用

文章目录 Protobuf是什么Protobuf使⽤流程介绍ProtoBuf的使用创建.proto⽂件指定proto3语法package声明符定义消息&#xff08;message&#xff09;编译contacts.proto⽂件命令如下&#xff1a;序列化与反序列化的使⽤ Protobuf是什么 ProtoBuf&#xff08;全称ProtocolBuffer…

数字 FPV 革命 – DJI、Leadcore 和 Artosyn 的三角关系。

人们对 DJI、Caddx FPV 以及 HDZero 等公司最近推出的数字 FPV 系统的起源进行了大量的猜测和推测。随着 Avatar 系统的发布&#xff0c;也有许多人认为它要么使用与 DJI 相同的芯片组&#xff0c;要么是复制品或克隆品。在本文中&#xff0c;我将尝试揭开这一切的神秘面纱&…

python spider novel

python msedgedriver 获取小说 声明&#xff1a;只为学习/练习技术 from lxml import etree from selenium import webdriver from selenium.webdriver.edge.service import Service from selenium.webdriver.edge.options import Optionsimport time# 初始化EdgeOptions, 以…

【系统规划与管理师】【案例分析】【考点】【答案篇】第4章 IT服务规划设计

【问题篇】☞【系统规划与管理师】【案例分析】【考点】【问题篇】第4章 IT服务规划设计 【移动端浏览】☞【系统规划与管理师】【案例分析】【模拟考题】章节考题汇总&#xff08;第4章&#xff09;&#xff08;答案篇&#xff09;&#xff08;共38个知识点&#xff09; 第4章…

《数字信号处理》学习05-单位冲击响应与系统响应

目录 一&#xff0c;单位冲激响应 二&#xff0c;LTI系统对任意序列的系统响应 三&#xff0c;LTI系统的性质 通过上一篇文章《数字信号处理》学习04-离散时间系统中的线性时不变系统-CSDN博客的学习&#xff0c;我已经知道了离散时间线性时不变系统&#xff08;LTI&#x…

基于 jenkins 的持续测试方案

CI/CD Continuous Integration; Continuous Deployment; 持续集成&#xff0c;将新代码和旧代码一起打包、构建&#xff1b;持续部署&#xff0c;将新构建的包进行部署&#xff1b;持续测试&#xff0c;将新代码、新单元测试一起测试&#xff1b;方案&#xff1a; 公有云DevO…

Python 控制Chrome浏览器使用Selenium4操作点击百度搜索

前面我们讲到如何安装Selenium和ChromeDriver来驱动打开网页,现在我们有一个目的就是使用python来控制chrome浏览器打开百度并搜索 直接先上调试好的代码 from time import sleepfrom selenium import webdriver from selenium.webdriver.common.keys import Keys from selen…