Redis五大数据类型

news2024/9/21 0:41:07

d5905029de50405b804c19be179ff019.jpg关于Redis的五大数据类型,它们分别为:String、List、Hash、Set、SortSet。本文将会从它的底层数据结构、常用操作命令、一些特点和实际应用这几个方面进行解析。对于数据结构的解析,本文只会从大的方面来解析,不会介绍详细的代码实现。

 

 

String

1.实现结构

  String是Redis中最常用的一种数据类型,也是Redis中最简单的一种数据类型。首先,表面上它是字符串,但其实他可以灵活的表示字符串、整数、浮点数3种值。Redis会自动的识别这3种值。那么,String的底层数据机构又是怎样的呢?由于Redis是使用c语言实现的,而c语言中没有String这一数据类型,那么就需要自己实现一个类似于String的结构体。它的名字就叫做SDS(simple dynamic string),下面是它的代码结构。

 

复制代码

1 typedef struct sdshdr {

2 // buf中已经占用的字符长度

3 unsigned int len;

4 // buf中剩余可用的字符长度

5 unsigned int free;

6 // 数据空间

7 char buf[];

8 }

复制代码

如果有了解过Java集合框架类的朋友都知道,这种结构与集合中动态数组结构类似,那么就会涉及到一系列的扩容判断和操作,但这些具体的做法在这里不深入讲解。不过有一点比较重要的就是String的value值最大可以存放512MB的数据,所以有时候它不仅仅可以存放字符,还可以存放字节数据。

 

2.实际应用

  在讲实际应用之前,要声明的是Redis是基于单线程IO多路复用的架构实现的NoSql,意味着它的操作都是串行化的,所以在命令操作上不会出现线程安全问题,基于这个特性可以有很多应用。

 

分布式锁。利用Redis的串行化特性,可以轻松的实现分布式锁,其中用到的命令有:setnx key value , expire key time ,del key ,其中第一个setnx是指在key不存在时能赋值成功,expire 来设置key的存活时间来防止程序异常而没有及时del到key值的情况。但是程序也有可能在expire没有执行时就已经挂掉的时候,这是可以来一个增强版set key value NX EX time。这里的NX就是表示if not exist,而Ex表示时间单位秒,Px代表毫秒。

分布式session。这里仅仅是利用Redis的数据库功能,把分布式应用的session抽取到Redis中,普通的get、set,命令即可完成。

商品秒杀实现。把需要销售的商品提前放入Redis,通过redis的incr和decr命令安全的增加和减少库存。

限时验证。 expire key time ,判断exists key在短信验证时,当redis中存在数据则不允许再次请求验证发送。

 

 

List

1.实现结构

  首先,List的主要存取操作有lpush、lpop、rpush、rpop,有点像是双向队列。List的实现是灵活多样的,它分别有ziplist(压缩链表)、LinkedList(双向链表)两种实现方式。

 

  1.ziplist

  如下图所示,它是基于连续内存实现(类似数组)。当然,它的每一个entry的大小可能不是一致的,这就需要特殊的控制手段去解决,所以才叫压缩表。那么数组有的特性它都会有,比如在lpush、lpop的时候就会有数据的搬移,时间复杂度是O(n)。所以,一般在数据元素较少时使用ziplist结构实现。

 

 

 

  2.LinkedList

  则与我们日常所学的双向链表相差无异,同样也保留则头尾指针、数据长度等数据,这里就不再详细说明,需要了解的去读一读Java的LInkedList源码也不错。

 

2.实际应用

消息队列。使用lpush,brpop两个命令可以模拟一个消息队列。其中brpop key time为阻塞式弹出,当队列中为空时会阻塞当前操作,该操作需要添加超时参数,单位为秒。

有限集合。使用ltrim key start end操作可以获取一个固定位置的数据,可以快速实现一个有限的集合。

Hash

 1.实现结构

  首先,Hash的特性我们可以想象为Java集合中的HashMap,一个hash中可以有多个field:value(键值对)。关于hash的实现同样有两种情况。一种是基于ZipList,一种是基于HashTable实现。

 

  1.ZipList

  这里的的ZipList与List当中的ZipList其实是相差无几的,唯一的特点就是Hash存储的时候,它的entry数量是成对增加的,同时也是成对存在的,所以它的长度一定是2的整数倍。filed值放在前面,value放在后面的形式存放。当然采用ZipList操作时,它的查找删改查的时间复杂度就会变为O(n),所以ZipList适合在数据较少的情况下使用。

 

 2.HashTable

 

