Redis--数据结构详解

先来介绍一下redis,redis是一款内存高速缓存数据库,非关系型数据库,非关系型怎么理解呢,像mysql,oracle这都是关系型数据库,数据之间是存在某种关系的,而非关系型数据库存储的就是非结构化的海量数据,无法体现数据的关系。

redis的数据结构

redis不同于memcache的一点就是redis支持丰富的数据结构,而memcache只有string,下面我i们详细介绍一下,redis的五种数据结构,string,hash,list,set,zset。

string(字符串)

string是redis最基本的类型,也是非关系型数据库最基本的类型,结构就是 key-value
string是二进制安全的,意思就是他可以存储jpg图片和序列化的对象,最大能储存512MB

typedef char *sds;

struct sdshdr {

        int len;// 记录 buf 数组中已使用字节的数量  等于 SDS 所保存字符串的长度

        int free;// 记录 buf 数组中未使用字节的数量

        char buf[];// 字节数组,用于保存字符串

};

虽说redis使用c语言写的,但是却不是c中的string类型,他是自己构建了一种名为简单动态字符串的抽象类型,我们可以观察他的源码实现,他的结构体中由三个部分,加入我们使用他保存一个“redis”,结构就是这样的:
在这里插入图片描述
len就是长度,buf数组用来保存字符串的每个元素,free记录了数组中未使用的字节容量

hash(字典)

hash就是一个键值对集合或者一个关联数组,是一个string类型的field和value的映射表,适合储存对象,每个key都是唯一的。
redis的字典使用哈希表作为底层实现,定义如下

typedef struct dictht{
     //哈希表数组
     dictEntry **table;
     //哈希表大小
     unsigned long size;
     //哈希表大小掩码,用于计算索引值
     //总是等于 size-1
     unsigned long sizemask;
     //该哈希表已有节点的数量
     unsigned long used;

}dictht
 哈希表是由数组 table 组成,table 中每个元素都是指向 dict.h/dictEntry 结构,dictEntry 结构定义如下:

typedef struct dictEntry{
     //键
     void *key;
     //值
     union{
          void *val;
          uint64_tu64;
          int64_ts64;
     }v;

     //指向下一个哈希表节点,形成链表
     struct dictEntry *next;
}dictEntry

key是用来保存键值,val用来保存值,值可以是指针,也可以是uint64_t整数,也可以是int64_t整数,还有一个指向下一个哈希节点的指针,是为了解决哈希冲突,解决方法有两种,一种是开放地址法,另一种就是拉链法,这里曹勇的就是后者,所以需要一个指向下一节点的指针
在这里插入图片描述

List(列表/双向链表)

list的实现其实就是一个双向链表,所以他支持左右插入即弹出,所以list一般用来做消息队列,看一下他的底层实现:


typedef struct listNode {

    struct listNode *prev;  //指向前一个节点

    struct listNode *next; //指向后一个节点

void *value;//值

} listNode;//节点



typedef struct list {

    listNode *head;//双向链表的头节点

listNode *tail;//双向链表的尾节点

    void *(*dup)(void *ptr);//复制

    void (*free)(void *ptr);//释放

    int (*match)(void *ptr, void *key);//匹配

unsigned long len;//链表长度

} list;//双向链表/列表



typedef struct listIter {

    listNode *next;//指向列表的某个节点

int direction;//迭代方向

} listIter;//访问链表的迭代器


总结一下list的特点:
1 双端:具有前置节点和后置节点的引用,可以直接获取
2 无环,前后都指向的null
3 带链表长度计数器,通过len属性获取链表的长度,时间复杂度为O(1)
4多态:链表节点使用void*作为指针保存节点值,可以保存各种不同的类型的节点的值

set(集合)

底层实现就是哈希,所以他是无序的,它相当于一个集合,所以他是不重复的,redis还提供了为集合求交集,并集,差集的操作,就可以实现共同好友,推荐好友等功能

zset(有序集合)

和set一样都是string类型元素的集合,且不允许有重复的元素,不同的就是每个元素都关联一个double类型的分数,redis就是通过这个分数来为集合中的元素进行排序


typedef struct zskiplistNode {

    robj *obj; // 成员对象

    double score;// 分值

    struct zskiplistNode *backward; // 后退指针

    struct zskiplistLevel {

        struct zskiplistNode *forward; // 前进指针

        unsigned int span;// 跨度

    } level[]; // 层

} zskiplistNode;//有序集合的节点



typedef struct zskiplist {

    struct zskiplistNode *header, *tail;  // 表头节点和表尾节点

    unsigned long length;// 表中节点的数量

    int level;// 表中层数最大的节点的层数

} zskiplist;//有序集合


zset的底层其实是一个跳跃表结构

在这里插入图片描述
先简单介绍到这里,下一篇我会详细介绍一下hash和zset中的一些详细的知识点

猜你喜欢

转载自blog.csdn.net/LYue123/article/details/88777183