Redis 十大核心数据类型解析

news2025/1/24 22:49:30

一、Redis 简述

redis是一个开源的使用C语言编写的一个kv存储系统,是一个速度非常快的非关系远程内存数据库。它支持包括String、List、Set、Zset、hash五种数据结构。

除此之外,通过复制、持久化和客户端分片等特性,用户可以很方便地将redis扩展成一个能够包含数百GB数据和每秒处理上百万次的请求的系统。目前支持多种语言的api,方便用户使用。

redis同时也内置了事务、LUA脚本、复制等功能,提供两种持久化选项,一种是每隔一段时间将数据导入到磁盘(RDB快照模式),另一种是追加命令到日志中(AOF模式)。如果只是作为高效的内存数据库使用也可以关闭持久化功能。

通过哨兵(sentinel)和自动分区(Cuuster)的方式可以提高redis服务器的高可用性。

与关系型数据库相比,redis的命令请求不需要经过查询分析器或查询优化器进行处理,也避免了更新数据时引起的随机读\写,这些慢操作。它直接读写内存中的数据,并且数据是按照一定的数据结构存储的,所以它的速度非常快。

  1. redis命令手册:http://www.redis.cn/commands.html
  2. redis 命令说明:https://www.redis.net.cn/order/

二、Redis 基本数据类型

声明:这里的数据类型是value的数据类型,key的数据类型(区分大小写)都是字符串;

2.1 Redis 键(key)

在这里插入图片描述

2.2 Redis字符串 String

1) 定义与简述

与其他语言或者键值存储提供相似,键(key)------值(value) (字符串格式),字符串拥有一些操作命令,如原子自增 incr ,自减 decr(自增自减范围signed long区间,超出会报错) 、get、 set、 del等等。

Redis是使用C语言开发,但是C中并没有字符串类型,只能使用指针或者字符数组的形式表示一个字符串,所以Redis设计了一种简单的动态字符串(SDS[Simple Dynamic String]) 作为底层实现:【SDS具体结构后续探索】
在这里插入图片描述
定义SDS对象,此对象中包含三个属性:

  1. len buf中已经占有的长度(表示此字符串的实际长度)
  2. free buf中未使用的缓冲区长度
  3. buf[] 实际保存字符串数据的地方

所以取字符串的长度时间复杂度为O(1) , 另外 buf[] 依然采用C语言的以 \0 结尾可以直接使用C语言部分标准C字符串库函数。

空间分配原则:

  1. 当len小于1MB(1024*1024)时 增加字符串分配空间大小为加倍现有空间
  2. 当len大于1MB时每次只会多扩容1MB的空间,【字符串最大长度是512MB】

由此总结以下特性:

  1. Redis为字符分配空间的次数是小于等于字符串的长度N,而原C语言中分配原则必须为N,降低了分配次数,提高了追加速度,代价就是多占用一些内存空间,且这些空间不会自动释放。
  2. 二进制安全性高
  3. 高效的计算字符串长度(时间复杂度O(1))
  4. 高效的追加字符串操作

Redis的字符串类型是其他几种的基础,值可以是字符串(简单,复杂的json,xml),数字(整型,浮点),二进制(图片,音频,视频),最大值不能超过512MB。
在这里插入图片描述

2)常用命令
在这里插入图片描述

3)应用场景

1、分布式锁
在这里插入图片描述
2、抖音点赞
在这里插入图片描述

3、喜欢的文章
阅读数:只要点击了rest地址,直接可以使用incr key 命令增加一个数字1,完成记录数字。
在这里插入图片描述

2.3 Redis 列表(List)

1)定义及简述

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),它底层是一个双端链表的结构,容量是2的32次方减1个元素,大概40多亿,主要功能有push/pop等,一般用在栈、队列、消息队列等场景。

left、right都可以插入添加;

  • 如果键不存在,创建新的链表;
  • 如果键已存在,新增内容;
  • 如果值全移除,对应的键也就消失了。

