| 副标题[/!--empirenews.page--] 面试中,redis也是很受面试官亲睐的一部分。我向在这里讲的是redis的底层数据结构,而不是你理解的五大数据结构。你有没有想过redis底层是怎样的数据结构呢,他们和我们java中的HashMap、List、等使用的数据结构有什么区别呢。 1. 字符串处理(string) 我们都知道redis是用C语言写,但是C语言处理字符串和数组的成本是很高的,下面我分别说几个例子。 没有数据结构支撑的几个问题 
     极其容易造成缓冲区溢出问题,比如用strcat(),在用这个函数之前必须要先给目标变量分配足够的空间,否则就会溢出。 如果要获取字符串的长度,没有数据结构的支撑,可能就需要遍历,它的复杂度是O(N) 内存重分配。C字符串的每次变更(曾长或缩短)都会对数组作内存重分配。同样,如果是缩短,没有处理好多余的空间,也会造成内存泄漏。 好了,Redis自己构建了一种名叫Simple dynamic string(SDS)的数据结构,他分别对这几个问题作了处理。我们先来看看它的结构源码: struct sdshdr{       //记录buf数组中已使用字节的数量       //等于 SDS 保存字符串的长度       int len;       //记录 buf 数组中未使用字节的数量       int free;       //字节数组,用于保存字符串       char buf[];  } 
 再来说说它的优点: 
     开发者不用担心字符串变更造成的内存溢出问题。 常数时间复杂度获取字符串长度len字段。 空间预分配free字段,会默认留够一定的空间防止多次重分配内存。 更多了解:https://redis.io/topics/internals-sds 这就是string的底层实现,更是redis对所有字符串数据的处理方式(SDS会被嵌套到别的数据结构里使用)。 2. 链表 Redis的链表在双向链表上扩展了头、尾节点、元素数等属性。 
 2.1 源码 ListNode节点数据结构: 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的链表有这几个特点: 
     可以直接获得头、尾节点。 常数时间复杂度得到链表长度。 是双向链表。 3. 字典(Hash) Redis的Hash,就是在数组+链表的基础上,进行了一些rehash优化等。 
 3.1 数据结构源码 哈希表: typedef struct dictht {      // 哈希表数组      dictEntry **table;      // 哈希表大小      unsigned long size;      // 哈希表大小掩码,用于计算索引值      // 总是等于 size - 1      unsigned long sizemask;      // 该哈希表已有节点的数量      unsigned long used;  } dictht; 
 (编辑:鹰潭站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |