当前位置: 首页 > news >正文

【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)

目录

  • Redis
    • String(字符串)
    • List(列表)
    • Hash(字典)
    • Set(集合)
    • ZSet(有序集合)

Redis

Redis有5种基本的数据结构,分别为:string(字符串)、list(列表)、set(集合)、hash(哈希)和 zset(有序集合)。下面我们依次理解这五种基本数据类型。
在这里插入图片描述
除了String的底层是简单字符串SDS结构,其他类型底层都有两种数据结构支持。

String(字符串)

字符串是Redis最简单的数据结构。Redis所有的数据结构都是以唯一的key字符串作为名称,然后通过这个唯一key值来获取相应的value数据。不同类型的数据结构差异就在于value的结构不一样。
在这里插入图片描述
字符串结构使用非常广泛,一个常见的用途就是缓存用户信息。我们将用户信息结构体使用JSON序列化成字符串,然后将序列化后的字符串塞进Redis来缓存。同样,取用户信息会经过一次反序列化的过程。

在这里插入图片描述
Redis的字符串是动态字符串,是可以修改的字符串,在内存中它是以字节数组的形式存在的,内部实现上采用预分配冗余空间的方式来减少内存的频繁分配,如上图所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串的长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。注意:字符串最大长度为512M

List(列表)

List的插入和删除操作特别快,时间复杂度为O(1),但是索引定位很慢,时间复杂度为O(n)。当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。

Redis的列表结构常常被用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进Redis的列表,另一个线程从这个列表中轮询数据进行处理。

快速列表

如果再深入一点,你会发现Redis底层存储的是一个叫做quicklist的一个结构。
在这里插入图片描述
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的的附加指针空间太大,会比较浪费空间,而且会加重内存的碎片化。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prevnext。所以Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能。又不会出现太大的空间冗余。

quicklist内部默认单个ziplist长度为8k字节,超过了这个字节数,就会新起有一个ziplist

Hash(字典)

字典(dict)是 Redis 服务器中出现最为频繁的复合型数据结构,除了 hash 结构的数据会用到字典外,整个 Redis 数据库的所有 key 和 value也组成了一个全局字典,还有带过期时间的 key 集合也是一个字典。zset 集合中存储 value 和 score 值的映射关系也是通过 dict 结构实现的。

Redis的字典是个无序字典(golang、java中字典也是无序字典),内部实现为数组+链表二维结构。第一维hash的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。

在这里插入图片描述
Redis为了高性能,不能堵塞服务,rehash采用的是渐进式策略。

在这里插入图片描述
渐进式rehash会在rehash的同时,保留新旧两个hash结构,查询时会同时查询两个hash结构,然后在后续的定时任务中以及hash的子指令中,循序渐进的将旧hash的内容一点点迁移到新的hash结构中。

当 hash 移除了最后一个元素之后,该数据结构自动被删除,内存被回收。hash 结构也可以用来存储用户信息,不同于字符串一次性需要全部序列化整个对象,hash 可以对用户结构中的每个字段单独存储。这样当我们需要获取用户信息时可以进行部分获取。而以整个字符串的形式去保存用户信息的话就只能一次性全部读取,这样就会比较浪费网络流量。

hash 也有缺点,hash 结构的存储消耗要高于单个字符串,到底该使用 hash 还是字符串,需要根据实际情况再三权衡。

扩容条件

正常条件下,当hash表中元素的个数等于第一维数组的长度时,就会开始扩容,扩容的新数组是原数组大小的2倍。不过如果Redis这个在做bgsave,为了减少内存页的过多分离(Copy On Write),Redis尽量不去扩容(dict_can_resize),但是如果hash表已经非常满了,元素的个数已经达到了第一维数组长度的5倍(dict_force_resize_ratio),说明hash表已经过于拥挤了,这个时候就会强制扩容。

缩容条件

当 hash 表因为元素的逐渐删除而变得越来越稀疏时,Redis会对 hash 表进行缩容来减少hash表的第一维数组空间占用。缩容的条件是元素个数低于数组长度的10%。缩容不会考虑Redis是否正在做bgsave

Set(集合)

Redis的集合内部实现相当于一个特殊的字典,字典中所有的value都是一个值NULL,它内部的键值对是无序的唯一(自动排重)的。

当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。set结构可以用来存储活动中奖的用户ID,因为有去重功能,可以保证同一个用户不会中奖两次。

