您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    能够是目前最详细的Redis内存模型及运用解读(2)
    时间:2018-08-09 08:10 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    内存碎片的产生与对数据停止的操作、数据的特点等都有关;此外,与运用的内存分配器也有关系:假设内存分配器设计合理,可以尽能够的增加内存碎片的产生。前面将要说到的jemalloc便在控制内存碎片方面做的很好。

    假设Redis效劳器中的内存碎片曾经很大,可以经过安全重启的方式减小内存碎片:由于重启之后,Redis重新从备份文件中读取数据,在内存中停止重排,为每个数据重新选择适宜的内存单元,减小内存碎片。

    三、Redis数据存储的细节

    1、概述

    关于Redis数据存储的细节,触及到内存分配器(如jemalloc)、复杂静态字符串(SDS)、5种对象类型及外部编码、redisObject。在讲述详细内容之前,先阐明一下这几个概念之间的关系。

    下图是执行set hello world时,所触及到的数据模型。

    能够是目前最详细的Redis内存模型及运用解读

    图片来源:https://searchdatabase.techtarget.com.cn/7-20218/

    (1)dictEntry:Redis是Key-Value数据库,因此对每个键值对都会有一个dictEntry,外面存储了指向Key和Value的指针;next指向下一个dictEntry,与本Key-Value有关。

    (2)Key:图中右上角可见,Key(”hello”)并不是直接以字符串存储,而是存储在SDS结构中。

    (3)redisObject:Value(“world”)既不是直接以字符串存储,也不是像Key一样直接存储在SDS中,而是存储在redisObject中。实践上,不论Value是5种类型的哪一种,都是经过redisObject来存储的;而redisObject中的type字段指明了Value对象的类型,ptr字段则指向对象所在的地址。不过可以看出,字符串对象虽然经过了redisObject的包装,但依然需求经过SDS存储。

    实践上,redisObject除了type和ptr字段以外,还有其他字段图中没有给出,如用于指定对象外部编码的字段;前面会详细引见。

    (4)jemalloc:无论是DictEntry对象,还是redisObject、SDS对象,都需求内存分配器(如jemalloc)分配内存停止存储。以DictEntry对象为例,有3个指针组成,在64位机器下占24个字节,jemalloc会为它分配32字节大小的内存单元。

    下面来辨别引见jemalloc、redisObject、SDS、对象类型及外部编码。

    2、jemalloc

    Redis在编译时便会指定内存分配器;内存分配器可以是 libc 、jemalloc或许tcmalloc,默许是jemalloc。

    jemalloc作为Redis的默许内存分配器,在减小内存碎片方面做的相比照较好。jemalloc在64位系统中,将内存空间划分为小、大、庞大三个范围;每个范围内又划分了许多小的内存块单位;当Redis存储数据时,会选择大小最适宜的内存块停止存储。

    jemalloc划分的内存单元如下图所示:

    能够是目前最详细的Redis内存模型及运用解读

    图片来源:

    例如,假设需求存储大小为130字节的对象,jemalloc会将其放入160字节的内存单元中。

    3、redisObject

    前面说到,Redis对象有5种类型;无论是哪种类型,Redis都不会直接存储,而是经过redisObject对象停止存储。

    redisObject对象十分重要,Redis对象的类型、外部编码、内存回收、共享对象等功用,都需求redisObject支持,下面将经过redisObject的结构来阐明它是如何起作用的。

    redisObject的定义如下(不同版本的Redis能够稍稍有所不同):

    typedef struct redisObject { 

    unsigned type:4; 

    unsigned encoding:4; 

    unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */ 

    int refcount; 

    void *ptr; 

    } robj; 

    redisObject的每个字段的含义和作用如下:

    (1)type

    type字段表示对象的类型,占4个比特;目前包括REDIS_STRING(字符串)、REDIS_LIST (列表)、REDIS_HASH(哈希)、REDIS_SET(集合)、REDIS_ZSET(有序集合)。

    当我们执行type命令时,便是经过读取RedisObject的type字段取得对象的类型;如下图所示:

    能够是目前最详细的Redis内存模型及运用解读

    (2)encoding

    encoding表示对象的外部编码,占4个比特。

    关于Redis支持的每种类型,都有至少两种外部编码,例如关于字符串,有int、embstr、raw三种编码。经过encoding属性,Redis可以依据不同的运用场景来为对象设置不同的编码,大大提高了Redis的灵敏性和效率。以列表对象为例,有紧缩列表和双端链表两种编码方式;假设列表中的元素较少,Redis倾向于运用紧缩列表停止存储,由于紧缩列表占用内存更少,而且比双端链表可以更快载入;当列表对象元素较多时,紧缩列表就会转化为更适宜存储少量元素的双端链表。

    经过object encoding命令,可以查看对象采用的编码方式,如下图所示:

    能够是目前最详细的Redis内存模型及运用解读

    5种对象类型对应的编码方式以及运用条件,将在前面引见。

    (3)lru

    lru记载的是对象最后一次被命令顺序拜访的时间,占据的比特数不同的版本有所不同(如4.0版本占24比特,2.6版本占22比特)。

    经过比照lru时间与以后时间,可以计算某个对象的空转时间;object idletime命令可以显示该空转时间(单位是秒)。object idletime命令的一个特殊之处在于它不改动对象的lru值。

    (责任编辑:admin)