Redis深入学习笔记-01

本文深入介绍了Redis中的五种核心数据结构:字符串(string)、列表(list)、字典(hash)、集合(set)和有序集合(zset),包括它们的特性和应用场景,如字符串的动态增长、列表的高效插入删除、hash的渐进式rehash等。
摘要由CSDN通过智能技术生成

1、基础数据结构(五种)

string(字符串)、list(列表)、hash(字典)、set(集合)、zset(有序集合)。

string(字符串)

                                                      

        string内部表示的是一个字符数组,Redis所有的数据结构都以唯一的key字符串作为名词,然后通过这个唯一的key值来获取相应的value数据。不同类型的数据结构的差异就在于value的结构不一样。

                                       

        Redis的字符串是动态字符串,是可以修改的字符串,内部结构的实现类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,内部为当前字符串分配的实际空间capacity一般要高于实际字符串长度len,当字符串长度小于 lMB 时,扩容都是加倍现有的空间 。如果字符串长度超过 1MB ,扩容时一次只会多扩1MB 的空间 字符串最大长度为 512MB。

        字符串常见操作:

        

        如果value值是一个整数,可以进行自增操作,范围在signed long的最大值和最小值之间。超出就会报错。

                                 

 list(列表)

        Redis的列表相当于Java中的LinkedList,是一个双向链表。插入和删除操作非常快,时间复杂度为O(1),但是索引定位很慢,时间复杂的为O(n)。当列表弹出了最后一个元素之后,该数据结构被自动删除,内存会回收。

               

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

        列表常见操作:队列和栈

                

        

 

 如果再深入的一点的话,Redis的底层存储不是一个简单的linkedlist,而是称之为“快速链表(quicklist)”的一个结构。后续介绍。

 

hash(字典)

        相当于Java中的HashMap,是一个无序字典,底层也是链表加数组。但是不同的是Redis的字典的值只能是字符串,另外rehash的方式也不一样。因为 Java HashMap 在字典很大时 rehash 是个耗时的操作,需要一次性全部rehash。Redis 为了追求高性能,不能堵塞服务,所以采用了渐进 式rehash 策略。

        渐进式rehash会在rehash的同时,保留新旧两个hash结构。查询的时候会同时查询两个hash结构,然后在后续的定时任务以及hash操作指令中,循序渐进地将旧hash的内容一点点地迁移到新的hash结构中。当搬迁完成了,就会使用新的hash结构取而代之。

                                   

         当hash移除了最后一个元素后就会该数据结构自动删除,内存被回收。

     hash结构也可以用来存储用户信息,与字符串需要一次性全部序列化整个对象不同,hash可以对用户结构中的每个字段单独存储,这样当我们需要获取用户信息时可以进行部分获取。而以整个字符串的形式去保存用户信息的话,就只能一次性全部读取,这样就会浪费网络流量。

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

        hash常见操作:

        

          

 

set(集合)

        Redis的集合相当于Java语言里面的HashSet,内部的键值对是无序的、唯一的。它的内部实现相当于一个特殊的字典,字典中所有的value都是一个值null。

        同样的,如果集合中最后一个元素被删除后这个数据结构就会被自动删除,内存被回收

        set结构可以用来存储在某活动中中奖的用户ID,因为有去重的功能,可以保证同一个用户不会中奖两次。

 

 zset(有序列表)

        zset类似于Java的SortedSet和HashMap的结合体,一方面它是一个set,保证了内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。它的内部实现用的是一种叫作“跳跃列表”的数据结构。

        zset中最后一个元素被移除后该数据结构就会被删除,内存被回收。

        zset可以用来存储粉丝列表,value是粉丝的用户ID,score是关注时间。我们可以对粉丝列表按关注时间进行排序。

        

跳跃列表

zset内部的排序功能是通过“跳跃列表”数据结构来实现的,它的结构非常特殊,也比较复杂。因为 zset 要支持随机的插入和删除,所以它不宜使用数组来表示。我们先看一个普通的链表数据结构

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

位置定位,链表做不到,那该怎么办?

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

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

        想想你老家在世界地图中的位置:亚洲→中国→某省→某市→某县→某镇→某村→门牌某号,也是这样一个结构。

        “跳跃列表”之所以“跳跃”,是因为内部的元素可能“身兼数职”,比如图1-12中间的这个元素,同时处于LO、L1和L2层中,可以快速在不同层次之间进行“跳跃”。

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

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

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

        跳跃列表内部结构,后续再更新。

        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失忆机器

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值