因为它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
在这里插入图片描述
在3.2版本以后,重新引入了一个quicklist的数据结构,列表的底层都是使用quicklist实现的,它结合ziplist和linkedlist的优点。按照原文解释这种数据结构时【A doubly linked list of ziplists】的意思就是一个由ziplist组成的双向链表。那么这两种数据结构是怎么结合的呢?

宏观上就是一个链表结构,只不过每个节点都是以压缩列表的ziplist的结构保存着数据,而每个ziplist又可以包含多个entry,也可以理解为每一个quicklist 节点保存的是一片数据,而不是一个数据。quicklist将多个ziplist用双向指针串联起来。
在这里插入图片描述

整体上quicklist就是一个双向链表结构,和普通链表一样插入删除效率很高,但是查询效率却是O(n),不过这样链表访问两端的元素时间复杂度就是O(1),所以对list的操作多是 poll 或 push;

每个quicklist 节点就是一个ziplist ,具备压缩列表的特性

2)常见命令
在这里插入图片描述

3)应用场景

1、微信公众号订阅消息

  1. 大V作者李永乐老师和CSDN发布了文章分别是 11 和 22
  2. 你关注了他们两个,只要他们发布了新文章,就会安装进我的List
    lpush likearticle:你id 11 22
  3. 查看你自己的号订阅的全部文章,类似分页,下面0~10就是一次显示10条
    lrange likearticle:你id 0 9

2.4 Redis 哈希表(hash)

1) 定义及简述

Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)。

散列可以看做是文档或者关系数据库里的一行hash底层数据结构实现有两种:

一种是ziplist,当存储的数据超过配置的阈值时,就转用hashtable的结构,这种转换比较消耗性能,所以应该尽量避免这种转换操作,同时满足以下两个条件时,才会使用这种结构,

  1. 当键的个数小于hash-max-ziplist-entries(默认512)
  2. 当所有值都小于hash-max-ziplist-value(默认64)

另一种就是hashtable。这种结构的时间复杂度为O(1),但是会消耗比较多的内存空间。
在这里插入图片描述
缺点:hash结构的存储消耗高于单个字符串。具体使用需要考虑场景是使用hash还是字符串

2)常用命令
在这里插入图片描述

3)应用场景

1、早起购物车设计
新增商品 → hset shopcar:uid1024 334488 1
新增商品 → hset shopcar:uid1024 334477 1
增加商品数量 → hincrby shopcar:uid1024 334477 1
商品总数 → hlen shopcar:uid1024
全部选择 → hgetall shopcar:uid1024

2.5 Redis 集合(Set)

1) 定义及简述

Redis的集合和列表都可以存储多个字符串,他们之间的不同在于,列表可以存储多个相同的字符串,而集合通过使用散列表(hashset)来保证自己存储的每个字符串是各不相同(这些散列只有key,而没有与之对应的值),redis中的集合是无序的。

还可能存在另一种集合,那就是intset,它是用于存储整数的有序集合,里面存放同一类型的整数。共有三种整数:int16_t、int32_t、int64_t。查找的时间复杂度为O(logN),但是插入的时候,有可能会涉及到升级(比如:原来是int16_t的集合,当插入int32_t的整数的时候就会为每个元素升级为int32_t)这时候会对内存重新分配,所以此时的时间复杂度就是O(N)级别的了。

注意:intset只支持升级不支持降级操作。

intset在redis.conf中也有一个配置参数set-max-intset-entries默认值为512。表示如果entry的个数小于此值,则可以编码成REDIS_ENCODING_INTSET类型存储,节约内存。否则采用dict的形式存储。
在这里插入图片描述
Set集合类型底层使用intset和hashset两种数据结构;intset可以理解为数组,hashset就理解为普通的hash表key为set的值,value为null)
Set的底层存储intset和hashtable是存在编码转换的,使用intset存储必须满足下面两个条件,否则使用hashtable,条件如下:

  1. 集合对象保存的所有元素都是整数值
  2. 集合对象保存的元素数量不超过512个

