zoukankan      html  css  js  c++  java
  • 【Redis】内部数据结构自顶向下梳理

     

     

    本博客将顺着自顶向下的思路梳理一下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的所有对象体系都是挂在一个Dict字典下的。这也体现了Redis非关系型的特点。

    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)

    对象系统与各种底层数据结构映射关系如下:

  • 相关阅读:
    VS2015 出现 .NETSystem.Runtime.Remoting.RemotingException: TCP 错误
    C#学习笔记------参数
    C#简单工厂和抽象类的实例
    css基础1
    html中的div span和frameset框架标签
    关于C#委托的一些学习笔记
    html基础加强2
    HTML基础加强
    利用GDI+在Winfrom绘制验证码
    winfrom如何在listview中添加控件
  • 原文地址:https://www.cnblogs.com/wjxzs/p/14239488.html
Copyright © 2011-2022 走看看