Redis基础数据结构内部实现简单介绍

5种基础数据结构

  • Redis有5种基础数据结构,分别是:String(字符串),list(列表),hash(字典),set(集合),zset(有序集合),这五种是我们开发种经常用的到的,是Redis种最基础,最重要的部分。
string(字符串)
  • 字符串string是Redis最简单的一个数据结构,他的内部表示是一个字符数组,Redis所有的数据结构都以唯一的key字符串作为名称,然后通过这个唯一的key获取对应的value数据,不同类型数据结构差异其实就在value上而已。如下图对应String类型字符串示意图:
    Alt
  • Redis的字符串底层实现其实是动态的字符串,是可以修改的字符串,内部结构实现类似java种的ArrayList,采用预分配的方式冗余了一部分空的内存空间来减少频繁的内存重新分配的环节,如下图,内部为当前字符串分配的实际空间Capacity,一般比我们字符串长度len更多,当字符串长度小于1M时候,扩容都是加倍现有空间,如果字符串长度超过1M,扩容的时候,只会扩容1M内存(生产上一个1M的字符也比较大了,不建议这么搞)。注意,字符串最大长度512M。
    Alt
  • 如果这个string类型的数据value是一个整数,Redis还提供来一种自增的操作,他的自增范围是signed long的最大值最小值之间,超过这个范围,Redis会报错。
set age 30
incr age //自增
list(列表)
  • Redis的list相当于Java中的LinkedList,他是链表而不是数组。这个意味着list的插入和删除是很快的,事件复杂度是O(1),但是下标索引定位慢,事件复杂度O(n),Redis中实现是一个双向链表结构的保证顺序性,串起来可以同时支持前后的方向便利,当列表弹出最后一个元素,该数据结构被自动删除,内存回收。如下图
    在这里插入图片描述
  • Redis的列表结构可以用来做简单的异步队列使用,将需要延后处理的任务结构化为一个字符串,放到Redis列表中,另一个线程在列表中逐个弹出。
右近左出:队列
  • 队列是先进先出的数据结构,用于消费队列和异步的逻辑处理,他会确保元素的访问顺序性。如下图
    在这里插入图片描述
右边进右边出:栈
  • 栈是先进后出的数据结构,跟队列正好相反,我们用Redis的列表数据结构来做栈使用如下:
    在这里插入图片描述
警惕慢操作
  • lindex相当于java链表的get方法,他需要遍历整个链表,性能O(n),随着参数index的增加而增加
  • ltrim 与字面上意思不一致,保留一段期间内的值,删掉区间以外的,可以通过这个来获取一个定长列表,index可以是负数,-1是倒数第一个,-2 倒数第二个
ltrim key start_index end_index // 删除start_index到 end_index以外的所有元素
内部存储:快速列表
  • Redis的底层存储的不是一个简单的LinkedList,而是一个快速列表的一个结构
  • 首先元素较少的时候,会使用一块连续的内存存储,这个结构叫做ziplist,压缩列表。他所有的元素彼此紧挨在一起存储,分配的是一块连续的内存(可以看作一个数组)
  • 当数据量比较多的时候才会改成quicklist。因为普通列表需要的附加指针占用空间太大比如我们list中都是int类型的数据,那么每一个节点还需要维护两个指针prev,next,指针所占用的内存比实际数据还要多
  • 所以Redis将链表和ziplist结合使用,组成quicklist,也就是将多个ziplist用双向指针串起来,就可以节省很多指针空间。如下图。
    在这里插入图片描述
hash(字典)
  • Redis的字典相当于Java中的HashMap,,他是无顺序的字典结构,内存存储多个key,value,
    在这里插入图片描述
  • 实现结构与Java中HashMap也类似,都是数组+链表的而为结构,如下图,第一纬度的hash结构数组会发生重合的情况,也就是两个key的hash值一样,就会使用链表的形式将元素串起来。
    在这里插入图片描述
  • 不同地方Redis的字典值只能是字符串,另外他们的rehash的方式也不一样,因为Java的HashMap字典很大时候,rehash的耗时很多,而且一次性全部完成,Redis为追求高性能,不能堵塞服务,所以采用渐进式rehash策略
  • 渐进式rehash会在rehash的同时,保留新旧两个hash结构,查询时候同时查询两个字典结构,后续Redis会在定时任务以及hash操作指令中,逐渐的将旧的hash内容一点点迁移到新的hash结构,完成后才用新的。(空间换时间)
    在这里插入图片描述
  • 当hash结构最后一个元素被移除,该数据结构会自动删掉,内存自动回收。
  • 同字符串一样,hash结构也有单个key的计数功能,他对于指令是hincrby,和incr使用方法基本一致
127.0.0.1:6379> hset user age 29
(integer) 1
127.0.0.1:6379> hset user height 171
(integer) 1
127.0.0.1:6379> hincrby user height
(error) ERR wrong number of arguments for 'hincrby' command
127.0.0.1:6379> hincrby user height 1
(integer) 172
127.0.0.1:6379> hget user height
"172"
set(集合)
  • Redis的集合相当于java中的HashSet,内部的键值对是无序的,唯一的。他的内部实现相当于一个特殊的字典,字典中的所有value都是一个NULL而已,同样当集合最后一个元素被移除也会被删除,自动回收内存。
  • set结构可以用来存储中奖用户id,因为有去重的功能,保证唯一性。
