Redis的一些数据类型(一)

(一)数据类型

   我们说redis是key value键值对的方式存储数据,key是字符串,而value是一些数据结构,那今天就来说一下value存储的数据。

  

   我们数据结构包含,String,hash,list,set和zest但是在redis内部真的就是按这些数据结构存储的嘛?

   很明显上面的图告诉我们不是,我们在内部是由不同的内存编码来保存数据的,但是时间复杂度是跟我们的数据结构一样的,那我们先来看一下第一个

1.String

String数据结构内部编码由raw,int,embstr

raw:存储一些比较短的字符串

int:我们redis里没有存储整形数据的方法,所以我们一般会用字符串来保存整型数据,所以我们String里有一个内存编码int,如果我们存入整型数据的话,内存编码就是int类型来保存数据。

embstr:存储一些比较长的字符串

2.hash

hashtable:内部就是一个哈希表

ziplist:是一个压缩列表

3.list

内部包含

linkedlist:链表(不是很节省空间)但是效率比较高

ziplist:压缩列表,比较节省空间,但是效率不高

我们redis3.2开始引入了新的实现方式quicklist,同时兼顾了linkedlist和ziplist,其实quicklist就是个链表,每个元素又是一个ziplist,同时节省了空间和效率

4.set

hashtable:就是一个哈希表

intset:集合中存的元素都是整数

5.zset

skiplist:跳表,也是链表,每个节点上有多个指针域,使用这些指针域的指向可以做到从跳表上查询的时间复杂度是o(logn)

查询内部编码方式

   使用object encoding key,用来查看key对应的value的实际编码方式(redis会自动根据实际情况,自动适应的)

redis单线程模式

   我们之前说redis只使用一个线程来处理所有的命令请求,但是redis又很快,这看起来是相互矛盾的,因为多个线程一起执行怎么会比单线程还慢呢?

   实际上redis确实只有多个线程,但是是用来处理网络IO

   当我们两个客户端同时发起上述的请求,此时我们会产生疑问是否会产生线程安全问题

   答案是不会,因为我们多个请求同时到达redis服务器,需要在队列中排队,再等待redis服务器一个一个取出里面的命令再执行,类似于实现了一个阻塞队列,微观上讲,redis服务器是串行执行这个多个命令的

   而他快的原因就是因为他的业务逻辑都是些很简单的操作,不是很消耗cpu资源,但是redis由于是单线程模型就必须要小心,某一些操作占用时间太长了阻塞其他命令的执行,而且redis是访问内存数据库访问硬盘,并且正因为他是单线程模型,所以省去了一些线程竞争的开销

   处理网络IO的时候是使用了类似epoll这样的IO多路复用机制

   这里我们说一下什么是IO多路复用,这里我们在网络原理那几篇博客中说过,简单来说就是一个线程管理多个socket

    我们来回顾一下,TCP客户端需要有一个sever socket,然后会给我们客户端分配一个socket,如果我们多个客户端同时访问,同时就有多个socket,但这些socket大多数情况下并不是一直都在传输数据,很多情况下socket都是静默的,因为没有数据要进行传输(可能在等待用户的输入),但也有一些socket是活跃的,我们之前实现的时候因为每个客户端都要分配一个线程,客户端多了,线程就多了,系统开销就会变大,所以我们当时有两个方案,一个就是引入协程(更小的线程),一个就是使用IO多路复用

  那我们说IO多路复用就是一个线程管理多个socket,那对于这些socket也是有要求的,我们需要这几个socket交互不频繁,大部分时间都在等待,如果这几个socket的交互都特别频繁,那我们还是要使用多个线程的

 (二)String类型

    我们redis中的string是直接按照二进制数据的方式存储的不做任何的编码转换,存什么取什么(mysql中的默认字符集是拉丁文,所以我们插入中文会失败),因为是二进制方式存储的,所以我们也可以存一些音频和图片等(但不可以存太大的)

1.set和get

   我们看后面的nx和xx,nx标识如果key不存在才设置value存在就不设置(返回nil),xx标识如果key存在那就设置不存在就不设置(返回nil),ex和px是设置过期时间单位是秒和毫秒。

  redis文档给出的语法格式说明【】是独立的单元,可以同时存在多个【】,但是|是表示或,一个单元只能出现一个

  我们现在库上有很多操作,我们可以有一个操作可以删除所有数据,就是flushall(我们一般不使用)

