• 技术文章 > mysql教程

    Redis压缩列表的详细介绍(示例讲解)

    不言 不言 2019-02-12 13:34:34 转载 103
    本篇文章给大家带来的内容是关于Redis压缩列表的详细介绍(示例讲解),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

    此篇文章是主要介绍Redis在数据存储方面的其中一种方式,压缩列表。

    本文会介绍

    1、压缩列表(ziplist)的使用场景

    2.如何达到节约内存的效果?

    3.压缩列表的存储格式

    4. 连锁更新的问题

    5. conf文件配置。

    在实践上的操作主要是对conf配置文件进行配置,具体上没有确切的一个值,更多是经验值。也有的项目会直接使用原本的默认值。此篇对于更好地理解一个数据库底层的存储逻辑会有一点帮助。修学储能,既要博,也要渊。希望这篇文章对同样也是在学习Redis的各位同伴有点用。(推荐教程:Redis教程

    一、压缩列表(ziplist)的使用场景:

    Redis为了优化数据存储,节约内存,在列表、字典(哈希键)和有序集合的底层实现了使用压缩列表这一优化方案。

    例如,假如一个哈希键里面存储的字符串比较短,那么Redis就会将它用压缩列表的格式去存储,即转换为字节数组存储。而一个哈希键内部存储的整数值比较小,同样也会把它存储为压缩列表的一个节点。同理,列表键的对小数据的存储跟哈希键的操作类似。

    如此说来,压缩列表并不是开发者可以直接调用的Redis中的一种存储数据结构,而是Redis中为优化数据存储而在底层做的一项努力。理解好这点还是比较重要的。

    二、如何达到节约内存的效果?

    压缩列表是一种序列化的数据结构,这种数据结构的功能是将一系列数据与其编码信息存储在一块连续的内存区域,这块内存物理上是连续的。但逻辑上被分为多个组成部分,即节点。目的是为了在一定可控的时间复杂度条件下尽可能的减少不必要的内存开销,从而达到节省内存的效果。需要理解是怎么达到节约内存作用的,还需要去了解压缩列表的存储格式。

    三、压缩列表的存储格式:

    压缩列表(ziplist)是Redis列表键、哈希键和有序集合键的底层实现之一,其实质是一种序列化的数据存储结构。有别于普通情况下,Redis用双端链表表示列表,使用散列表表示哈希键,用散列表+跳跃表表示有序集合。当一个列表或者哈希字典/有序集合只包含很少内容,并且每一个列表项或者哈希项/有序集合项如果是小整数,或者比较短的字符串。那么Redis就会用压缩列表来做底层的实现。

    压缩列表由一系列经Redis特殊编码的连续内存块组成,每一个内存块称为一个节点(entry),而一个压缩列表可以包含很多个节点。每个节点存储的数据格式可以是字节数组(中文字符串等都会转换为字节数组)或者整数值。

    字节数组的长度可以是以下的其中一种:

    1. 长度小于等于63字节(2的6次方)

    2. 长度小于等于16383字节(2的14次方)

    3. 长度小于等于4294967295字节(2的32次方)

    整数值可能是以下六种中的其中一种:

    1. 4位长,介于0-12之间的无符号整数

    2. 1字节长的有符号整数

    3. 3字节长的有符号整数

    4. int16_t类型整数

    5. int32_类型整数

    6. int64_t类型整数

    普通存储格式下和压缩列表存储格式下的不同点:

    列表存储结构典型的为双端链表,每一个值都是用一个节点来表示,每个节点都会有指向前一个节点和后一个节点的指针,以及指向节点包含的字符串值的指针。而字符串值又分为3个部分存储,第一部分存储字符串长度,第二部分存储字符串值中剩余可用的字节量,第三部分存储的则是字符串数据本身。所以一个节点往往都需要存储3个指针、2个记录字符串信息的整数、字符串本省和一个额外的字节。总体上额外的开销是很大的(21字节)。

    压缩列表节点的格式:

    每一个节点都有previous_entry_length,encoding,content三个部分组成,在遍历压缩列表的时候是从后往前遍历的。

    1. previous_entry_length记录了前一个节点的长度,只要用当前指针减去这个值就可以达到前一个节点的起始地址。

    2. encoding记录了节点content属性所保存数据的类型和长度

    3. content记录了一个节点的值

    显然压缩列表这种方式节约了不少存储空间。但同时也会引发下面的问题。

    四、连锁更新的问题:

    一般而言如果前一个节点的整体长度小于254字节,previous_entry_length属性只需要1个字节的空间来保存这个长度值。而当前一个节点大于254字节的时候,previous_entry_length属性要用5个字节长的空间来记录长度值。

    当长度为254字节