vb6实现union数据结构_Redis底层数据结构

本文探讨了vb6中实现union数据结构,并深入解析了Redis底层数据结构SDS的特点,包括常量时间获取长度、防止缓冲区溢出、减少内存再分配、二进制安全性以及链表结构的优化特性,如双端、无环和带长度计数器的设计。
Redis本身是一个基于C语言开发的内存数据库,它包含String、Set、List、Hash、Set、ZSet等数据类型。那么它底层的数据结构是什么样的呢?简单而言,redis的数据结构包含简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表等。简单动态字符串Redis没有直接用C语言的字符串,而是自己构建了一种名为【简单动态字符串】(Simple Dynamic String, SDS)的抽象类型,并将SDS作为Redis的默认字符串类型表示。
struct sdshdr{     //记录buf数组中已使用字节的数量     //等于 SDS 保存字符串的长度     int len;     //记录 buf 数组中未使用字节的数量     int free;     //字节数组,用于保存字符串     char buf[];}
0b12e9b8c8725c5fe1a9c3f5357ddcf3.png这样做的好处是:
  • 常量复杂度获取字符串长度,直接读取len属性,而不需要通过遍历计数
  • 杜绝缓冲区溢出。C语言在strcat函数进行拼接时,如果没有分配足够长度的内存空间,就会造成缓冲区溢出。而对于SDS数据类型,在进行字符修改时,会首先根据len属性检查内存空间是否满足需求,如果不满足,会进行空间扩展。
  • 减少修改字符串的内存重新分配次数。C语言不记录字符串的长度,如果要修改字符串,必须要重新分配内存。SDS通过len和free属性的存在,对于修改字符串SDS实现了空间预分配和惰性空间释放2种策略:
      (1)空间预分配:对字符串进行空间扩展时,扩展的内存比实际需要的多,可以减少分配次数      (2)惰性空间释放,对字符串进行缩短操作时,程序不立即使用内存重新分配来回收缩短后多余的字节,而是使用free属性将这些字节的数量记下来,等待后续使用。
  • 二进制安全。SDS的API都是以二进制的方式来处理buf中的元素,并且SDS不是以空字符串来判断是否结束,而是以len属性表示的长度来判断字符串是否结束。
  • 兼容部分C字符串函数。
6200fbd90ca6ec8bbc78dac9b6bacf79.png链表Redis构建了链表的实现。
typedef  struct listNode{       //前置节点       struct listNode *prev;       //后置节点       struct listNode *next;       //节点的值       void *value;  }listNode
typedef struct list{     //表头节点     listNode *head;     //表尾节点     listNode *tail;     //链表所包含的节点数量     unsigned long len;     //节点值复制函数     void (*free) (void *ptr);     //节点值释放函数     void (*free) (void *ptr);     //节点值对比函数     int (*match) (void *ptr,void *key);}list;
Redis链表特性
  • 双端:具有前置节点和后置节点的引用
  • 无环:表头节点的prev指针和表尾的next指针都指向NULL,对链表的访问都是以NULL结束
  • 带链表长度计数器:通过len属性获取链表长度
  • 多态:链表节点使用void * 指针来保存节点值,可以保存不同类型的值
字典
typedef struct dictht{     //哈希表数组     dictEntry **table;     //哈希表大小     unsigned long size;     //哈希表大小掩码,用于计算索引值     //总是等于 size-1     unsigned long sizemask;     //该哈希表已有节点的数量     unsigned long used;}dictht
哈希表是由数组table组成,table中的每个元素都是指向entry结构
typedef struct dictEntry{     //键     void *key;     //值     union{          void *val;          uint64_tu64;          int64_ts64;     }v;     //指向下一个哈希表节点,形成链表     struct dictEntry *next;}dictEntry
基本上与JAVA和HashMap一致。跳跃表Redis中跳跃表节点定义如下:
typedef struct zskiplistNode {     //层     struct zskiplistLevel{           //前进指针           struct zskiplistNode *forward;           //跨度           unsigned int span;     }level[];     //后退指针     struct zskiplistNode *backward;     //分值     double score;     //成员对象     robj *obj;} zskiplistNode
typedef struct zskiplist{     //表头节点和表尾节点     structz skiplistNode *header, *tail;     //表中节点的数量     unsigned long length;     //表中层数最大的节点的层数     int level;}zskiplist;
更多详情见文章《Redis跳跃表》整数集合整数集合是Redis用于保存整数值的集合抽象数据类型。压缩列表压缩列表是Redis为节省内存而开发的顺序型数据结构,通常作为列表键和哈希键的底层实现之一。总结大多数情况下,Redis使用简单字符串SDS作为字符串的表示,相对于C语言字符串,SDS具有常数复杂度获取字符串长度,杜绝了缓存区的溢出,减少了修改字符串长度时所需的内存重分配次数,以及二进制安全能存储各种类型的文件,并且还兼容部分C函数。通过为链表设置不同类型的特定函数,Redis链表可以保存各种不同类型的值,除了用作列表键,还在发布与订阅、慢查询、监视器等方面发挥作用(后面会介绍)。Redis的字典底层使用哈希表实现,每个字典通常有两个哈希表,一个平时使用,另一个用于rehash时使用,使用链地址法解决哈希冲突。跳跃表通常是有序集合的底层实现之一,表中的节点按照分值大小进行排序。整数集合是集合键的底层实现之一,底层由数组构成,升级特性能尽可能的节省内存。压缩列表是Redis为节省内存而开发的顺序型数据结构,通常作为列表键和哈希键的底层实现之一。参考链接:https://www.cnblogs.com/ysocean/p/9080942.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值