ZSet(有序集合)

zset可能是Redis提供的最为特色的数据结构,它也是在面试中面试官最爱问的数据结构。一方面它是一个set(字典结构),保证了内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。它的内部实现用的是一种叫做【跳跃列表】的数据结构。

zset中最后一个value被移除后,数据结构自动删除,内存被回收。zset可以用来存粉丝列表,value值是粉丝的用户ID,score是关注时间。我们可以对粉丝列表按关注时间进行排序。

zset还可以用来存储学生的成绩,value值是学生的ID,score是他的考试成绩。我们可以对成绩按分数进行排序就可以得到他的名次。

跳跃列表

zset内部的排序功能是通过【跳跃列表】数据结构来实现的,它的结构非常特殊,也比较复杂。

因为 zset 要支持随机的插入和删除,所以它不好使用数组来表示。

先来看一个普通的链表结构:

在这里插入图片描述
我们需要这个链表按照 score 值进行排序。这意味着当有新元素需要插入时,要定位到特定位置的插入点,这样才可以继续保证链表是有序的。通常我们会通过二分查找来找到插入点,但是二分查找的对象必须是数组,只有数组才可以支持快速位置定位,链表做不到,那该怎么办呢?

想想一个创业公司,刚开始只有几个人,团队成员之间人人平等,都是联合创始人。随着公司的成长,人数渐渐变多,团队沟通成本随之增加。这时候就会引入组长制,对团队进行划分。每个团队会有一个组长。开会的时候分团队进行,多个组长之间还会有自己的会议安排。公司规模进一步扩展,需要再增加一个层级 — 部门,每个部门会从组长列表中推选出一个代表来作为部长。部长们之间还会有自己的高层会议安排。

跳跃列表就是类似于这种层级制,最下面一层所有的元素都会串起来。然后每隔几个元素挑选出一个代表来,再将这几个代表使用另外一级指针串起来。然后在这些代表里再挑出来二级代表 ,再串起来。最终就形成了金字塔结构。

在这里插入图片描述
【跳跃列表】之所以【跳跃】,是因为内部的元素可能【身兼数职】,比如上图中间的这个元素,同时处于 L0、L1和L2层,可以快速再不同层次之间进行【跳跃】。

定位插入点时,先在顶层进行定位,然后下潜到下一级定位,一直下潜到最底层找到合适的位置,将新元素插进去。那新插入的元素如何才有机会【身兼数职】呢?

跳跃列表采取一个随机策略来决定新元素可以兼职到第几层。

首先 L0 层肯定是100%了,L1层只有50%的概率,L2层只有25%的概率,L3层只有12.5%的概率,一直随机到最顶层L31层。绝大多数元素都过不了几层,只有极少数元素可以深入到顶层。列表中的元素越多,能够深入的层次就越深,能进入到顶层的概率就会越大。

查找过程

请添加图片描述

  • 从第2层开始,因为 1 节点比 51 节点小,向后比较。

  • 21 节点比 51 节点小,继续向后比较,后面就是NULL了,所以从 21 节点向下到第 1 层

  • 到第 1 层,41 节点比 51 节点小,继续向后, 61 节点比 51 节点大,所以从 41 向下

  • 到第 0 层,51 节点为要查找的节点,节点被找到,共查找 4 次。

问题:为什么不采用树或者红黑树,或者像MySQL一样采用B树?(跳表和其他数据类型的区别)

两个核心问题:

  1. Redis的定位,也即问题的背景。Redis是一个内存数据库,在时间复杂度差不多的情况下,优先选择内存占用较小(也就是空间复杂度较低)的数据结构,而且相对而言跳表的实现起来更简单(它们更容易实现、调试等等)。
  2. 跳表和树的区别,尤其是数据结构上的区别。树需要大量的指针来记录节点信息,树越高,开销越大。跳表在这方面要好得多。在插入数据时,跳表可能会调整索引,树需要再平衡,各有特点。

相关文章:

【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)