2) 常用命令
在这里插入图片描述

2.6 Redis 有序集合(Sorted Set)

1) 定义及简述

zset类似于Java中的SortedSet和HashMap的结合体,一方面使用Set保证了内部Value的唯一性,给每一个value赋予score的排序权重。Zset的底层存储结构包括ziplist或skiplist,在同时满足以下两个条件的时候使用ziplist,其他使用skiplist,条件如下:

  1. 有序集合保存的元素数量小于128个
  2. 有序集合保存的所有元素长度小于64个

当ziplist作为底层存储结构时,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。

当skiplist作为zset的底层存储结构的时候,使用skiplist按序保存元素及分值,使用dict来保存元素和分值的映射关系

2)常用命令
在这里插入图片描述

2.7 Redis 位图(bitmap)

1) 定义及简述
bitmap是由0和1状态表现的二进制位的bit数组。
在这里插入图片描述
用String类型作为底层数据结构实现的一种统计二值状态的数据类型,位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(我们称之为一个索引)。

Bitmap支持的最大位数是232位,它可以极大的节约存储空间,使用512M内存就可以存储多达42.9亿的字节信息(232 = 4294967296)。

2) 常见命令
在这里插入图片描述

2.8 Redis 基数统计(HyperLogLog)

1)定义及简述

HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。(基数:去重后的元素真实个数

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

举例说明:
在这里插入图片描述
基数统计:用于统计一个集合中不重复元素的个数,就是对集合去重后的计算。

2)常用命令
在这里插入图片描述
实际案例
在这里插入图片描述

3)应用场景
1、网站首页亿级UV的统计方案

2.9 Redis 地理空间(GEO)

1)定义及简述
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,包括

  1. 添加地理位置的坐标。
  2. 获取地理位置的坐标。
  3. 计算两个位置之间的距离。
  4. 根据用户给定的经纬度坐标来获取指定范围内的地理位置集合

2) 常用命令
在这里插入图片描述

2.10 Redis 流(Stream)

1)定义及简述
Redis Stream 是 Redis 5.0 版本新增加的数据结构。

Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。

而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失

结构和原理
在这里插入图片描述
一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容
在这里插入图片描述

2) 常用命令
在这里插入图片描述
建议:

  1. stream 还是不能100%等价于Kafka、RocketMQ,生产案例少用、慎用。

2.11 Redis 位域(bitfield)

1)定义及简述
通过bitfield命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。说白了就是通过bitfield命令我们可以一次性对多个比特位域进行操作。

主要作用是:位域修改、溢出控制

2) 常用命令

BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

在这里插入图片描述

三、总结

本章介绍了redis的十大数据结构和它们使用的底层存储原理,为了达到节省内存和快速访问的目的每种数据结构可能有两种存储和访问结构,在必要的时候会由一种结构转换成另一种结构,但这个转换的过程会消耗系统性能和内存空间的,所以在使用的过程中需要注意这些配置参数,开发中尽量避免达到这些峰值,使得redis能够持续的提供高效的服务。

3.1 五种基本类型的常见场景

1)String类型

redis对于KV操作的效率很高,可以直接用于计数器,例如,统计在线人数等等,另外string类型是二进制存储安全的,所以也可以使用它来存储图片,甚至是视频等。

2)Hash类型

存放键值对,一般可以用来存某个对象的基本属性信息,例如,用户信息,商品信息等,

另外,由于hash的大小在小于配置的大小的时候使用的是ziplist结构,比较节约内存,所以针对大量的数据存储可以考虑使用hash来分段存储来达到压缩数据量,节约内存的目的,例如,对于大批量的商品对应的图片地址名称。比如:商品编码固定是10位,可以选取前7位做为hash的key,后三位作为field,图片地址作为value。这样每个hash表都不超过999个,只要把redis.conf中的hash-max-ziplist-entries改为1024,即可。

3)List类型