虽然说Hash与Java中的HashMap功能类似,但在HashTable这个结构上还是有一定的不同点的。要想了解HashTable的实现,需要了解三个结构。它们分别是:dict、dictht、entry。entry和前面list中提到的类似,下面列出前面两个结构的定义:

 

复制代码

 1 // 哈希表(字典)数据结构,Redis 的所有键值对都会存储在这里。其中包含两个哈希表。

 2 typedef struct dict {

 3 // 哈希表的类型,包括哈希函数,比较函数,键值的内存释放函数

 4 dictType *type;

 5 // 存储一些额外的数据

 6 void *privdata;

 7 // 两个哈希表

 8 dictht ht[2];

 9 // 哈希表重置下标,指定的是哈希数组的数组下标

10 int rehashidx; /* rehashing not in progress if rehashidx == -1 */

11 // 绑定到哈希表的迭代器个数

12 int iterators; /* number of iterators currently running */

13 } dict;

14 

15 typedef struct dictht { 

16 //槽位数组

17 dictEntry **table; 

18 //槽位数组长度

19 unsigned long size; 

20 //用于计算索引的掩码,可以理解为hash函数 

21 unsigned long sizemask;

22 //真正存储的键值对数量

23 unsigned long used; 

24 } dictht;

复制代码

关系可以总结为下面这幅图:

 

 

 

 

 

2.实际应用

存放对象Object。你可能会发现,从宏观上来说,这种一个key , field1 : value1 ,field2 : value2 一个键值对应多个字段field的格式非常适合用于描写一个对象。所以,hash一般会用于描述一个对象,但其实我们在实际中也有可能会用一个Json格式的字符串来描述一个对象。那么这两种方法都可行的情况下,会有什么优缺点呢?利用hash描述一个对象:可以做到序列化开销小,可以单独修改某一个字段而不用读出全部数据,但是使用比较复杂。而使用json描述对象,使用简单但需要耗费额外的序列化开销。需要使用什么形式,具体情况需要具体分析。

结合Json描述对象的集合。例如,在商城应用中,可以利用Hash的key来描述一个用户的id,而field用于描述用户的购物车列表中的一个物品的详细信息。

 

 

Set

Set是一个不允许重复的,无顺序的数据集合。值得注意的是,这里说的无顺序其实还是有一点歧义的,那么到底是怎么回事呢?接下来的博文就会有提到这个差异。

 

1.实现结构

  1.IntSet。

  这里的IntSet是一种在满足特定情况下所使用的数据结构。这种情况就是当全部value都为整型时,redis会使用IntSet这种结构。在这个情况下它是有序的。这是为什么呢?先从结构开始说起,为了平衡空间的性能的消耗,Redis在数据都为整型的时候使用了一种基于动态数组的结构体,同时在存放元素时保正元素的大小顺序,这样就可以使用二分查找以时间复杂度O(logn)来完成增删改查的操作。这样就节省了很多空间。至于增和删操作,同样会涉及到数组的数据搬移操作。下面为它的结构体代码:

 

复制代码

1 typedef struct intset {

2 // 编码方式

3 uint32_t enconding;

4 // 集合包含的元素数量

5 uint32_t length;

6 // 保存元素的数组    

7 int8_t contents[];

8 } intset;

复制代码

 

 

  2.HashTable

  当存在非整型数据的时候,Redis会自动把IntSet转换为HashTable的结构存放数据,但HashTable不能转换为IntSet。这里的HashTable与上面Hash结构提到的HashTable没有太大的差别。唯一的差别就在于Set存放在HashTable中只有Key值,没有value值,所以在HashTable的Entry中,Enrty的value永远为null。

 

2.实际应用

 记录唯一的事物。如ip值,身份证等。

随机用户抽奖。通过srandmember key 随机返回一个set中的数据。

用户标签。当用户在使用某个产品的时候,后台可能会记录该用户对某个东西的喜好,从而在该标签中记录该用户。同时,可以利用sinter key1 key2、sunion、sdiff返回标签中的交集、并集、差集。这样就可以轻松得出用户的共同喜好、所有喜好、非共同喜好等数据。

 SortSet

SortSet是一个实现了数据有序且唯一的键值对集合。其中,Entry的键为string类型,值为整型或浮点型,表示权值score。其中SortSet的顺序就是通过Score的值来确定的。

 

1.实现结构

