5种基础数据结构

  • Redis有5种基础数据结构,分别是:String(字符串),list(列表),hash(字典),set(集合),zset(有序集合),这五种是我们开发种经常用的到的,是Redis种最基础,最重要的部分。
string(字符串)
  • 字符串string是Redis最简单的一个数据结构,他的内部表示是一个字符数组,Redis所有的数据结构都以唯一的key字符串作为名称,然后通过这个唯一的key获取对应的value数据,不同类型数据结构差异其实就在value上而已。如下图对应String类型字符串示意图:
  • Redis的字符串底层实现其实是动态的字符串,是可以修改的字符串,内部结构实现类似java种的ArrayList,采用预分配的方式冗余了一部分空的内存空间来减少频繁的内存重新分配的环节,如下图,内部为当前字符串分配的实际空间Capacity,一般比我们字符串长度len更多,当字符串长度小于1M时候,扩容都是加倍现有空间,如果字符串长度超过1M,扩容的时候,只会扩容1M内存(生产上一个1M的字符也比较大了,不建议这么搞)。注意,字符串最大长度512M。
  • 如果这个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基础数据结构之二

Redis基础数据结构内部实现简单介绍相关推荐

  1. redis 基础数据结构实现

    参考文献 redis数据结构分析 Skip List(跳跃表)原理详解 redis 源码分析之内存布局 Redis 基础数据结构与对象 Redis设计与实现-第7章-压缩列表 在redis中构建了自己 ...

  2. redis 基础数据结构 之压缩列表

    redis基础数据结构 之 ziplist压缩链表 给新观众老爷的开场 ziplist是什么? ziplist的设计目的 ziplist的作用 ziplist的小瑕疵 ziplist 的空间布局 zl ...

  3. Redis基础数据结构

    Redis是一款完全免费的,高性能的key-value数据库,目前被大多数公司用来做缓存.Redis作为一个内存数据库,它的读写速度非常快:读速度可以达到110000次/s,写的速度是81000次/s ...

  4. salesforce lightning零基础学习(一) lightning简单介绍以及org开启lightning

    lightning对于开发salesforce人员来说并不陌生,即使没有做过lightning开发,这个名字肯定也是耳熟能详.原来的博客基本都是基于classic基于配置以及开发,后期博客会以ligh ...

  5. redis基础数据结构(一)可变长字符串sds

    redis中的字符串是二进制安全的,传统C字符串以'\0'为结尾,只能用于保存纯文本,不能用于保存音频.视频等二进制文件,因为只要在中间遇到'\0'就被截断了.redis的sds模块所有api都使用二 ...

  6. Redis基础数据结构String:你知道String长度限制多少吗

    字符串String是Redis最简单最常用的数据结构,它的内部表示就是一个字符数组,如图所示.Redis所有的数据结构都是以唯一的key字符串作为名称,然后通过这个唯一key值来获取相应的value数 ...

  7. 《剑指offer》——基础数据结构:从简单知识构建细致扎实的思考和实现能力...

    待补充-- 转载于:https://www.cnblogs.com/qinziang/p/9097047.html

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

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

  9. Redis基础篇(万丈高楼平地起):核心底层数据结构

    微信原文链接,排版更舒适. 大家好,我是小龙.近期有很多小伙伴私信我Redis怎么做持久化?集群方案怎么做?分布式锁怎么实现?可是我发现,每次简答完一个问题他还有其他类似问题,或则各个知识点不能串通形 ...

最新文章

  1. PHP设置禁止目录索引,/var/www/html目录索引禁止
  2. [Python正则表达式] 字符串中xml标签的匹配
  3. 机器学习——图解SVM中gamma和c参数的作用
  4. java框架讲解ppt_经典框架spring介绍课件.ppt
  5. A1156. 开心的金明
  6. 程序员如何探索新技术
  7. 安装jdk时更改java安装路径_JDK下载安装步骤
  8. blackberry 7290 滚轮 垂直滚动
  9. 删除windows默认共享
  10. 如何用powershell安装2345推广软件
  11. Python爬虫:让“蜘蛛”帮我们工作
  12. 爬虫——爬取人民网数据生成词云图
  13. 你最期待的热门思维导图测评在这里!
  14. container_of 和 offsetof 解析
  15. 整理10类Java毕设练手项目,献给帅帅的计算计专业毕业人
  16. 防止phpddos发包攻击
  17. 读《一本小小的蓝色逻辑书》:识别常见的逻辑漏洞
  18. 局域网、广域网、城域网的介绍,
  19. 三十一、java版商城之移动商城金刚区管理 Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入驻商城 直播带货商城 电子商务
  20. 【OpenCV】- 部署至IEDA

热门文章

  1. IOS之学习笔记四(类的实现和对象和id)
  2. Android之通过ActivityLifecycleCallbacks判断程序是否运行在后台
  3. Android之jni调用java函数总结
  4. Android之版本检测和更新
  5. 勾股定理的形象拆分法,原来数学可以这么好玩!
  6. 老师“鬼话”全曝光!哈哈哈哈哈全国的老师都这样吗?
  7. 100斤的铁和100斤女生哪个重?
  8. 再过四十年,你的女朋友可能是个美丽的机器人!不信你看
  9. jsp iframe嵌入php,jsp嵌套iframe从iframe中表单提交并传值到外层_html/css_WEB-ITnose
  10. linux挂载4t硬盘用不了,centos7挂载新加4T硬盘到/home目录