列表类型,可以用于实现消息队列,也可以使用它提供的range命令,做分页查询功能。

4)Set类型

集合,整数的有序列表可以直接使用set。可以用作某些去重功能,例如用户名不能重复等,另外,还可以对集合进行交集,并集操作,来查找某些元素的共同点,比如:去重作用实现中奖用户,共同好友等

5)zset类型

有序集合,可以使用范围查找,排行榜功能或者topN功能。

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

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

相关文章

基于Yolov8的NEU-DET钢材表面缺陷检测,优化组合新颖程度较高:CVPR2023 PConv和BiLevelRoutingAttention,涨点明显

1.钢铁缺陷数据集介绍 NEU-DET钢材表面缺陷共有六大类,分别为:crazing,inclusion,patches,pitted_surface,rolled-in_scale,scratches 每个类别分布为: 2.基于yolov8的训练 原始网络如下: map@0.5为0.733

博客系统(升级(Spring))(三)登录功能,注册功能,注销功能

博客系统 (三) 博客系统登录用户前端后端数据查询(在mapper上添加mapper接口) 注册用户前端后端插入数据 注销 博客系统 博客系统是干什么的? CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博客系统,这…

Spring Boot 中使用 Poi-tl 渲染数据并生成 Word 文档

本文 Demo 已收录到 demo-for-all-in-java 项目中,欢迎大家 star 支持!后续将持续更新! 前言 产品经理急冲冲地走了过来。「现在需要将按这些数据生成一个 Word 报告文档,你来安排下」 项目中有这么一个需求,需要将用户…

Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?

技术背景 好多开发者,问我们最多的问题是,为什么要设计轻量级RTSP服务?轻量级RTSP服务,和RTSP服务有什么区别? 针对这个问题,我们的回答是:轻量级RTSP服务解决的核心痛点是避免用户或者开发者…

59、SpringBoot 自定义JSON的序列化器和反序列化器

Serialization(序列化): 将java对象以一连串的字节码保存在磁盘文件中的过程,也可以说是保存java对象状态的过程。序列化可以将数据永久保存在磁盘上(通常保存在文件中)。 deserialization(反序列化): 将保存在磁盘文件中的java字节码重新转…

关于µC/OS-III 多任务的基本理解

关于C/OS-III 多任务的基本理解 任务和任务管理是 RTOS 的核心,且大多数项目使用 RTOS 的目的就是为了使用 RTOS 的多任务管理能力。 C/OS-III作为经典的RTOS,了解并学习其任务管理机制,是非常有必要的。 文章目录 关于C/OS-III 多任务的基本…

进阶C语言-指针的进阶(中)

指针的进阶 📖5.函数指针📖6.函数指针数组📖7.指向函数指针数组的指针📖8.回调函数 📖5.函数指针 数组指针 - 指向数组的指针 - 存放的是数组的地址 - &数组名就是数组的地址。 函数指针 - 指向函数的指针 - 存放的…

【Java】session的工作原理

文章目录 一、session的概念及特点session概念session主要有以下的这些特点 二、为什么要使用session三、session的工作原理四、session的生命周期Session何时生效Session何时失效 五、session的性能瓶颈六、session实现登录状态的控制 一、session的概念及特点 session概念 …

无涯教程-JavaScript - COUPDAYSNC函数

