数小钱钱的种花兔

数小钱钱的种花兔

本博客将顺着自顶向下的思路梳理一下Redis的数据结构体系,从数据库到对象体系,再到底层数据结构。我将基于我的一个项目的代码来进行介绍:daredis。该项目中,使用Java实现了Redis中所有的数据结构,思想与Redis大致类似,各种变量的命名与Redis源码基本一致,只是将结构体换成了类来实现。

Redis数据库

Redis服务器在初始化时,会创建一个db数组,大小默认是16,即创建16个数据库。如下所示:

public class RedisServer {

    private static int dbNum = 16;
    public static RedisDB[] db;

    public static void init(){
        db = new RedisDB[dbNum];
    }

    public static void initDB(int index){
        db[index] = new RedisDB();
    }
}

实际上,每个客户端都会拥有一个目标数据库,默认情况下为db[0]。客户端执行命令时,目标数据库会成为其操作对象。

RedisDB类型包含一个字典,代码如下:

public class RedisDB {

    //数据库的键空间
    Dict<SDS, RedisObject> dict;

    public RedisDB() {
        this.dict = new Dict<>();
    }
}

数据库RedisDB实际上包含一个Dict类型,即字典(Redis中尤为关键的底层数据结构),是一个键值对集合,键名是SDS字符串,键值是RedisObject。Dict是后面要讲的一种底层数据结构,在数据库体系中也是用到了Dict。

Redis对象系统

继续向下探索,看一看数据库键值RedisObject是什么。RedisObject表示Redis中的对象。Redis包含五种对象,统称对象系统

  • RedisHash哈希对象
  • RedisList列表对象
  • RedisSet集合对象
  • RedisString字符串对象
  • RedisZSet有序集合对象

RedisObject包含一个类型字段type和一个编码字段encoding,以及一个底层数据结构的引用ptr。如下所示:

public abstract class RedisObject {
    protected int type;
    protected int encoding;
    protected RedisObj ptr;
}

type的值由一个枚举类型来维护,表示上述五种类型中的某种类型,如下所示

public enum RedisType {
    STRING(0),
    LIST(1),
    HASH(2),
    SET(3),
    ZSET(4);
    private final int val;
    RedisType(int VAL) {
        this.val = VAL;
    }
    public int VAL(){
        return val;
    }
}

encoding同样由一个枚举类型来维护,表示ptr指向的数据结构的类型,如下所示

public enum RedisEnc {
    RAW(0),
    INT(1),
    HT(2),
    LINKEDLIST(3),
    ZIPLIST(4),
    INTSET(5),
    SKIPLIST(6),
    EMBSTR(7);
    private final int val;
    RedisEnc(int VAL) {
        this.val = VAL;
    }
    public int VAL(){
        return val;
    }
}

RedisObject中的ptr引用的对象可以是多种类型。例如列表对象可由压缩列表ziplist或者双端链表linkedlist来编码。两种编码可以转换,当满足以下两个条件时,使用ziplist编码

  • 列表对象保存的所有字符串元素长度都小于64字节;
  • 列表对象保存的元素数量小于512个;

两个条件有一项不满足,会将压缩列表转化为双端链表。
其它Redis对象的数据结构编码切换方式也与之类似。

Redis底层数据结构

底层数据结构指的是ptr指向的对象的内部结构,在Redis中,包含6种底层数据结构:

  • SDS动态字符串
  • ziplist压缩列表
  • list链表
  • dict字典
  • skiplist跳跃表
  • intset整数集合

熟悉Redis的同学来说,这些都是耳熟能详的数据结构,就不一一去介绍源码了,项目daredis中都有具体实现。
之前写过一篇介绍跳跃表的博客,也可以看看:
【Redis】跳跃表原理分析与基本代码实现(java)

对象系统与各种底层数据结构映射关系如下:
【Redis】内部数据结构自顶向下梳理-LMLPHP

01-01 01:54