SortSet的实现结构同样有两种,一种是ZipList结构实现,适用于较少数据的情况。另一种是SkipList+HashTable的形式,使用与数据较多的情况,其中SkipList是在保证有序的情况下优化范围查找的时间复杂度,而HashTable则是优化增删改查的时间复杂度。

 

  1.ZipList

 SortSet的ZipList和Hash中的数据结构类似,同样也是存放键值对,但是它维护了基于Score的有序性(默认从小到大),这里就不再赘述。

 

  2.SkipList+HashTable

  首先来说明主要的SkipList(跳表),跳表是一种基于有序链表,通过建立多层索引,以空间换时间的方式实现平均查找效率为O(logn)复杂度的一种数据结构。下面给出一个跳表的基本形式图:

 

 

 

 可以看到在根据数据的权值Score进行查找的时候,从最顶层的索引开始查找。当找到数据在某个范围后,在往下一层的索引查找,然后就这样一路缩小查找的范围。看上去是不是有点像二分查找?至于跳表的具体介绍和实现,可以参考这篇文章:为什么Redis要用跳表实现有序集合?

 

上面可以看到,基于跳表的实现的有序集合可以完成增删改查实现O(logn)的时间复杂度,那么有没有更加快的方式来实现O(1)的时间复杂度呢?通常说起O(1)的时间复杂度都会想起HashTable这个数据结构。Redis就利用HashTable+SkipList的组合数据结构,HashTable来实现增删改查的时间复杂度为O(1)的同时SkipList保证数据的有

 

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

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

相关文章

Linux_Shell命令解析

简介 在linux终端中执行ls命令,ls命令是如何被解析并且执行的。Shell命令的格式一般为: [commond] [-options] [parameter]执行命令 命令的选项 命令的参数当执行ls命令是显示当前目录下所有文件的名称 执行ls -l命令是显示当前目录下所有文件的属性…

软件工程开发文档写作教程(01)—开发文档的意义与作用

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl本文参考资料:电子工业出版社《软件文档写作教程》 马平,黄冬梅编著 软件工程开发文档的意义 软件文档是整个软件开发工作的基础,现代工程…

Maven(一)基础入门

