第六章----Redis数据类型底层实现

2020-03-20  本文已影响0人  枫子夜

Redis的数据库就是使用字典(哈希表)来作为底层实现的,对数据库的增删改查都是构建在字典(哈希表)的操作之上的。

typedef struct redisDb { 
    int id;         // 数据库ID标识
    dict *dict;     // 键空间,存放着所有的键值对              
    dict *expires;  // 过期哈希表,保存着键的过期时间                          
    dict *watched_keys; // 被watch命令监控的key和相应client    
    long long avg_ttl;  // 数据库内所有键的平均TTL(生存时间)     
} redisDb;
DB数据结构

每次在Redis中创建数据时都会生成两个对象:键对象、值对象。Redis对象用redisObject结构表示,其中类型、编码和指针记录了Redis五个数据类型和六个底层数据结构的关系。

typedef struct redisObject{
     //类型
     unsigned type:4;
     //编码
     unsigned encoding:4;
     //指向底层数据结构的指针
     void *ptr;
     //引用计数
     int refcount;
     //记录最后一次被程序访问的时间
     unsigned lru:22;
}robj
数据类型与数据结构

1. string对象

struct sdshdr{
     //记录buf数组中已使用字节的数量
     //等于 SDS 保存字符串的长度
     int len;
     //记录 buf 数组中未使用字节的数量
     int free;
     //字节数组,用于保存字符串
     char buf[];
}
raw字符串 embstr字符串

2. list对象

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;

链表具有前置节点和后置节点的引用,表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,通过 len 属性获取链表长度,链表节点使用 void* 指针来保存节点值,可以保存各种不同类型的值。

压缩列表组成 列表节点组成 ziplist linkedlist

3. hash对象

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

# hash表节点
typedef struct dictEntry{
     //键
     void *key;
     //值
     union{
          void *val;
          uint64_tu64;
          int64_ts64;
     }v;
 
     //指向下一个哈希表节点,形成链表
     struct dictEntry *next;
}dictEntry

# 字典
typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;
ziplist hashtable

4. set对象

typedef struct intset{
     //编码方式
     uint32_t encoding;
     //集合包含的元素数量
     uint32_t length;
     //保存元素的数组
     int8_t contents[];
 
}intset;
intset hashtable

5. zset对象

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;
跳跃表 ziplist
typedef struct zset{
     //跳跃表
     zskiplist *zsl;
     //字典
     dict *dice;
} zset;

6. 内存回收和共享

API

定期删除+惰性删除

定期删除: redis默认是每隔 100ms 就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。

惰性删除 : 当去查询已经过期的key时,Redis才会对其删除。

内存共享

7. 降低内存占用的几种方式

降低内存占用有助于减少创建快照和加载快照的时间、提升载入AOF文件和重新文件的效率、缩短主从同步所需的时间等!


春暖花开 应该走出去看看这片春色

上一篇 下一篇

猜你喜欢

热点阅读