get的使用就很简单,但是get只是支持字符串类型的value,如果value是其他的类型,get就会出错

2.MSET和MGET

   这两条命令一次可以操作多组键值对,我们之前也说过一次在exists查询多个key时说,我们redis是通过网络传输数据的,那如果一次传一个数据传多次就会导致我们大部分时间浪费在网络通信中,就会导致我们效率变低,但是如果我们一次传多个数据,就可以很好的节省我们的网络开销

   

   但是还是我们说的那个问题,redis是单线程模型,如果我们一次性传太多的数据,就会导致我们的redis会花很长的时间进行处理,就会导致其他的请求等待,可能会引发一系列的问题

   我们这里的时间复杂度都是O(1)

3.incr和incrby

   incr就是针对value的值+1,我们这里的value必须要是整数,如果是小数,需要我们是以哦那个incrfloat可以针对小数进行加减操作,我们这里的incr操作的key如果不存在,我们就会把这个key的value当作0来使用

  incrby就是把+1操作换成任意的一个整数,当然也可以是小数,但是这种减法我们会更适用于下一条指令

我们的返回值就是修改后的值

4.decr和decrby

   与上条指令类似,就是把+变成了-,我们要注意value中的值必须要是整数,在64位范围内,如果这个key对应value不存在就会当0处理

decrby就是-n的操作

上述的操作时间复杂度都是o(1)

5.append字符串拼接

   append是用来拼接字符串的,返回值是拼接后的长度,单位是字节,在redis中也是按照utf8进行编码所以一个汉字通常是三个字节

6.setrange设置一定范围的字符

默认从1开始设置,但是我们可以设置偏移量

但是如果是一个中文字符串就可能会出问题,如果我们凭空生成了一个字节,那么就会自动生成一个0x00

返回值是修改后的长度

7.strlen计算value中字符串长度

返回值就是value的长度单位是字节

8.getrange 

我们可以设置获取的头和尾通过设置start和end(都是闭区间)

  这里的start和end就类似于下标,但是redis下标可以支持负数,-1就表示倒数第一个元素,如果我们保存的是汉字,就会对字符串进行切分,到时候就不一定是一个完整的汉字了

9.String的编码方式

   我们之前说String内部有三种编码方式,并且可以通过object encoding+key来查询内部编码方式,那么我们现在就来通过指令来看一下

1)int

首先内部编码为int:8个字节的长整型

如果我们存的使一个整数,那么内部就会变为int,但是我们强调必须是整数,如果是小数会怎么样?

可以看到,如果我们的存一个小数内部编码会变为emstr(用来存较短的字符串),所以整数用int存是方便我们进行算术运算的,小数用字符串来存,那么我们想要进行运算,就需要讲字符串转为小数,运算后再保存

2)embstr

如果字符串的长度小于某个数,内部就会自动编码为emstr,具体的数字默认为39

3)raw

如果字符串长度比较大,内部就会自动编码为raw

10.String的一些应用场景

  1)缓存功能

这是我们redis作为缓存的模型,因为mysql从硬盘读取数据会比较慢,但是如果同时有很多请求,就会导致mysql出错,所以我们引入了redis,之前的博客也有详细说到过

   那我们String具体在这里有什么用呢?我们说key中存的一定是String类型的数据,我们先来看一段伪代码

我们让用户传一个id,然后我们在内部拼接一个类似报头一样的字符串,这样我们就能清楚的知道,在redis中,这是什么数据,如果我们不加,我们很可能存在redis中存储了用户的id(key)商品的id(key)如果统一传来一个id,我们也无法知道具体是什么类,当然我们也不建议这个名称过长,会影响我们redis的一个效率

2)计数

   我们上面说到内部编码的时候说String可以存整型数据,所以我们就可以把redis当作一个计数的基础工具,因为redis比较快,所以可以用来实现快速计数,查询缓存等功能,就比如我们播放一个视频,那我们视频的播放量就需要立刻+1