目录 一、Maven简介1.背景2.Maven是什么3.Maven的作用 二、下载与安装1.下载2.安装3.配置环境变量 三、Maven基础概念1.仓库2.坐标3.本地仓库配置4.远程仓库配置5.阿里云-镜像仓库配置6.全局 settings 与用户 settings 区别 四、第一个Maven项目(手工制作&#xff0…

【Python】快速简单搭建HTTP服务器并公网访问「cpolar内网穿透」

转载自远程内网穿透的文章:【Python】快速简单搭建HTTP服务器并公网访问「cpolar内网穿透」 1.前言 Python作为热度比较高的编程语言,其语法简单且语句清晰,而且python有良好的兼容性,可以轻松的和其他编程语言((比如…

Qt/QML编程学习之心得:ALSA音频开发(六)

Linux内核中对音频播放和捕获的最初支持是由开放声音系统(OSS)提供的。OSS API是为音频而设计的带有16位双通道回放和捕获的卡,以及随后的API通过open()、close()、read()和write()系统调用的标准POSIX。OSS的主要问题是,虽然基于文件的API实际上易于应用程序开发人…

电磁阀“位”与“通”的详细解说(示意图)

电磁阀是用电磁控制的工业设备,是用来控制流体的自动化基础元件,属于执行器。 而气动电磁阀是其中的一种,是通过控制阀体的移动来档住或漏出不同的排油的孔,而进油孔是常开的,液压油就会进入不同的排油管,…

物联网定位技术|实验报告|实验一 Wi-Fi指纹定位

目录 实验1 Wi-Fi指纹定位 1. 实验目标 2. 实验背景 3. 实验原理 3.1 WIFI基础知识 3.2室内定位方法建模 3.3指纹定位算法 ①离线/训练阶段 ②在线/定位阶段 4. 关键代码 5. 实验结果 6. 室内定位误差分析 6.1 非视距传播 6.2 多径传播 6.3 阴影效应 7. 实验总结 物联网定位技…

ESP32学习三-环境搭建(ESP-IDF V5.0,Ubuntu20.4)

一、准备事项 Ubuntu 20.04。具体安装可以参考如下链接。使用VMware安装Ubuntu虚拟机和VMware Tools_t_guest的博客-CSDN博客 二、安装ESP-IDF 1)、确认python3版本 输入python3 --version来确认python3的版本。因为要安装ESP-IDF 5.0版本,python3的版本…

Docker Compose与Docker Swarm的简介和区别

Docker Compose与Docker Swarm的简介和区别 背景Compose 简介Swarm 简介Compose 和 Swarm区别 背景 之前公司很多都是单体的spring boot服务,使用Docker的时候,只需要定义Dockerfile 文件,然后打成镜像把容器启动起来就ok了。但是现在的微服…

低成本,全流程!基于PaddleDepth和Paddle3D的三维视觉技术应用方案

现实生活中的很多应用场景都需要涉及到三维信息。针对三维视觉技术应用场景复杂多样、三维感知任务众多、流程复杂等问题,飞桨为开发者提供了低成本的深度信息搜集方案 PaddleDepth 以及面向自动驾驶三维感知的全流程开发套件 Paddle3D 。 三维视觉技术应用场景 3D …

01——计算机系统基础

计算机系统基础知识 计算机系统基础一、计算机系统的基本组成1 计算机硬件系统 二、计算机的类型三、计算机的组成和工作原理1 计算机的组成2 总线的基本概念2.1 总线的定义与分类 3 系统总线3.1 系统总线的概念3.2 常见的系统总线 4 外总线5 中央处理单元(CPU&…

【刷题】搜索——BFS:八数码【A*模板】

A*简介 某点u的距离f(u)定义如下: f ( u ) g ( u ) h ( u ) f(u) g(u) h(u) f(u)g(u)h(u) g(u):起点到u走的距离 h(u):u到终点估计的距离,保证 0 ≤ h ( u ) ≤ h ′ ( u ) 0 \leq h(u) \leq h(u) 0≤h(u)≤h′(u)。其中h’…

健康体检信息系统源码,个人体检、团队体检、体检报告、统计分析

健康体检管理系统源码 PEIS源码 数据对接 体检人员管理系统,系统有演示,文档齐全。 一套专业的体检管理系统源码,该系统涵盖个人体检、团队体检、关爱体检等多种体检类型,提供体检登记管理、体检结果管理、体检报告打印及发放…

阿里云服务器搭建网站流程by宝塔Linux面板

阿里云服务器安装宝塔面板教程,云服务器吧以阿里云Linux系统云服务器安装宝塔Linux面板为例,先配置云服务器安全组开放宝塔所需端口8888、888、80、443、20和21端口,然后执行安装宝塔面板命令脚本,最后登录宝塔后台安装LNMP&#…

尝试图像锐化

#图像锐化 拉普拉斯: 导数f(x,y)f(x1,y)f(x−1,y)f(x,y1)f(x,y−1)−4f(x,y) 可以扩展到8邻域: ​ Mat Sharpen(Mat input, int percent, int type) { Mat result; Mat s input.clone(); Mat kernel; switch (type) { case 0: kernel (Mat_(3, 3)…

4个令人惊艳的ChatGPT项目,开源了

自从 ChatGPT、Stable Diffusion 发布以来,各种相关开源项目百花齐放,着实让人应接不暇。今天,将着重挑选几个优质的开源项目,对我们的日常工作、学习生活,都会有很大的帮助。 一、Visual ChatGPT 这个是微软开源的项…

代码随想录_二叉树_leetcode700、98

leetcode700.二叉搜索树中的搜索 700. 二叉搜索树中的搜索 给定二叉搜索树(BST)的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。 示例 1: 输入&…

乘客出租出行需求短时预测

CLAB模型是一种空间-时间环境下基于深度学习的乘客流量预测模型,可有效挖掘出租车乘客出行的时空相关性,考虑历史数据流入量对出行需求的影响,从而提高预测准确性。 数据挖掘维度: 1.时间维度:预测的是短时预测&#x…

关于ONgDB我问了ChatGPT这些问题!

关于ONgDB我问了ChatGPT这些问题! 关于ONgDB我问了ChatGPT这些问题!提问 ChatGPTONgDB和Neo4j的区别是什么?ONgDB可以适配哪些版本的Neo4j软件包?ONgDB可以适配哪个版本的Neo4j Python驱动软件包?ONgDB 1.x版本的特点是…

Oracle系列之八:SQL查询

SQL查询 1. 基本查询2. 连接查询3. SQL语句解析4. Oracle Hint Oracle它提供了一个强大的SQL引擎,使得用户可以通过SQL语言来管理和操作数据库。 1. 基本查询 以CAP(顾客-代理-产品)数据库为例,表结构如下: CUSTOME…