浅谈一下Redis的数据结构

 更新时间:2023年08月12日 11:12:30   作者:bibiwannbe  
这篇文章主要介绍了浅谈一下Redis的数据结构,简单字符串结构被用于存储redis的key对象和String类型的value对象,其中的free和len字段可以轻松的使得在该字符串被修改时判断是否需要扩容,需要的朋友可以参考下

一、简单动态字符串SDS

struct sdshdr {
  int len;
  int free;
  char[] buf;
}

简单字符串结构被用于存储redis的key对象和String类型的value对象

其中的free和len字段可以轻松的使得在该字符串被修改时判断是否需要扩容。

为啥呢?因为redis的协议发送一个SET请求时格式开头会带上需要插入的value的长度,这样根据free以及len可以判断此时redis分配的数组大小是多少,需不需要扩容。对比于C语言的O(n)复杂度计算数组长度更快。

扩容策略:如果字符串大小<1MB, 每次扩容为2n+1大小;如果大于1MB,每次扩容1MB。

二、链表

链表结构用于存储list类型的键值(类似index),还有发布订阅等功能也用了链表结构。

链表节点:ListNode

链表:list

代码块  

typedef struct list{
	ListNode * tail;
	ListNode * head;
	unsigned long len;
	//节点值复制方法
	 void *(*dup) (void * ptr);
	//节点值释放方法
	 void *(*free) (void * ptr);
	//节点值对比方法
	int (*match)(void * ptr, void * key);
}

list+ListNode的链表结构

  三、字典

哈希表的结构:

字典的结构:

typedef struct dict{
	dictType *type;
  void *privdata;
  dictht *ht[2];
  int rehashIndx;	
}

ht[2]: 需要两个hashTable的原因是在进行rehash的操作时,需要使用另一个hashTable。

rehashIndx:在不进行rehash时值为-1,在渐进rehash过程中,这个值代表了rehash进行到的dictEntry的索引。

在hash时将会根据key取哈希&sizeMark来获得dictEnrty数组的下标索引,当数组中非空则将dictEntry元素插入到链表第一个位置。

随着链表的长度越来越长,对于字典的查询速度也会越慢,这时候就需要rehash。

rehash将会用到另一个空哈希表ht[1],将里面的table数组大小增加,再将原来的键值重新hash放入新的DictEntry中。rehash完毕后,把ht[1]变为ht[0], 再重新开辟一个空间作为ht[1]。

四、跳跃表

跳跃表用作有序集合键的底层实现以及在集群节点用作内部数据结构

后退指针:后退指针用于从表尾遍历节点。

object:保存的是一个指向对象的指针。

score分值:关乎节点的排序,如果分值相同则成员对象较大的排在后面。

zskiplist:虽然通过多个节点就可以组成跳跃表,但是使用zskiplist中的length、level字段就可以在O(1)复杂度返回跳跃表的长度以及层级。

五、整数集合

encoding:可支持存储INSET_ENC_INT16、INSET_ENC_INT32、INSET_ENC_INT64(int16_t、int32_t、int64_t)三种位数的整数。

content: 在这个数组中按照大小顺序存放整数,并且元素不会出现重复项。

集合升级:当集合需要插入一个比原有类型更大的整数时,需要先给数组的每个元素重新分配空间,首先先扩大数组空间到相应的大小,再将原来位置上的整数从后往前重新进行类型转换放到相应的索引上。每次升级都需要对底层元素进行转型并移动,时间复杂度为O(N)。升级使得这个集合更为节省内存,并且可以使得使用者不必关注c语言底层创建数组时指定类型位数不足而导致的插入异常问题。

整数集合不支持降级。

六、压缩列表

压缩列表是列表建和哈希键底层实现之一。一个列表键只包含少量列表项,并且每个列表项要么就是整数值,要么就是长度比较短的字符串,Redis就会使用压缩列表来做列表键的底层实现。

zlbytes:记录整个压缩列表占用的内存字节数,对压缩列表进行内存重分配、计算zlend位置时使用。

zltail:记录压缩列表表尾节点距离压缩列表起始地址有多少字节;通过这个偏移量,程序无序遍历整个压缩列表就可以确定表尾节点地址。

zzllen:压缩列表节点数量;当这个值等于UINT16_MAX时,节点的真实数量需要遍历整个压缩列表才能计算得出。

entryX:列表节点,压缩列表包含的各个节点,节点长度由节点保存的内容决定

​zlend:特殊值0xFF记录标记压缩列表的末端。

压缩列表节点

previous_entry_length:记录前一个压缩列表节点的长度,可通过这个属性减去指针起始地址往前回溯节点,该属性的长度为1字节或5字节,当前一节长度小于254字节,则前一节长度使用这个字段直接保存,如果前一节长度>=254字节,则前一字节设置为0xFE,之后四个字节用十进制保存长度。

encoding:记录了节点content属性保存的数据类型及长度。

content:保存节点值,可以是字节数组或者整数("hello world"、10086)

连锁更新机制:由于在进行节点插入时,一旦节点长度>=254字节,则修改后续节点的previos_entry_length属性,从1字节扩至5字节,可能再次引起后续节点的连锁修改。

就需要对压缩列表的执行空间重新分配,对每个节点进行重新分配需要的复杂度为O(N),则最坏需要进行N次分配,则连锁更新最坏复杂度为O(N2)。

到此这篇关于浅谈一下Redis的数据结构的文章就介绍到这了,更多相关Redis的数据结构内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈Redis的keys命令到底有多慢

    浅谈Redis的keys命令到底有多慢

    本文主要介绍了浅谈Redis的keys命令到底有多慢,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Redis分布式锁实例分析讲解

    Redis分布式锁实例分析讲解

    分布式锁是控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性
    2022-12-12
  • Redis migrate数据迁移工具的使用教程

    Redis migrate数据迁移工具的使用教程

    这篇文章主要给大家介绍了关于Redis migrate数据迁移工具的使用教程,文中通过示例代码介绍的非常详细,对大家的学习或者使用Redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • Django使用redis配置缓存的方法

    Django使用redis配置缓存的方法

    Redis是一个内存数据库由于其性能极高,因此经常作为中间件、缓存使用,缓存某些内容是为了保存昂贵计算的结果,这样就不必在下次执行计算,接下来通过本文给大家分享redis配置缓存的方法,感兴趣的朋友一起看看吧
    2021-06-06
  • 解决redis启动的警告日志问题

    解决redis启动的警告日志问题

    这篇文章主要介绍了解决redis启动的警告日志问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • redis通过位图法记录在线用户的状态详解

    redis通过位图法记录在线用户的状态详解

    这篇文章主要给大家介绍了关于redis如何通过位图法记录在线用户的状态的相关资料,文中先对位图进行了一个简单的介绍,而后通过示例代码将实现的方法介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • k8s部署redis集群搭建过程示例详解

    k8s部署redis集群搭建过程示例详解

    这篇文章主要为大家介绍了k8s部署redis集群搭建过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Redis数据库安全详解

    Redis数据库安全详解

    这篇文章主要为大家介绍了Redis数据库安全详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 基于Redis的限流器的实现(示例讲解)

    基于Redis的限流器的实现(示例讲解)

    下面小编就为大家分享一篇基于Redis的限流器的实现(示例讲解),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • Redis 缓存击穿问题及解决方案

    Redis 缓存击穿问题及解决方案

    缓存击穿是指在高并发环境下,大量请求同时访问缓存中不存在的数据,导致这些请求穿透到数据库,本文主要介绍了Redis缓存击穿问题及解决方案
    2023-12-12

最新评论