但是也有一些问题,就是redis不擅长统计数据,如果我们要通过value里存的整数来统计一些数据,就会比较麻烦,就比如我们统计播放量前10的数据,如果我们使用mysql,直接一个orderby,一个limite就可以直接查询到

   所以我们需要一个统计数据的仓库,可以是mysql也可以是别的,来将播放量同步到其他数据源,由这个仓库来统计数据,这里我们写入统计数据的仓库的方式是异步的,也就是说,我们不需要获取数据就立刻给这个统计数据的仓库,等双方都不是很忙的时候,再进行同步就可以

3)session

我们在之前的博客里也说到了好几次session,他通常跟cookie一起出现

session用来存储服务器数据,cookie用来存储客户端数据(都是通过键值对的方式存储)

   我们客户端向服务器发起了请求之后服务器要存储我们的数据,就存到了session中,然后给我们返回一个token(内部可能是sessionid也可以是别的,但是一定能通过这个找到对应的session),我们客户端通常就会把这个token中的数据存储到cookie中,然后我们下次请求服务器的时候,就会携带着cookie,服务器拿到cookie拿到sessionid,然后再获取对应的数据,那这个作为标识放到token中的数据,就是一个字符串

那这种通过负载均衡分配到不同服务器上的模型,如果只是我们上述说的过程,就不是很够用了,因为我们无法保证每一次访问的都是那一个服务器,所以我们需要再引入一个redis

我们通过引入个redis服务器来存储所有session,这样我们每个web服务器的session都会放到redis中,客户端拿着cookie来查询时,我们就会再访问redis寻找对应的session

4)手机验证码

    我们现在每次登录一个东西,会让用户输入手机号并且发送一个验证码,通过验证码进行验证,确定是不是用户本人,但是验证码每多久才可以获取一次,并且有过期时间,这时我们就可以很好的利用我们的setex key +时间+value的指令

我们也可以验证短信,把收到的验证码提交,系统来进行验证

这是伪代码的实现

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

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

相关文章

macOS与Ubuntu虚拟机使用SSH文件互传

1.ubuntu配置: 安装openssh服务: sudo apt-get install openssh-server -y 查看服务启动状态: systemctl status ssh 2.macOS使用scp连接ubuntu并发送文件 查看ubuntu IP : ifconfigmacOS终端连接ubuntu : sc

第五篇:Linux进程的相关知识总结(1)

目录 第四章:进程 4.1进程管理 4.1.1进程管理需要的学习目标 4.1.1.1了解进程的相关信息 4.1.1.2僵尸进程的概念和处理方法: 4.1.1.3PID、PPID的概念以及特性: 4.1.1.4进程状态 4.1.2进程管理PS 4.1.2.1静态查看进程 4.1.2.1.1自定义…

基于AI网关的智慧煤矿安全监测应用

煤矿安全一直是矿业管理的重中之重。由于煤矿环境的恶劣与复杂性,例如工作中间环节多、设施设备多样且集中、空间狭小、环境闭塞、有害气体隐患、粉尘聚集等,针对煤矿的安全监测和防范时常面临着极大的挑战。 随着AI技术的发展与普及,依托AI实…

优青博导团队指导-组蛋白甲基化修饰、实验设计、实验结果分析、测序分析及SCI论文辅助,精准高效,为农医学科研保驾护航!

组蛋白甲基化修饰工具(H3K4me3 ChIP-seq) 组蛋白甲基化类型也有很多种,包括赖氨酸甲基化位点H3K4、H3K9、H3K27、H3K36、H3K79和H4K20等。组蛋白H3第4位赖氨酸的甲基化修饰(H3K4)在进化上高度保守,是被研究最多的组蛋白修饰之一。

gnome Files管理文件学习

Files文件夹页可以非常高效的使用,接下来介绍一些有用的快捷命令和tricks 首先是快捷键: **Ctrl T**Ctrl N**Ctrl WClose window or tab**Ctrl FSearch**Ctrl LEnter location**BackspaceGo Back to a Previous FolderCtrl Zoom inCtrl -Zoom outCtrl 0…

MISC - 第四天(OOK编码,audacity音频工具,摩斯电码,D盾,盲文识别,vmdk文件压缩)

前言 各位师傅大家好,我是qmx_07,今天继续讲解MISC知识点 FLAG 附件是一张图片,尝试binwalk无果 使用StegSolve工具Data Extract查看时 发现PK字段,是大多数压缩包的文件头点击Save Bin保存zip文件 解压缩失败使用修复软件:htt…

六西格玛绿带培训机构哪家好?记住这2点很重要