目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构,分别为:string(字符串)、list(列表)、set(集合)、hash(哈希&a…...

ubuntu源码安装aria2

github:GitHub - aria2/aria2: aria2 is a lightweight multi-protocol & multi-source, cross platform download utility operated in command-line. It supports HTTP/HTTPS, FTP, SFTP, BitTorrent and Metalink. 发行说明:GitHub - aria2/aria2 at releas…...

【多任务案例:猫狗脸部定位与分类】

【猫狗脸部定位与识别】 1 引言2 损失函数3 The Oxford-IIIT Pet Dataset数据集4 数据预处理4 创建模型输入5 自定义数据集加载方式6 显示一批次数据7 创建定位模型8 模型训练9 绘制损失曲线10 模型保存与预测 1 引言 猫狗脸部定位与识别分为定位和识别,即定位猫狗…...

.Net 锁的介绍

在.NET中,有多种锁机制可用于多线程编程,用来确保线程安全和共享资源的同步。以下是.NET中常见的锁机制: 1. **Monitor(互斥锁):** `Monitor` 是.NET中最基本的锁机制之一。它使用 `lock` 关键字实现,可以确保在同一时刻只有一个线程能够访问被锁定的代码块。`Monitor`…...

Office 2021 小型企业版商用办公软件评测:提升工作效率与协作能力的专业利器

作为一名软件评测人员,我将为您带来一篇关于 Office 2021 小型企业版商用办公软件的评测文章。在这篇评测中,我将从实用性、使用场景、优点和缺点等多个方面对该软件进行客观分析,在专业角度为您揭示它的真正实力和潜力。 一、实用性&#xf…...

Monkey测试

一:测试环境搭建 1:下载android-sdk_r24.4.1-windows 2:下载Java 3:配置环境变量:关于怎么配置环境变量(百度一下:monkey环境搭建,) 二:monkey测试&#xff1…...

wzx-jmw:NFL合理,但可能被颠覆。2023-2024

As well known by all, NFL is ... 没有免费的午餐理论 No Free Lunch Theorem_免费午餐理论-CSDN博客 However, if we......

密码技术 (5) - 数字签名

一. 前言 前面在介绍消息认证码时,我们知道消息认证码虽然可以确认消息的完整性,但是无法防止否认问题。而数字签名可以解决否认的问题,接下来介绍数字签名的原理。 二. 数字签名的原理 数字签名和公钥密码一样,也有公钥和私钥&am…...

php实战案例记录(10)单引号和双引号的用法和区别

在 PHP 中,单引号和双引号都被用于表示字符串。它们有一些共同之处,但也有一些明显的区别。 解析变量: 双引号允许解析变量,而单引号不会。在双引号中,你可以直接在字符串中插入变量,而不需要进行额外的连接…...

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石② 第十九章 驱动程序基石②19.3 异步通知19.3.1 适用场景19.3.2 使用流程19.3.3 驱动编程19.3.4 应用编程19.3.5 现场编程19.3.6 上机编程19.3.7 异步通知机制内核代码详解 19.4 阻塞与非阻塞19.4.1 应用编程19.4.2 驱动编程…...

trycatch、throw、throws

在Java中,try-catch、throw和throws是用于处理异常的重要关键字和机制,它们的作用如下: try-catch:try-catch 是用于捕获和处理异常的语句块。在try块中放置可能引发异常的代码。如果在try块中的代码引发了异常,控制流会跳转到与异常类型匹配的catch块。在catch块中,可以…...

问 ChatGPT 关于 GPT 的事情:数据准备篇

一、假如你是一名人工智能工程师,手里有一个65B的GPT大模型,但你需要一个6B左右的小模型,你会怎么做? 答:作为人工智能工程师,如果我手里有一个65B的GPT大模型,而我需要一个6B左右的小模型&…...

leetcode_17电话号码的组合

1. 题意 输出电话号码对应的字母左右组合 电话号码的组合 2. 题解 回溯 class Solution { public:void gen_res(vector<string> &res, vector<string> &s_m,string &digits, string &t, size_t depth) {if (depth digits.size()) {if ( !t.em…...

记录使用vue-test-utils + jest 在uniapp中进行单元测试

目录 前情安装依赖package.json配置jest配置测试文件目录编写setup.js编写第一个测试文件jest.fn()和jest.spyOn()jest 解析scss失败测试vuex$refs定时器测试函数调用n次手动调用生命周期处理其他模块导入的函数测试插槽 前情 uniapp推荐了测试方案dcloudio/uni-automator&…...

《C和指针》笔记30:函数声明数组参数、数组初始化方式和字符数组的初始化

文章目录 1. 函数声明数组参数2. 数组初始化方式2.1 静态初始化2.2 自动变量初始化 2.2 字符数组的初始化 1. 函数声明数组参数 下面两个函数原型是一样的&#xff1a; int strlen( char *string ); int strlen( char string[] );可以使用任何一种声明&#xff0c;但哪个“更…...

VBA技术资料MF64:遍历单元格搜索字符并高亮显示

【分享成果&#xff0c;随喜正能量】不要在乎他人的评论&#xff0c;不必理论与他人有关的是非&#xff0c;你只要做好自己就够了。苔花如米小&#xff0c;也学牡丹开。无论什么时候&#xff0c;都要有忠于自己的勇气&#xff0c;去做喜欢的事&#xff0c;去认识喜欢的人&#…...

一键智能视频编辑与视频修复算法——ProPainter源码解析与部署

前言 视频编辑和修复确实是随着电子产品的普及变得越来越重要的技能。有许多视频编辑工具可以帮助人们轻松完成这些任务如&#xff1a;Adobe Premiere Pro&#xff0c;Final Cut Pro X&#xff0c;Davinci Resolve&#xff0c;HitFilm Express&#xff0c;它们都提供一些视频修…...

Flutter开发环境的配置

2023-10最新版本 flutter SDK版本下载地址 https://flutter.cn/docs/development/tools/sdk/releases gradle各版本快速下载地址 https://blog.csdn.net/ii950606/article/details/109105402 JAVA SDK下载地址 https://www.oracle.com/java/technologies/downloads/#java…...

【超详细】Wireshark教程----Wireshark 分析ICMP报文数据试验

一&#xff0c;试验环境搭建 1-1 试验环境示例图 1-2 环境准备 两台kali主机&#xff08;虚拟机&#xff09; kali2022 192.168.220.129/24 kali2022 192.168.220.3/27 1-2-1 网关配置&#xff1a; 编辑-------- 虚拟网路编辑器 更改设置进来以后 &#xff0c;先选择N…...

Linux命令(92)之rm

linux命令之rm 1.rm介绍 linux命令rm是用来删除一个或多个文件/目录&#xff0c;由于其删除的不可逆性&#xff0c;建议在日常工作中一定要慎用 2.rm用法 rm [参数] 文件/目录 rm常用参数 参数说明-r递归删除文件或目录-f不提示强制删除-i删除文件或目录前进行确认-v详细显…...

Mysql主从复制数据架构全面解读

大家好&#xff0c;我是山子&#xff0c;今天给大家分析Mysql 实现主从复制的方方面面&#xff0c;主从复制当然也是我们做读写分离的前提&#xff0c;以下内容是从各网络平台摘录整理总结归纳在一起的&#xff1b;内容已经从主从复制的各方面的维度进行了阐述&#xff1b;非常…...

ios证书类型及其作用说明

ios证书类型及其作用说明 很多刚开始接触iOS证书的开发者可能不是很了解iOS证书的类型功能和概念。下面对iOS证书的几个方面进行介绍。 apple开发账号分类&#xff1a; 免费账号&#xff1a; 无需支付费用给apple&#xff0c;使用个人信息注册的账号 可以开发测试安装&…...

警告-Ubuntu提示W: Possible missing firmware xxx解决方法

目录 现象原因解决方法 现象 当执行 sudo apt-get update或者sudo apt-get dist-upgrade时&#xff0c;有如下警告&#xff1a; W: Possible missing firmware /lib/firmware/rtl_nic/rtl8125a-3.fw for module r8169 W: Possible missing firmware /lib/firmware/rtl_nic/rt…...

有时候,使用 clang -g test.c 编译出可执行文件后,发现 gdb a.out 进行调试无法读取符号信息,为什么?

经过测试&#xff0c;gdb 并不是和所有版本的 llvm/clang 都兼容的 当 gdb 版本为 9.2 时&#xff0c;能支持 9.0.1-12 版本的 clang&#xff0c;但无法支持 16.0.6 版本的 clang 可以尝试使用 LLVM 专用的调试器 lldb 我尝试使用了 16.0.6 版本的 lldb 调试 16.0.6 的 clan…...

UG\NX二次开发 信息窗口的一些操作 NXOpen/ListingWindow

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 信息窗口的一些操作 NXOpen/ListingWindow 效果: 代码: #include "me.hpp" #include <NXOpen/ListingWindow.hxx> #include <…...

macbook电脑磁盘满了怎么删东西?

macbook是苹果公司的一款高性能笔记本电脑&#xff0c;受到很多用户的喜爱。但是&#xff0c;如果macbook的磁盘空间不足&#xff0c;可能会导致一些问题&#xff0c;比如无法开机、运行缓慢、应用崩溃等。那么&#xff0c;macbook磁盘满了无法开机怎么办&#xff0c;macbook磁…...

解释 RESTful API,以及如何使用它构建 web 应用程序

RESTful API是一种基于HTTP协议&#xff0c;使用REST架构风格设计的API。其核心思想是将所有的Web应用程序资源抽象为一组资源集合&#xff0c;并通过HTTP协议中的GET、POST、PUT、DELETE等几个方法对这些资源进行操作&#xff0c;使得Web应用程序能够方便地、高效地进行管理和…...

qml使用c++自定义listmodel数据

qml要使用c中自定义的model&#xff0c;首先该model类需要继承QAbstractListModel类&#xff0c;然后需要重写其中的三个函数&#xff0c;分别是 int rowCount(const QModelIndex &parent); QVariant data(const QModelIndex &index, int role Qt::DisplayRole); QHas…...

cf 解题报告 01

E. Power of Points Problem - 1857E - Codeforces 题意&#xff1a; 给你 n n n 个点&#xff0c;其整数坐标为 x 1 , … x n x_1,\dots x_n x1​,…xn​&#xff0c;它们位于一条数线上。 对于某个整数 s s s&#xff0c;我们构建线段[ s , x 1 s,x_1 s,x1​], [ s , x…...

傅里叶系列 P1 的定价选项

如果您想了解更多信息&#xff0c;请查看第 2 部分和第 3 部分。 一、说明 这是第一篇文章&#xff0c;我将帮助您获得如何使用这个新的强大工具来解决金融中的半分析问题并取代您的蒙特卡洛方法的直觉。 我们都知道并喜欢蒙特卡洛数字积分方法&#xff0c;但是如果我告诉你你可…...

提供常州网站推广/在百度怎么免费发布广告

为什么3dmax渲染出来是黑色的&#xff0c;用PS打开也是全黑的?渲染出来的结果全黑&#xff0c;大概率新手都会遇到这样的问题&#xff0c;那么如何解决呢&#xff1f;看看以下几种设置就可以解决这个问题。第一种情况是抗锯齿过滤器选择错了首先我们打开3dmax中渲染设置里面的…...

网站建设添加资料/怎么做网站宣传

MySQL5.6.6版本之后增加了密码强度验证插件validate_password&#xff0c;相关参数设置的较为严格。 如下错误&#xff1a; 有时&#xff0c;在开发和测试环境中&#xff0c;不想密码设置得那么复杂&#xff0c;譬如只想设置root的密码为123456。 SET PASSWORD FOR rootlocal…...

网站建设原理/销售渠道及方式

Vue作者尤雨溪&#xff0c;英文 Evan You艺术硕士&#xff0c;毕业后在 Google Creative Lab工作后转为 全职 JavaScript 开发工程师主要作品 Vue、Vue Router、Vuex、vue/cli github主页&#xff1a;https://github.com/yyx990803Vue.js记录片&#xff1a;https://www.youtube…...

福永镇网站建设/百度网站推广价格查询

1 首先说下字符集。gb18030字符集兼容了gbk字符集&#xff0c;以两个字节表示一个文字。windows系统可能使用的就是这两种的一种。unicode字符集以2个或以上的字节表示一个汉字。通用字符集(Universal Character Set, UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义…...

济南香港国际网站建设/有产品怎么找销售渠道

本文实例为大家分享了python实现万年历的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下#coding:utf-8def leap_year(year):#判断平瑞年if year%40 and year%100!0 or year%4000:return Trueelse:return Falsedef getMonthDays(year,month):#得到每个年份每月的天数d…...

爱站权重/百度识别图片找图

mysql自动关闭&#xff0c;日志看不懂&#xff0c;希望大神解读下Version: 5.5.48 socket: /tmp/mysql.sock port: 3306 Source distribution160515 14:15:17 mysqld_safe Number of processes running now: 0160515 14:15:17 mysqld_safe mysqld restarted160515 14:15:17 [Wa…...