来补补底层知识?Redis基础数据结构 | 小册免费学
mhr18 2024-11-30 12:27 20 浏览 0 评论
Redis所有的数据结构都是key-value形式,并且key字符串是唯一的,不同类型的数据结构的差异就在于value的结构不一样,下面我们就来看看Redis有哪些基础数据类型吧
- Redis基础数据结构
- string(字符串)
- list(列表)
- set(集合)
- zset(有序集合)
- hash(哈希)
string
value为string的数据结构 Redis的字符串为动态字符串,是可以修改的字符串。内部结构是实现类似ArrayList,会动态扩容,并且会预分配冗余空间的方式来减少内存的频繁分配。一般会分配多余实际字符串长度的容量。
扩容机制:当字符串小于1M时,扩容都是加倍现有的空间,超过1M,扩容每次只会扩容1M,且字符串最大容量为512M
常用应用场景:缓存用户信息,通过序列化成JSON字符串存入Redis缓存,然后反序列化变成所需用户信息。
操作(在Redis客户端): 键值对 命令: 存值:set 键名 value值 取值:get 键名
批量键值对 可以批量读写多个字符串,节省网络耗时IO开销 命令: 存值:mset 键名1 v1 键名2 v2... 取值:mget 键名1 键名2
过期和set命令 过期命令:expire 键名 timeout 默认过期实践单位为秒 原子性存值+过期:set 键名 timeout value值
键存在返回1并执行set创建,键不存在返回0,set创建失败,setnx因为此特性,常被用来作为锁 setnx 键名 value值
计数 如果value是整数时,还可以对其自增,自增的范围为有符号的singed long的max和min,超过会报错 incr 键名 incrby 键名 步长(负数为自减)
list(列表)
Redis的列表结构为链表,插入,删除,时间复杂度为O(1),索引定位时间复杂度为O(n)。
而且列表弹出一个元素后,该数据结构被删除,内存被回收
使用场景: 经常使用左进右出数据结构做异步队列使用,将需要延后处理的任务塞进Redis列表,而另一个线程从这个列表中轮询数据进行处理
右进左出:队列 rpush 键名 v1 v2 ... 查看长度:llen books 取出数据:lpop books
右进右出:栈 rpush 键名 v1 v2 ... 取出数据:rpop books
慢操作 取出对应索引值:lindex 键名 去除区间外的值:ltrim 键名 start end 保留start-end区间的值,可以使用ltrim做一个定长的链表 index为负数时,-1为倒数第一,以此类推
快速链表 Redis列表的底层时一个quicklist结构 元素较少时:连续内存存储 结构:ziplist压缩列表 数据量较多时:将链表和ziplist结合形成quicklist,将多个ziplist使用双向指针连接 优点:每个元素都挂两个指针时会浪费空间,增重内存碎片化
hash(字典)
Redis的hash相当于Java的HashMap,无序字典
内部结构实现:数据加链表
第一维hash的数组碰撞后,将会将碰撞的元素用链表串起来
与Java中HashMap比较:Redis的字典值只能是string,rehash方式不同,Java的HashMap在字典很大时,rehash是个很耗时的操作,需要一次性全部rehash,Redis使用渐进式rehash策略,不堵塞服务。
渐进式rehash:在rehash的同时,保留了新旧两个hash结构,查询时会同时查询两个hash结构,然后在后续的定时任务以及hash操作指令中,循序渐进的将旧hash的内容迁移到新的hash结构中,当搬移完成了,新hash结构会取而代之
hash移除最后一个元素后,该数据结构自动被删除,内存被回收
hash结构也可以用来存储用户信息,string存储用户信息时需要全部序列化整个对象,hash可以对用户结构的每个字段单独存储,所以获取用户信息时就可以部分获取,可以节约网络流量。
hash缺点:hash结构存储消耗高于当个string
命令: 设置值:hset 键名 属性 属性值 取值:hgetall 键名 #entries()、hget 键名 属性名(取特定的属性值) 长度:hlen 键名
hash中单个属性值与string类似,可以进行自增 hincrby 键名 属性名 步长 incr 键名 属性名
set(集合)
Redis的集合可以类比于Java中的HashSet,他的内部键值对是无序的、唯一的
内部实现:特殊的字典,字典的每个value值为NULL
当集合中最后一个元素被移除后,数据结构自动删除,内存被回收
使用场景(去重):存储活动中奖用户,通过去重,保证用户不会中奖两次
命令 设置值: sadd 键名 value(可以多个value) 取值:smembers 键名 取一个:spop 键名 某个value是否存在:sismember 键名 value 长度:scard 键名
zset(有序集合)
Redis特有的数据结构,类似于Java中SortedSet和HashMap的结合体,set保证了value的唯一性,score代表value的权重,根据这个权重排序
内部实现:跳跃列表
zset最后一个value被移除后,数据结构被删除,内存被回收
应用场景(排序相关): 粉丝列表:value为ID,score为关注时间 学生成绩单:value为ID,score为成绩
命令 设置值:zadd 键名 权重 value 按权重排序列出:zrange 键名 start end (start end表示排序区间0 -1 表示所有) zrevrange 键名 start end 倒序 长度:zcard 键名 取某个值的权重score:zscore 键名 value 查看某个值的排名:zrank 键名 value 查看某个权重区间的值:zrangebyscore 键名 start end (start end 为权重区间) zrangebyscore 键名 -inf end withscores(-∞到end,并返回权重) 删除:zrem 键名 value
跳跃链表
zset内部实现:hash+跳跃链表
一个普通的链表查找元素的时间复杂度为O(N),即使单链表中的元素都是有序的,而数组可以利用二分查找的方法查找元素,面对有序的元素时,查找的时间复杂度为O(logn),而为了让链表查找效率更快,则出现了可以“二分查找”的链表:跳跃链表。
跳跃链表是一个有序的数据结构,每个节点维护了多个指向其他节点的指针,从而达到快速查找的目的。
当Redis中zset包含的元素比较多,或元素成员是比较长的字符串时,跳跃链表的优势会非常明显
跳跃链表可以理解为多层的链表
- 多层的结构组成,每层都是一个有序的链表
- 最底层(level 1)的链表包含了所有的元素
- 跳跃表的查找次数近似于层数,时间复杂度为O(logn),插入,删除也为O(logn)
- 跳跃表是一种随机化的数据结构(通过抛硬币的方式来决定层数)
- 跳跃表的空间复杂度为O(logn)
如何让有序的链表查找速度更快呢?查找 因为元素都是有序的,我们可以再增加一些路径来加快查找速度。 路径:多加一层隔一个排序的有序链表 通过对上一层的元素与查找元素的比较(二分查找),决定是否进入下一层查找。
如何维护这个链表呢?插入与删除 插入或删除时,跳跃表的节点树就会改变,意味着跳跃表的层数也会动态改变
新插入的元素应该跨越几层呢? 采取策略:抛硬币,每次插入一层的一个节点时,抛一次硬币,不满足条件时统计次数,这个次数就是新插入元素的层数。
如何删除元素呢 直接把该元素跨域的层级删除即可
跳跃表vs二叉查找树 二叉查找树的查找、新增、删除也是近似O(logn),但存在一种极端情况,当数据有序时,此时就是一层有序的链表了,此时的查找、新增、删除的复杂度就变成O(n)了
跳跃表vs红黑树 红黑树在新增、删除节点时,会通过调整结构来保持红黑树的平衡,而跳跃表,通过一个随机数来决定跨域层级,由此可见红黑树的新增、删除时维护的花销是更高的
容器型数据结构的通用规则
list/set/zset/hash这四种容器型数据结构,共有的通用规则:
1.create if not exists 如果该容器未创建,那就新创建一个
2.dorp if no elements 如果该容器中已经没有元素了,就会删除这个容器的数据结构,释放内存
过期时间
Redis所有的基础数据结构都可以设置过期时间的,并且是以对象维度设置的。到期之后Redis会自动删除对应的对象,而不是对象中的某个元素值。
对于string的特殊性:当对一个string设置了过期时间,之后又修改了这个string,过期时间会消失
作者:清色池塘
链接:https://juejin.cn/post/6951272935566868517
相关推荐
- Spring Boot 分布式事务实现简单得超乎想象
-
环境:SpringBoot2.7.18+Atomikos4.x+MySQL5.71.简介关于什么是分布式事务,本文不做介绍。有需要了解的自行查找相关的资料。本篇文章将基于SpringBoot...
- Qt编写可视化大屏电子看板系统15-曲线面积图
-
##一、前言曲线面积图其实就是在曲线图上增加了颜色填充,单纯的曲线可能就只有线条以及数据点,面积图则需要从坐标轴的左下角和右下角联合曲线形成完整的封闭区域路径,然后对这个路径进行颜色填充,为了更美观...
- Doris大数据AI可视化管理工具SelectDB Studio重磅发布!
-
一、初识SelectDBStudioSelectDBStudio是专为ApacheDoris湖仓一体典型场景实战及其兼容数据库量身打造的GUI工具,简化数据开发与管理。二、Select...
- RAD Studio 、Delphi或C++Builder设计代码编译上线缩短开发时间
-
#春日生活打卡季#本月,Embarcadero宣布RADStudio12.3Athens以及Delphi12.3和C++Builder12.3,提供下载。RADStudio12.3A...
- Mybatis Plus框架学习指南-第三节内容
-
自动填充字段基本概念MyBatis-Plus提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等。原理自动填充功能通过实现com.baomidou.myba...
- 「数据库」Sysbench 数据库压力测试工具
-
sysbench是一个开源的、模块化的、跨平台的多线程性能测试工具,可以用来进行CPU、内存、磁盘I/O、线程、数据库的性能测试。目前支持的数据库有MySQL、Oracle和PostgreSQL。以...
- 如何选择适合公司的ERP(选erp系统的经验之谈)
-
很多中小公司想搞ERP,但不得要领。上ERP的目的都是歪的,如提高效率,减少人员,堵住财务漏洞等等。真正用ERP的目的是借机提升企业管理能力,找出管理上的问题并解决,使企业管理更规范以及标准化。上ER...
- Manus放开注册,但Flowith才是Agent领域真正的yyds
-
大家好,我是运营黑客。前天,AIAgent领域的当红炸子鸡—Manus宣布全面放开注册,终于,不需要邀请码就能体验了。于是,赶紧找了个小号去确认一下。然后,额……就被墙在了外面。官方解释:中文版...
- 歌浓酒庄总酿酒师:我们有最好的葡萄园和最棒的酿酒师
-
中新网1月23日电1月18日,张裕董事长周洪江及总经理孙健一行在澳大利亚阿德莱德,完成了歌浓酒庄股权交割签约仪式,这也意味着张裕全球布局基本成型。歌浓:澳大利亚年度最佳酒庄据悉,此次张裕收购的...
- 软件测试进阶之自动化测试——python+appium实例
-
扼要:1、了解python+appium进行APP的自动化测试实例;2、能根据实例进行实训操作;本课程主要讲述用python+appium对APP进行UI自动化测试的例子。appium支持Androi...
- 为什么说Python是最伟大的语言?看图就知道了
-
来源:麦叔编程作者:麦叔测试一下你的分析能力,直接上图,自己判断一下为什么Python是最好的语言?1.有图有真相Java之父-JamesGoshlingC++之父-BjarneStrou...
- 如何在Eclipse中配置Python开发环境?
-
Eclipse是著名的跨平台集成开发环境(IDE),最初主要用来Java语言开发。但是我们通过安装不同的插件Eclipse可以支持不同的计算机语言。比如说,我们可以通过安装PyDev插件,使Eclip...
- 联合国岗位上新啦(联合国的岗位)
-
联合国人权事务高级专员办事处PostingTitleIntern-HumanRightsDutyStationBANGKOKDeadlineOct7,2025CategoryandL...
- 一周安全漫谈丨工信部:拟定超1亿条一般数据泄露属后果严重情节
-
工信部:拟定超1亿条一般数据泄露属后果严重情节11月23日,工信部官网公布《工业和信息化领域数据安全行政处罚裁量指引(试行)(征求意见稿)》。《裁量指引》征求意见稿明确了行政处罚由违法行为发生地管辖、...
- oracle列转行以及C#执行语句时报错问题
-
oracle列转行的关键字:UNPIVOT,经常查到的怎么样转一列,多列怎么转呢,直接上代码(sshwomeyourcode):SELECTsee_no,diag_no,diag_code,...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)