zset(有序列表)
  • zset是Redis提供的最有特色的一个数据结构,类似java的sortedSet和HashMap的结合体,应为他有两者特点,首先他是一个set,所以保证内部每个value的唯一性,另外他给每个value的排序赋予一个权重score,代表这个value的排序权重,他内部实现是一个叫”跳跃表“的数据结构。
跳跃列表
  • zset的内部排序功能是通过跳跃表数据结构来实现的,他的结构非常特殊,因为zset既要支持随机的插入和删除,所以他不能用数组,数组需要遍历

  • Zset要支持按照score排序,这意味着有新元素插入,需要定位特定的位置插入点,这样才可以保证有序性,通常我们用二分查找(平均时间复杂度最小),但是二分查找对象都是数组,链表无法做到这样就两个条件矛盾来用如下的结构来解决这个问题:变异形态的链表

  • 比如我们平时公司的结构中,研发人员平等,都有一个组长,各个组长平等,组长上有leader,各个leader之间平等,leader上没有总监,依次向上到最后的CEO,跳跃表就类似这样的一个层级结构

  • 最下面的一层是所有元素都串起来,然后每隔几个元素挑选出一个代表,再将这几个代表用另外一个指针串联。接着在这些代表中继续挑选出二级代表,形成新的金字塔结构。如下:
    在这里插入图片描述

  • 解释:

    • 类比二分法,当我们用二分发时候,先找到middle位置,比较中间位置的value和将要insert进去元素的value,如果小,则将0~middle作为新的链表,如果大middle-max作为新的链表重新以上步骤,来到第二层。
    • 如上图,我们定位插入点时候,先从顶层开始,我们将最顶层的一个节点就相当于中间位置,只不过他是我们通过特殊的数据结构暴露出来的一个中间位置,然后类比上面步骤,我们进入到第二层中,比较中间位置的L2和将要insert进去元素的value,如果小,将L1层级中中0~L2位置元素作为新的链表,我们通过这样逐层的比较,直到最底层找到合适的位置,将新的元素insert进去。
    • 这种做法就相当于将二分法的步骤拆开后,得到N个链表,每个链表都是我们二分法中每个步骤中需要查找的那个半个数组而已,通过比较每个数组中的中间value值来得出最后的位置。用冗余的方式来避免链表的遍历(替换数组的下标索引功能)
  • 跳跃表中节点可以在多个层级有多个身份,跳跃表采用随机策略决定新元素可以到第几层,L0层概率是1 ,L1 只有50%对半分,L2 再次25%,L3只有12.5%,依次,一直随机到顶层L31,每次对半,到顶层基本不会有很多数据。

容器类型数据结构的通用规则

  • list,set, hash, zset四种数据结构是容器型数据结构,他们共享下面几个规则:
    • create if not exists:如果容器不存在,那就创建一个,子啊进行操作,比如rpush操作刚开始没有列表,会新建一个列表,然后在rpush元素
    • drop if no elements:如果容器中没有元素,会立即删除容器,释放内存。意味着lpop操作完最后一个元素后列表就会消失。
    • 过期时间设置,到期自动删除,注意如果一个key设置来过期时间后调用set方法修改,过期时间会消失。

上一篇Redis数据结构以及对应存储策略
下一篇Redis基础数据结构之二

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

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

相关文章

[剑指offer]面试题7:用两个栈实现队列

面试题7:用两个栈实现队列 题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。 用两个栈模拟一个队列的操作: 代码如下: #include …

ASP.NET CORE WEBAPI文件下载

最近要使用ASP.NET CORE WEBAPI用来下载文件,使用的.NET CORE 3.1。考虑如下场景:文件是程序生成的。文件应该能兼容各种格式。浏览器可以感知进行下载。准备经过简单的调研,得到以下结论。ASP.NET CORE 提供FileResult这种类型的ActionResul…

Redis高级数据结构原理解析-bitmap,hyperloglog

Redis 位图 开发过程中,我们可能遇到这种场景记录用户的打卡情况,签到情况,这些场景只有两种结果,有或者没有,加入记录的数据量比较大,比如用一年的数据,如果用Redis中普通key/value&#xff0…

[剑指offer]面试题8:旋转数组的最小数字

面试题8:旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数…

.NET Core + Kubernetes:快速体验

Kubernetes[1] 是目前非常主流的容器编排工具,在应用创建、应用部署、应用扩容、应用更新等方面都非常的方便,而且在应用故障时,也可以快速自愈。所以基于微服务架构下的产品,了解 Kubernetes 的使用是非常必要的,我猜…

[剑指offer]面试题9:斐波那契数列

