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的指令

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

这是伪代码的实现

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新手卖家做跨境电商,选择Shopee还是亚马逊?

对于刚刚涉足跨境电商领域的新人来说,选择合适的电商平台是迈出成功第一步的关键。目前最主流的跨境平台一定是亚马逊,平台覆盖全球各个市场,利润高,但门槛也高。Shopee主要面向的是东南亚市场,商品一般更有性价比&…

LabVIEW界面输入值设为默认值

在LabVIEW中,将前面板上所有控件的当前输入值设为默认值,可以通过以下步骤实现: 使用控件属性节点:你可以创建一个属性节点来获取所有控件的引用。 右键点击控件,选择“创建” > “属性节点”。 设置属性节点为“D…

Unity开发绘画板——02.创建项目

1.创建Unity工程 我们创建一个名为 DrawingBoard 的工程,然后先把必要的工程目录都创建一下: 主要包含了一下几个文件夹: Scripts :存放我们的代码文件 Scenes :工程默认会创建的,存放场景文件 Shaders &…

加固与脱壳01 - 环境搭建

虚拟机 VMWare 多平台可用,而且可以直接激活,需要先注册一个账号 https://support.broadcom.com/group/ecx/productdownloads?subfamilyVMwareWorkstationPro KALI 类Ubuntu系统,官方提供了 vmware 版本,直接下载就可以使用。…

关于安卓App自动化测试的一些想法

安卓App自动化一般使用PythonAppium。页面元素通常是使用AndroidStudio中的UI Automator Viewer工具来进行页面元素的追踪。但是这里涉及到一个问题就是,安卓apk在每次打包的时候,会进行页面的混淆以及加固,所以导致每次apk打包之后会出现页面…

[Linux]用户管理指令

开机/重启/登录/注销 进入xhsell 或者虚拟系统中, 右键桌面打开终端, 在终端执行命令, 重启或关机linux系统 建议使用普通账号登录, 如果权限不够时, 使用 su - 用户名 命令切换到超管, 然后再使用 logout命令退回到普通账号, logout 不能在图形界面的终端中使用 用户管理 Li…

网络信息传输安全

目录 机密性-加密 对称加密 非对称加密 身份认证 摘要算法和数据完整性 数字签名 签名验签 数字证书 申请数字证书所需信息 数字证书的生成 数字证书的应用 https协议 数字证书的申请 数据在网络中传输过程中,怎么做到 数据没有被篡改?hash算…

基于PHP的新闻管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于phpMySQL的新闻管理系统。…

[js逆向学习] fastmoss电商网站——店铺排名

逆向目标 网站:https://www.fastmoss.com/shop-marketing/tiktok接口:https://www.fastmoss.com/api/shop/shopList/参数:fm-sign 逆向分析 我们今天要分析的是店铺排名,先分析网络请求,找到目标接口 按照上图操作…

JUC高并发编程2:Lock接口

1 synchronized 1.1 synchronized关键字回顾 synchronized 是 Java 中的一个关键字,用于实现线程间的同步。它提供了一种简单而有效的方式来控制对共享资源的访问,从而避免多个线程同时访问同一资源时可能出现的竞态条件(race condition&am…

.net core8 使用JWT鉴权(附当前源码)

说明 该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。 该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。 说明:OverallAuth2.0 是一个简单、易懂、功能强…

LeetcodeTop100 刷题总结(二)

LeetCode 热题 100:https://leetcode.cn/studyplan/top-100-liked/ 文章目录 八、二叉树94. 二叉树的中序遍历(递归与非递归)补充:144. 二叉树的前序遍历(递归与非递归)补充:145. 二叉树的后序遍…

你的提交信息还在拖后腿?看这里,提升代码质量的绝招!

文章目录 前言一、什么是约定式提交?二、创建新仓库三、将代码推送到远程仓库的步骤1.检查当前远程仓库2.添加代码到暂存区3. 进行约定式提交4. 推送代码到远程仓库5. 完成推送 总结 前言 在当今软件开发领域,Git已经成为最广泛使用的版本控制系统之一。…

java算法OJ(1)位运算

目录 1.前言 2.正文 2.1位运算符号 2.1俩数相除 2.1.1题目 2.1.2示例 2.1.3题解 2.2二进制求和 2.2.1题目 2.2.2示例 2.2.3题解 2.3只出现一次的数字 2.3.1题目 2.3.2示例 2.3.3题解 2.4只出现一次的数字(进阶版) 2.4.1题目 2.4.2示例…

【ComfyUI】控制光照节点——ComfyUI-IC-Light-Native

原始代码(非comfyui):https://github.com/lllyasviel/IC-Light comfyui实现1(600星):https://github.com/kijai/ComfyUI-IC-Light comfyui实现2(500星):https://github.c…

cobbler自动批量安装多版本操作系统

本次虚拟化环境为VMware Workstation Pro,cobbler服务端为CentOS7.9,需要自动安装的版本为CentOS7.9和CentOS8.1 目录 一、安装cobbler服务端1、修改YUM源2、关闭防火墙3、安装软件包4、cobbler环境配置5、解决语法问题6、启动服务7、导入镜像8、自定义…

Spring自定义参数解析器

在这篇文章中,我们认识了参数解析器和消息转换器,今天我们来自定义一个参数解析器。 自定义参数解析器 实现HandlerMethodArgumentResolver的类,并注册到Spring容器。 Component//注册到Spring public class UserAr…

统信服务器操作系统【Cron定时任务服务】

Cron定时任务服务服务介绍、服务管理、服务配置 文章目录 一、功能概述二、功能介绍1. Cron 服务管理2.Cron 服务管理3.Cron 服务配置run-parts一、功能概述 cron是一个可以用来根据时间、日期、月份、星期的组合来 调度对周期性任务执行的守护进程。利用 cron 所提供的功能,可…

第十四届蓝桥杯嵌入式国赛

一. 前言 本篇博客主要讲述十四届蓝桥杯嵌入式的国赛题目,包括STM32CubeMx的相关配置以及相关功能实现代码以及我在做题过程中所遇到的一些问题和总结收获。如果有兴趣的伙伴还可以去做做其它届的真题,可去 蓝桥云课 上搜索历届真题即可。 二. 题目概述 …

七种修复错误:由于找不到msvcr110.dll 无法继续执行的方法

当你在运行某些程序时遇到“找不到msvcr110.dll”的错误提示,这通常意味着你的系统缺少了Microsoft Visual C 2012 Redistributable包中的一个重要文件。这个DLL文件是Microsoft Visual C Redistributable的一部分,用于支持许多使用Visual C编写的软件和…