在探讨“六西格玛绿带培训机构哪家好”这一议题时,我们不得不深入剖析当前市场上纷繁复杂的培训机构,以及如何选择一家既能提供高质量教学,又能满足个人职业发展需求的机构。六西格玛作为一套严谨的管理方法论,旨在通过减少变异、…

directx修复工具怎么用?不懂dll缺失怎么修复?本文整理了详细的dll修复方法!

DLL错误,相信很多小伙伴都头疼这个问题。 在电脑上运行程序或者打开某个文件时,是不是会看到“缺少xxx.dll”的错误弹窗?这时候大部分小白用户都是懵的,不知道这是出了什么问题,又该如何解决。 dll文件在电脑领域中扮…

某易易盾验证码逆向

注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架,本文网址如下,使用base64解码获得: aHR0cHM6Ly9kdW4uMTYzLmNvbS90cmlhbC9qaWdzYXc= ———————————————— 我们来看一下接口请求,这里关注的重点就…

9/24作业

1. 分文件编译 分什么要分文件编译? 防止主文件过大,不好修改,简化编译流程 1) 分那些文件 头文件:所有需要提前导入的库文件,函数声明 功能函数:所有功能函数的定义 主函数:main函数&…

【解决虚拟机NAT联网】收藏这份教程就不用再辛苦找了

网上的教程一大堆,看的云里雾里,对于一个小白来说这里看懂了,下一步又看不懂了,一模一样的去设置也不一定成功。 解决办法01 恢复默认设置: 首先公布一个最基础的最直接最有效的恢复网络的办法: 关闭虚拟…

Serverless and Go

本篇内容是根据2019年8月份Serverless and Go音频录制内容的整理与翻译, Johnny、Mat、Jaana 和特邀嘉宾 Stevenson Jean-Pierre 讨论了 Go 世界中的Serverless。什么是Serverless,Serverless适用于哪些用例,有哪些权衡,以及如何在Serverles…

keepalived+lvs集群

目录 一、环境 二、配置 1、master 1.在master上安装配置Keepalived 2.在master上修改配置文件 2、backup 1.在backup(192.168.229.12)上安装keepalived 2.在backup上修改配置文件 3、master和backup上启动服务 4、web服务器配置 1.web1和web…

一键搞定!这4款在线音频剪辑神器,你值得拥有!

嘿,小伙伴们,是不是有时候感觉手中的音乐或者语音素材需要经过一番精雕细琢才能完美呈现呢?今天,我就来给大家分享几款超好用的在线音频剪辑工具,让你在轻松愉快的氛围中,享受剪辑的乐趣,体验到…

MySQL函数:流程函数

1.IF函数 基本语法:IF(expr1,expr2,expr3) 功能:如果value为true,返回t, 否则返回f 例如:这个里面expr1里面是false,返回的是Error,如果是true,返回OK select if(false, OK, Err…

OAuth 2.0第三方授权登录

认证和授权的概念和区别 认证 (Authentication[ɔːˌθentɪˈkeɪʃn] ): 你是谁。授权 (Authorization[ˌɔːθəraɪˈzeɪʃ(ə)n]): 你有权限干什么。 概念: Authentication(认证) 是验证您的身份的凭据&…

利用大型语言模型轻松打造浪漫时刻

当情人节年年如约而至,每每都需费尽心思为对方营造一场令人难忘的仪式,却因缺乏创意与思路而倍感困扰。今天,我决定让大型语言模型为我们提供一些灵感和建议,让我们能够轻松实现这一目标。让我们开始行动吧!此前&#…

Paper 0 | Visual Instruction Tuning

使用机器生成的指令跟踪数据对大型语言模型 (LLM) 进行指令调整已被证明可以提高新任务的零样本能力,但这个想法在多模态领域的探索较少。我们首次尝试使用纯语言 GPT-4 生成多模态语言图像指令跟踪数据。通过对此类生成的数据进行指令调整,我们引入了 L…

手语手势识别系统源码分享

手语手势识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

Python_面向对象属性与方法

Python完全采用了面向对象的思想,是真正面向对象的编程语言,完全支持面向对象的基本功能,例如:继承、多态、封装等。Python中,一切皆对象。我们在前面学习的数据类型、函数等,都是对象。 面向过程和面向对象…