面试题9:斐波那契数列 题目一:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契数列的定义如下: ❖ 效率很低的解法,挑剔的面试官不会喜欢 代码如下: long long fib(…

Redis分布式锁奥义

分布式锁 分布式系统进行逻辑处理的时候,经常会遇到并发问题,例如直播场景中,用户需要连麦主播,当多个用户在同一个时刻一起连麦时候,应该保证只有一个用户能连麦成功,我们改怎么保证这种业务场景下保证数…

.NET Core + Kubernetes:Pod

在 .NET Core Kubernetes:快速体验 文章中,已经实现将一个 .NET Core API 服务部署在 Kubernetes 集群中,接下来将逐步了解 Kubernetes 中各核心模块。首先当然是 Pod,我相信 Pod 是在接触 Kubernetes 时听到较多的一个词语&…

LBS解决方案

LBS解决方案 LBS(基于地理位置的服务)服务是现在移动互联网中比较常用的功能,例如外卖中我附近的店铺,通常是以客户位置坐标为中心,查询一定范围内的店铺信息,按照距离由近及原进行倒叙排序 方案一&#…

长沙IT技术圈百万年薪大佬?是否存在?

作者:邹溪源,长沙资深互联网从业者,架构师社区特邀嘉宾!01引子不知不觉,IT技术圈开始流传起“百万年薪”的故事,有人问我,长沙有百万大佬么?其实我也不知道。02背景长沙自古以来就是…

网络编程-网络分层的意义

网络 我们生活在一个网络无处不在的一个虚拟世界中,网络中的每一个设备都是一个节点。大多是我们的计算机,但是他还可以连接其他设备,例如打印机,路由器,网关,你的手机,智能家居等。我们可以使…

网络编程-TCP/IP协议栈-IP协议

协议 协议就是约定的一种规则&#xff0c;例如扑克游戏中约定好的各种规则&#xff0c;2<3<4<5<…等&#xff0c;以此作为游戏规则。当所有人都遵循这个规则&#xff0c;那么久可以不需要任何多余的交流就可以进行游戏&#xff0c;这个方式形成的约定就是一种协议…

.NET项目升级手记:可为空引用

c# 8引入了新特性&#xff1a;“可为空引用”&#xff08;详情&#xff09;&#xff0c;这个功能个人觉得挺好的&#xff0c;能够非常明确的表现程序设计者的意图&#xff0c;编译器能够进行检查&#xff0c;尽最大可能减小NullReferenceException错误。如果是新项目&#xff0…

.NET与鲲鹏共展翅,昇腾九万里(一)

2019年1月7日&#xff0c;华为推出鲲鹏920处理器&#xff0c;便宣告了构建鲲鹏生态系统的开始。据官方介绍&#xff0c;鲲鹏是一个包含了鲲鹏计算单元、AI处理单元、智能管理、智能网卡的片上系统SoC&#xff0c;在此之上加上服务器操作系统&#xff0c;从而形成一个生态的闭环…

网络编程-TCP/IP协议栈-TCP协议

TCP协议 TCP协议作用 TCP协议位于协议栈的传输层。当应用层向TCP层发送用于网间传输的&#xff0c;用8字节表示的数据流&#xff0c;TCP则吧数据流分割成适当长度的报文段&#xff0c;最大传输段大小&#xff08;MSS&#xff09;通常受到改计算机连接的网络数据链路层的最大传…

互联网10年,激战如梦

— 1 —1969年&#xff0c;美国国防部研究计划署第一次将互联网应用于军事连接。随后美国西南部四所名校的四台计算机通过这项技术连接起来。谁也没想到&#xff0c;这项计划会对人类的命运产生如此重大影响。1993年&#xff0c;互联网真正诞生。美国白宫宣布开始提供「在线服务…

网络编程-TCP/IP协议栈-UDP/HTTP协议

UDP协议 UDP协议全称是用户数据报协议&#xff0c;在网络中她与TCP协议一样用于处理数据包&#xff0c;两个协议同处于协议栈的传输层&#xff0c;和TCP不同的是&#xff0c;UDP是一种无连接的协议栈。 因为UDP是无连接的&#xff0c;所以相对来说&#xff0c;UDP的报头比TCP要…

十问十答 Ms-PL 许可证

Microsoft 公共许可证&#xff08;The Microsoft Public License&#xff09;是微软为释出开源项目而编写和发布的自由开源软件许可证。如果你用 .NET 开发&#xff0c;你会经常碰见 Ms-PL。在微软的自由开源项目托管地 Codeplex&#xff08;已寿终正寝&#xff0c;微软已战略转…

网络编程-HTTPS协议的实现原理

HTTP传输协议缺点 之前几篇文章中详细讲解了TCP/IP协议栈中的几个协议&#xff0c;其中个就有对HTTP做了一个比较详细的讲解。HTTP是基于TCP进行传输的&#xff0c;其中传输的内容都是明文报文数据&#xff0c;如果我是一个黑客&#xff0c;我会想办法获取这个HTTP消息体&…

从案例角度解析建模平台动态规则引擎

源宝导读&#xff1a;明源云ERP建模平台提供了强大的页面联动规则引擎&#xff0c;原来需要编写代码完成的联动控制逻辑&#xff0c;现在只需要点点鼠标&#xff0c;通过配置完成。本文从实际案例的角度出发&#xff0c;介绍原始的代码逻辑如何转化为引擎规则的过程。一、背景明…