描述 COUPDAYSNC函数返回从结算日期到下一个息票日期的天数。 语法 COUPDAYSNC (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 RequiredMaturity 证…

基于第二代 ChatGLM2-6B P-Tuning v2 微调训练医疗问答任务

今天是教师节,恭祝全体老师们节日快乐!😊 一、ChatGLM2-6B 在本专栏前面文章中实验了使用 ChatYuan-large-v2 Freeze 微调训练医疗问答任务,训练后效果整体还可以,这篇文章继续探索使用最近比较火的 ChatGLM 官方推出…

docker镜像详解

目录 什么是docker镜像镜像相关命令docker pulldocker imagesdocker searchdocker rmi导出 / 导入镜像 镜像分层镜像摘要镜像摘要的作用分发散列值 什么是docker镜像 Docker镜像是Docker容器的基础组件,它包含了运行一个应用程序所需的一切,包括代码、运…

Sharding-Jdbc(2):Sharding-Jdbc入门案例

1 前置条件 搭建读写分离的数据库环境,搭建方法如下文,目标数据库test Mysql性能优化(5):主从同步原理与实现_mysql主从配置优化_不死鸟.亚历山大.狼崽子的博客-CSDN博客 2 新建maven项目 3 pom引入依赖 <?xml version="1.0" encoding="UTF-8"…

《protobuf》基础语法2

文章目录 枚举类型ANY 类型oneof 类型map 类型改进通讯录实例 枚举类型 protobuf里有枚举类型&#xff0c;定义如下 enum PhoneType {string home_addr 0;string work_addr 1; }同message一样&#xff0c;可分为 嵌套定义&#xff0c;文件内定义&#xff0c;文件外定义。不…

二维码智慧门牌管理系统:智能化地址管理,提升社会治理效率

文章目录 前言一、地址管理挑战二、二维码智慧门牌管理系统解决方案 前言 随着科技的飞速发展&#xff0c;我们的生活正经历前所未有的变革。尤其是智能化技术&#xff0c;已经深刻影响了我们的日常生活和工作环境。然而&#xff0c;在某些领域&#xff0c;如地址管理和社会治…

十大免费好用的视频软件推荐,新手小白必备

很多人都在使用视频软件进行编辑&#xff0c;那么你们知道哪些视频软件是免费的而且还好用&#xff1f; 现在很多小伙伴比较喜欢用手机编辑视频&#xff0c;而这些剪辑软件具有领先的智能化AI技术&#xff0c;让你不用绿幕就能一键挖出图像&#xff0c;不仅可以一键挖出三维人…

获取板块分类并展示

板块分类也会变动&#xff0c;偶尔看下&#xff0c;利于总体分析大盘 https:dapanyuntu.com/ 该网站含有板块信息 分析接口 搜素关键字 拷贝curl到curl解析工具&#xff0c;去掉无用的参数&#xff0c;生成requests代码 尝试nginx反代接口 server {listen 443;loca…

汇率失守7.3关口

号外&#xff1a;9.8教链内参《被判入狱1万年》。 拉锯多时的离岸人民币汇率USDCNH失守7.3关口&#xff0c;隔夜冲破7.36的高位。 为什么7.3是一个关键关口&#xff1f;因为这里是2022年10月底、11月初时曾经测试过的支撑位&#xff08;从CNH的角度说&#xff09;。 如果支撑位…

微信视频号挂公众号文章链接新方法:不限次数,不限号

当看到自己身边的人&#xff0c;通过我分享的方法绑定成功&#xff0c;那是开心到起飞了。 因为我知道&#xff1a;外面不靠谱的人很多&#xff01;分享不靠谱方法的人&#xff0c;可谓是更多。 为什么我要主动分享视频号评论区挂公众号文章链接&#xff1f;总有人伸张正义&a…

java中log使用总结

目录 一、概述1.1. 核心日志框架1.2 门面日志框架 二、最佳实践2.1 核心日志框架API包2.2 门面日志框架依赖2.3 集成使用2.3.1 集成jcl2.3.2 集成slf4j2.3.2.1 slf4j集成单一框架2.3.2.2 slf4j整合混合框架 三、总结3.1 所有相关包3.1.1 核心日志框架包3.1.2 门面日志框架3.1.3…

Python元类(metaclass)

Python 是一种强大的编程语言&#xff0c;一部分得益于其语言设计中独特的元类&#xff08;Metaclass&#xff09;机制。尽管元类的概念在刚开始接触时可能会让人感到困惑&#xff0c;但一旦理解了它们的工作原理和应用方式&#xff0c;我们就可以用它们做出强大且灵活的抽象。…