Redis 5.0数据结构之压缩列表ziplist源码详解(一)

【Redis系列3】Redis列表对象之linkedlist(双端列表)和ziplist(压缩列表)及quicklick(快速列表)实现原理分析 Redis列表对象之linkedlist和ziplist实现原理分析前言列表对象linkedlistlinkedlist存储结构ziplistziplist存储结构entry存储结构prevlenencodingentry-dataziplist数据示例ziplist连锁更新问题linkedlist和ziplist的选择quicklistquicklist内部存储结构quicklist的compress属性quicklistNode的zl指针quicklist对比原始两种列表的改进总结 前言 上一篇我们分析 阅读详情

由于篇幅过长,ziplist的源码分析分为两篇,本篇是第一篇,涉及到ziplist的数据结构、初始化创建、以及ziplist的特殊编码部分的源码分析。

第二篇博客地址:Redis 5.0数据结构之压缩列表ziplist源码详解(二)

概述

Redis基于C语言开发,由于C并未内置链表,因此Redis自己实现了一系列链表,有双端链表linkedlist、压缩列表ziplist、快速链表quicklist等,本篇将从源码角度展现压缩列表ziplist。

笔者相关文章推送:
Redis 5.0数据结构之双端链表linkedlist源码解析
Redis 链表list常用命令总结

Redis 中的list实现

众所周知Redis有五种数据类型,链表是其中的一种,在Redis在3.2版本,修改了list的底层实现,在Redis 3.2之前链表是由双端链表linkedlist和压缩链表ziplist共同实现的,Redis3.2版本之后主要实现优化为了快速链表quicklist。

Redis3.2之前,当同时满足以下两个条件时,列表键的底层实现为ziplist,其余情况均使用linkedlist

  • 哈希对象保存的所有键值的字符串长度小于64字节;
  • 哈希对象保存的键值对数量小于512个;

可见压缩列表主要是为了节约内存开发。

本篇使用源码版本均为Redis 5.0,其他版本也具有一定的参考价值,主要介绍的压缩列表ziplist源码均来自ziplist.h和ziplist.c两个文件。

压缩列表的构成

笔者认为ziplist是链表中十分特殊的存在。传统意义上或是说更广为人知的list链表实现,都是在节点构造中使用指针,然后直接使用该指针指向当前节点前后节点的地址,来实现链表。但ziplist并不是使用指针直接保存节点内存地址的方式实现,ziplist使用连续内存地址+偏移量的方式实现链表。

理解压缩列表及其源码的重点就在于要理解压缩列表的结构。压缩列表没有数据结构代码定义,压缩列表是一种通过内存特殊编码方式实现的数据结构

压缩列表相关宏定义函数

首先源码中提供了一些宏定义函数,用于获取ziplist相关信息,在下文的源码分析中各方法将频繁出现

/* ziplist结尾特殊标志位 默认0xFF 即255 */
#define ZIP_END 255

/* 返回压缩列表ziplist包含的总字节数 */
#define ZIPLIST_BYTES(zl)       (*((uint32_t*)(zl)))

/* 返回ziplist中最后一个节点的偏移量 */
#define ZIPLIST_TAIL_OFFSET(zl) (*((uint32_t*)((zl)+sizeof(uint32_t))))

/* 返回ziplist的总长度
 * 该属性值超过UINT16_MAX(65536)时,返回UINT16_MAX,表示真实长度需要遍历得出 */
#define ZIPLIST_LENGTH(zl)      (*((uint16_t*)((zl)+sizeof(uint32_t)*2)))

/* 返回ziplist的header长度(header总所需字节数) 总共10字节 header包括
 * 一个32位的属性用于表示ziplist的总字节数
 * 一个32位的属性用于表示起始地址到尾节点的偏移量
 * 一个16位的属性用于表示节点数,即ziplist长度 */ 
#define ZIPLIST_HEADER_SIZE     (sizeof(uint32_t)*2+sizeof(uint16_t))

/* 返回ziplist结尾标志的长度(结尾所需字节数) 总共1字节 */
#define ZIPLIST_END_SIZE        (sizeof(uint8_t))

/* 返回ziplist中指向第一个节点的指针 */
#define ZIPLIST_ENTRY_HEAD(zl)  ((zl)+ZIPLIST_HEADER_SIZE)

/* 返回ziplist中指向最后一个节点的指针 使用header中的的偏移量获取 */
#define ZIPLIST_ENTRY_TAIL(zl)  ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))

/* 返回指向ziplist结尾标识(0xFF)的指针 */
#define ZIPLIST_ENTRY_END(zl)   ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)

压缩列表创建函数

由于压缩列表基于内存特殊编码实现,源码种并没有数据结构代码定义,但可以通过上文的宏定义函数,结合压缩列表的创建函数来推出压缩列表的大致组成部分。压缩列表创建函数如下:

/* Create a new empty ziplist. */
unsigned char *ziplistNew(void) {
	// 为压缩列表申请bytes字节空间
    unsigned int bytes = ZIPLIST_HEADER_SIZE+ZIPLIST_END_SIZE;
    unsigned char *zl = zmalloc(bytes);
    // 默认小端模式存储 如果在使用大端存储的机器上运行 需要大小端转换 详见计组
    ZIPLIST_BYTES(zl) = intrev32ifbe(bytes);
    ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE);
    // 设置len属性为0 len表示ziplist中节点数量
    ZIPLIST_LENGTH(zl) = 0;
    // 设置ziplist结尾标志0xFF
    zl[bytes-1] = ZIP_END;
    return zl;
}

压缩列表组成部分

由源码可见压缩列表共有如下五个组成部分:

属 性类 型长 度用 途
zlbytesunit32_t4字节记录整个压缩列表占用的内存字节数,包括zlbytes的四字节:在对压缩列表进行内存重分配, 或者计算 zlend 的位置时使用。
zltailunit32_t4字节记录压缩列表表尾节点距离压缩列表的起始地址有多少字节: 通过这个偏移量,程序无须遍历整个压缩列表就可以确定表尾节点的地址。
zlenunit16_t2字节记录了压缩列表包含的节点数量: 当这个属性的值小于 UINT16_MAX (65535)时, 这个属性的值就是压缩列表包含节点的数量; 当这个值等于 UINT16_MAX 时, 节点的真实数量需要遍历整个压缩列表才能计算得出。
entryX列表节点不定压缩列表包含的各个节点,节点的长度由节点保存的内容决定。
zlendunit8_t1字节特殊值 0xFF (十进制 255 ),用于标记压缩列表的末端。

压缩列表组成示意图如下:
在这里插入图片描述

压缩列表节点的构成

压缩列表中有五个组成部分,其中最终要当属实际存储数据的zlentry节点,接下来将通过源码分析压缩列表节点的组成。

压缩列表节点结构定义

与压缩列表本身不同,节点具有明确的结构定义,压缩列表的节点在ziplist.c中定义如下:

typedef struct zlentry {
	// 用于记录内存编码后前一个entry的len占用了多少字节 即prevrawlen占用了多少字节
    unsigned int prevrawlensize; 
    // 用于记录前一个entry占用的长度 
    // 通过当前entry地址 - prevrawlen可以寻找到上一个entry的首地址
    unsigned int prevrawlen;     
    // 用于记录内存编码后当前entry的len占用了多少字节
    unsigned int lensize;        
    // 用于记录当前entry的长度
    unsigned int len;
    // 用于记录当前entry的header大小 即lensize + prevrawsize  
    unsigned int headersize;     
    // 用于记录当前节点编码格式
    unsigned char encoding;
    // 指向当前节点的指针      
    unsigned char *p;       
} zlentry;

prevrawlen的编码

zlentry中的prevrawlen长度并不是固定的,在prevrawlen的处理上使用了压缩编码,相关函数如下:

#define ZIP_BIG_PREVLEN 254

/* 对prevrawlen进行编码 或者直接返回编码len长度所需要的字节数 */
unsigned int zipStorePrevEntryLength(unsigned char *p, unsigned int len) {
	// 当传入p为NULL时 自然不需要编码 直接返回编码len长度所需要的字节数
    if (p == NULL) {
        return (len < ZIP_BIG_PREVLEN) ? 1 : sizeof(len)+1;
    } else {
    	// 如果len小于254 则直接使用一个字节保存
        if (len < ZIP_BIG_PREVLEN) {
            p[0] = len;
            return 1;
        // len大于等于254时调用函数处理
        } else {
            return zipStorePrevEntryLengthLarge(p,len);
        }
    }
}

int zipStorePrevEntryLengthLarge(unsigned char *p, unsigned int len) {
    if (p != NULL) {
    	// 首先首位固定设为254 表示节点长度一定大于等于254字节
        p[0] = ZIP_BIG_PREVLEN;
        // 随后开辟所需内存空间
        memcpy(p+1,&len,sizeof(len));
        // 大小端转换
        memrev32ifbe(p+1);
    }
    // p为NULL时直接返回编码len所需字节数
    return 1+sizeof(len);
}

从以上两个函数中可以发现,prevrawlen的编码有两种可能,即属性长度只可能是1字节或5字节

  • 当前一个节点长度小于254字节时,直接将前一节点存储在当前字节中
  • 当前一个节点长度大于等于254字节时,将prevrawlen的第一个字节设为254,后四个字节用于保存前一节点长度(因为unsigned int固定4字节)。

len与encoding编码

源码阅读到现在的部分,仍有一个重要的问题没用理清,就是zlentry能存放什么数据,这里先给出结论,zlentry被设置允许存放字符串和整数类型数据,由于压缩列表的主要目的是尽量节省空间,所以字符串和整数类型的数据有也自然有他的压缩(编码)方式。

字符串编码

#define ZIP_STR_MASK 0xc0
#define ZIP_INT_MASK 0x30

#define ZIP_IS_STR(enc) (((enc) & ZIP_STR_MASK) < ZIP_STR_MASK)

#define ZIP_STR_06B (0 << 6)
#define ZIP_STR_14B (1 << 6)
#define ZIP_STR_32B (2 << 6)

/* 与prevrawlen编码相同 p不为NULL时写入 为NULL时直接返回长度 */
unsigned int zipStoreEntryEncoding(unsigned char *p, unsigned char encoding, unsigned int rawlen) {
    unsigned char len = 1, buf[5];
	// 判断存放的是否是字符串
    if (ZIP_IS_STR(encoding)) {
    	// 长度 <= 0x3f 即63
        if (rawlen <= 0x3f) {
        	// 此处len不变 即只占位1字节
            if (!p) return len;
            // 该字节高位存放标识ZIP_STR_06B 0 << 6 即该字节高二位是00
            // 后6位实际存放长度 故表示能够存放63个字节
            buf[0] = ZIP_STR_06B | rawlen;
        // 长度 <= 0x3fff 即16383
        } else if (rawlen <= 0x3fff) {
        	// len扩大 占位2字节
            len += 1;
            if (!p) return len;
            // 首位字节高二位为ZIP_STR_14B 1 << 6 即高二位01
            // 其余14位实际存放长度 故表示能存放16383个字节
            buf[0] = ZIP_STR_14B | ((rawlen >> 8) & 0x3f);
            buf[1] = rawlen & 0xff;
        // 其余情况 实际上是 长度小于4294967295
        } else {
        	// len扩大 占位5字节
            len += 4;
            if (!p) return len;
            // 首位字节为ZIP_STR_32B 2 << 6 高二位固定10 该字节其余位不使用
            // 剩余四个字节用于存放长度 故表示能存放4294967295个字节
            buf[0] = ZIP_STR_32B;
            buf[1] = (rawlen >> 24) & 0xff;
            buf[2] = (rawlen >> 16) & 0xff;
            buf[3] = (rawlen >> 8) & 0xff;
            buf[4] = rawlen & 0xff;
        }
    } else {
        // 不是字符串 那么编码编码为整型 长度固定位1 见整数编码
        if (!p) return len;
        buf[0] = encoding;
    }

    // p中存放
    memcpy(p,buf,len);
    return len;
}

从字符串编码的函数中可以明显的发现,在存放字符串(字节数组)时,有三种可能的长度,下附字节数组编码表格,其中x表示实际存放长度的位,_表示弃用不适用的位。

编码编码长度实际存储的数据
00xxxxxx1字节长度小于等于63字节的字节数组
01xxxxxx xxxxxxxx2字节长度小于等于16383字节的字节数组
10_ _ _ _ _ _ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx5字节长度小于4294 967 295字节的字节数组

整数编码

// 观察可见整数编码的高二位固定11 0xc0 = 1100 0000
#define ZIP_INT_16B (0xc0 | 0<<4)
#define ZIP_INT_32B (0xc0 | 1<<4)
#define ZIP_INT_64B (0xc0 | 2<<4)
#define ZIP_INT_24B (0xc0 | 3<<4)
#define ZIP_INT_8B 0xfe

int zipTryEncoding(unsigned char *entry, unsigned int entrylen, long long *v, unsigned char *encoding) {
	// 存放实际数据
    long long value;

    if (entrylen >= 32 || entrylen == 0) return 0;
    if (string2ll((char*)entry,entrylen,&value)) {
        /* Great, the string can be encoded. Check what's the smallest
         * of our encoding types that can hold this value. */
		// 0~12的整数值特殊 直接保存在encoding字段中
        if (value >= 0 && value <= 12) {
            *encoding = ZIP_INT_IMM_MIN+value;
        // 其余情况直接根据整数值范围 为encoding对应编码
        } else if (value >= INT8_MIN && value <= INT8_MAX) {
            *encoding = ZIP_INT_8B;
        } else if (value >= INT16_MIN && value <= INT16_MAX) {
            *encoding = ZIP_INT_16B;
        } else if (value >= INT24_MIN && value <= INT24_MAX) {
            *encoding = ZIP_INT_24B;
        } else if (value >= INT32_MIN && value <= INT32_MAX) {
            *encoding = ZIP_INT_32B;
        } else {
            *encoding = ZIP_INT_64B;
        }
        *v = value;
        return 1;
    }
    return 0;
}

从整型编码函数中可见,在存放整数时,有六种可能的长度,附整数编码表格如下:

编码编码长度实际存储的数据
110000001字节int16_t类型的整数
110100001字节int32_t类型的整数
111000001字节int64_t类型的整数
111100001字节24位有符号整数
111111101字节8位有符好整数
1111xxxx1字节encoding的低四位直接保存一个0~12的整数

ziplist的添加元素、查找元素、删除元素以及连锁更新的实现源码分析见第二篇博客。

部分理论内容和图片参考/摘自:《Redis设计与实现》——黄健宏

Redis 压缩列表ziplist 解读 Redis 压缩列表ziplist 解读 1.redis为什么使用ziplist redis是一种基于内存的数据库,内存是一种稀缺资源,需要寻找高效的数据结构来减少内存的使用。 redis中存储小对象时,LISTs, HASHes, and ZSETs 采用了ziplist数据结构,当超过一定大小后,变为linkedlist数据结构 如上图 1. LIST元素个数比较少,而且每个元素的长... 阅读详情

相关推荐

【Redis】ziplist与listpack源码剖析:Redis数据存储的演进与优化

ziplist是一种紧凑的字节数组数据结构,适用于存储小型列表。zlbytes:总字节数(4字节)。zltail:到列表尾节点的偏移量(4字节)。zllen:节点数量(2字节)。entry:实际存储的节点。zlend:结束标记(1字节,值为 0xFF)。每个节点包括prevlen(前一个节点的长度)、encoding(编码方式)和entry-data(实际存储内容)。

白晨的博客 1945

Redis源码分析(四)—— ziplist的设计与实现

背景 ziplist是一种为节约内存而开发的数据结构,本质是一个字节数组。 ziplist是列表键和哈希键的底层实现之一,也用于quicklist的实现。 问题思考 双向链表结构,在存储数据本身长度远小于链表节点大小的场景下,有严重的内存浪费问题。针对这种情况,Redis设计了ziplist这种节约内存的数据结构。以下给出ziplist相关的思考问题,了解ziplist的实现原理和设计思路。 ziplist的数据结构 ziplist节点构成 为什么要设计ziplist ziplist相关操作 查找指定节

pcj_888的博客 2181

redis ziplist压缩列表的源码分析

ziplist是redis为了节约内存而开发的,由一系列特殊编码的连续内存块组成的顺序数据结构。一个 ziplist可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。

wade1991的专栏 1048

Redis 5.0数据结构之压缩列表ziplist源码详解(二)

前文已经提及了压缩列表ziplist的主要设计初衷是尽量节约空间,因此设计出了一系列的压缩编码,将ziplist设计成了内存地址连续,使用基地址+偏移量的方式来访问压缩列表内节点,并且说明了压缩列表节点结构具有的属性以及相应的作用,通过源码分析了对于节点内各属性的编码的实现细节。

MSSPLANET的博客 907

Redis源码解析-基础数据-ziplist(压缩列表)

太长不看版 压缩列表是一种为节约空间而实现的线性数据结构,本质是字节数组。 压缩列表元素可以为整数或字符串。 压缩列表在快速列表、列表对象和哈希对象中都有使用。 压缩列表添加(平均复杂度O(n))与删除节点(平均复杂度O(n)),可能会触发连锁更新(平均复杂度O(n^2)),因为触发机率不高所以不影响性能。 因为节点存在字符串,字符串匹配为O(n)复杂度,所以压缩列表查找节点平均复杂度为O(n...

Knight0xffff的博客 595

解决屏幕不亮难题:慷智SerDes DE信号极性配置避坑指南

本文深入探讨了基于慷智AIM95x系列SerDes芯片的嵌入式显示系统开发中,因DE信号极性配置不匹配导致屏幕不亮的典型故障。文章详细解析了DE信号的核心作用与极性定义,提供了慷智SerDes芯片中DE极性寄存器的具体配置方法与调试记录,并给出了从隔离问题、对比时序到波形验证的系统性排查流程,帮助工程师快速定位并解决此类隐蔽问题。

weixin_29185493的博客 138

深入源码分析Redis ZSet、ziplist、skiplist数据结构

深入Redis源码学习底层数据结构:ZSet、Ziplist、SkipList。本篇文章会从源码和数据结构图的方式,解析ziplist、skiplist两大数据结构的关键实现。

AllenChan_的博客 1527

【C++PTA】6-1 Point类的运算 (10 分)

定义Point类,有坐标x,y两个私有成员变量;对Point类重载“+”(相加)、“-”(相减)和“==”(相等)运算符,实现对坐标的改变,要求用友元函数和成员函数两种方法实现。对Point类重载<<运算符,以使得代码 Point p; cout<<p<<endl;可以输出该点对象的坐标。 函数接口定义: 实现Point类。 裁判测试程序样例: /* 请在这里填写答案 */ int main(int argc, char const *argv[]) { P

libertye的博客 2367

Redis源码学习(28),压缩列表学习,ziplist.c(一)

  经过我们的不懈努力终于把SDS和双端链表搞定之后,现在要进入压缩列表数据结构的学习,ziplist是列表、hash、有序集合的数据结构之一。   压缩列表听名字是经过压缩的一种列表,是用提高内存使用率的一种数据结构,下面我们就来看看它究竟是什么样的数据结构。 1 介绍 1.1 ziplist   虽然网上有很多关于Redis中ziplist介绍,不过我们最好还是阅读作者的说明更加准确点。 /* The ziplist is a specially encoded dually linked list t

无痕之意的博客 731

SAP传输请求全流程详解:从SE10创建到STMS跨环境部署(附常见错误排查)

本文详细解析了SAP传输请求的全流程,从SE10创建到STMS跨环境部署,并提供了常见错误排查方法。涵盖工作台请求、定制请求等类型,以及STMS传输原理和实战操作技巧,帮助用户高效管理SAP系统变更。

weixin_29214335的博客 142

低电压高效率能源管理芯片BQ25570的基本用法及应用电路实例

BQ25570是一款低电压、高效率、集成了可编程功率追踪(MPPT)功能、BOOST升压功能和BUCK降压功能的综合型能源管理电路。冷启动工作电压为330mV,热启动工作电压为100mV。主要应用于温差发电片TEG、压电、摩擦发电和太阳能板的能量收集,也可以用于人体可穿戴自取能传感设备的能量管理。本文主要介绍了BQ25570相关参数计算、MPPT功能验证、工作逻辑和应用场景,并设计了一版测试电路,给出了不同应用需求的电路配置建议。

weixin_49213602的博客 3450

Redis基础数据结构之 ziplist 压缩列表 源码解读

Ziplist在存储小数据集时非常高效,但由于其紧凑存储的特性,在进行插入、删除和更新操作时可能会涉及到内存的重新分配和复制。因此,Ziplist最适合用于内存敏感的应用场景,特别是当数据集较小且操作以读取为主时。对于大型数据集或频繁的写操作,Redis可能会选择其他更适合的数据结构。

无休居士的博客 1888

三相SVPWM逆变器双闭环PI解耦控制:从dq坐标系到参数整定实战

本文深入解析了三相SVPWM逆变器的双闭环PI解耦控制技术。通过引入dq坐标系,将交流量转换为直流量,并结合前馈补偿实现电流环的解耦控制。文章详细阐述了从数学模型推导、控制器设计到参数整定与SVPWM实现的完整流程,为工程师提供了从理论到实战的系统性指导。

weixin_28292761的博客 402

Redis - ziplist (压缩列表) 图文详解

List列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向List列表添加元素。最大长度为2^32-1,也即每个列表支持超过40亿个元素。Redis的List类型有多种实现方式,由双向链表或压缩列表(v7.0由listpack替代)实现的。这篇文章就是介绍其中一种实现ziplist-压缩列表。ziplist为了节省内存,采用了紧凑的连续存储。所以在修改操作下并不能像一般的链表那么容易,需要从新分配新的内存,然后复制到新的空间。httpshttps。............

一七令 1万+

Unreal Engine开发:多人联机与网络同步_延迟补偿与预测

通过延迟补偿和预测技术,我们可以显著减少网络延迟对多人在线动作游戏的影响,提升玩家的体验。延迟补偿主要在服务器端实现,通过回溯时间点来更准确地处理输入和事件。预测技术主要在客户端实现,通过预先计算玩家的动作结果来减少延迟感。结合这两种技术,可以实现更平滑、更公平的多人游戏体验。

chenlz2007的博客 1191

MobSF-v3源代码分析(一)

移动安全框架(MobSF)是一种自动化的移动应用程序(Android/iOS/Windows)测试框架,能够执行静态、动态和恶意软件分析。 它可用于Android、iOS和Windows移动应用程序的有效和快速安全分析,并支持二进制文件(APK,IPA和APPX)和压缩源代码。 MobSF可以在运行时为Android应用程序进行动态应用程序测试,并具有由CapFuzz(一种特定于Web API的安全扫描程序)提供支持的Web API模糊测试。MobSF旨在使您的CI/CD或DevSecOps管道集成无缝。

武天旭的博客 8959

[redis 源码走读] - 压缩列表(ziplist)

作者简介:大家好,我是哥,前中兴通讯、美团架构师,现某互联网公司联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!压缩列表ziplist是一个双向链表,设计主要是为了节省内存。保存字符串,数值两种类型( It stores both strings and integer values),列表内部实现主要是对一块连续内存进行管理,列表支持列表头尾的插入或弹出结点操作。

smart_an的专栏 1159

MATLAB与ROS联合仿真——实例程序搭建思路

MATLAB与ROS联合仿真——实例程序搭建思路

慕羽★的博客 5227

Redis基础数据结构之 quicklist 和 listpack 源码解读

Quicklist 是 Redis 3.2 引入的一种新的数据结构,旨在优化列表类型的存储。Quicklist 是一种链表结构,其中每个节点都是一个ziplist。这样做的目的是结合ziplist的优点(内存效率)和传统链表的优点(更好的插入和删除性能)。在Redis 7.0版本之前,quicklist是由双向链表和压缩列表构成的。然而,在Redis 7.0版本中,quicklist的底层实现由双向链表和压缩列表变为了由双向链表和listpack构成的结构。

无休居士的博客 3033

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Redis源码(3)ziplist压缩列表和quicklist快表

Redis的ziplist和quicklist源码分析

weixin_43823462的博客 1386

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Redis底层数据结构之ziplist(压缩列表)

ziplist是Redis中的某些数据类型底层所使用的数据结构 Redis中的hash,List,Sorted List这几种类型的数据在某些情况下会使用ziplist来存储。 Hash类型 当hash类型的数据满足以下条件时,底层使用ziplist存储。 当hash键值对个数小于等于 hash-max-ziplist-entries 配置的值,默认512 当键值对中值的长度小于等于 hash-max-ziplist-value 配置的值,默认64 当hash类型的数据同时满足以上两个条件时,会将val

Torry__的博客 4558

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

redis源码之压缩列表ziplist

未完待续… 压缩列表ziplist 1.简介 压缩列表是 Redis 为了节约内存而开发的, 由一系列特殊编码的连续内存块组成的顺序型(sequential)数据结构。 2.组成 属性 类型 长度 用途 zlbytes uint_32t 4B 记录整个压缩列表占用的内存字节数:在对压缩列表进行内存重分配, 或者计算 zlend的位置...

897901160 6641

Redis源码剖析和注释(六)--- 压缩列表(ziplist)

Redis 压缩列表(ziplist)1. 介绍压缩列表(ziplist)是哈希键的底层实现之一。它是经过特殊编码的双向链表,和整数集合(intset)一样,是为了提高内存的存储效率而设计的。当保存的对象是小整数值,或者是长度较短的字符串,那么redis就会使用压缩列表来作为哈希键的实现。127.0.0.1:6379> HMSET hash name mike age 28 sex male OK

men_wen的博客 8494

Redis源码剖析之压缩列表(ziplist)

本来打算只用一篇文章来讲解Redis中的list,在实际写作过程中发现Redis中有多种list的实现,所以准备拆成多篇文章,本文主要讲ziplist,ziplist也是quicklist的基础。另外还有skiplist,skiplist虽然是list,当主要和set命令相关,所以会放到后面。 本文主要涉及到的源码在ziplist.c 何为ziplist?我们可以在ziplist.c源码头部找到一段Redis作者的一段介绍。 The ziplist is a specially encoded duall

xindoo 3232

Redis数据结构之——ziplist

Redis数据结构之——ziplist

weixin_46935110的博客 2844

[redis 源码走读] 压缩列表(ziplist)

压缩列表 点赞作者:redis 源码,注释很多而且很详细。看压缩列表源码前,可以先看看 ziplist.c 文件顶部注释,基本可以了解该数据结构设计。 压缩列表ziplist是一个双向链表,设计主要是为了节省内存。保存字符串,数值两种类型( It stores both strings and integer values),列表内部实现主要是对一块连续内存进行管理,列表支持列表头尾的插入或弹出...

wenfh2020的专栏 327
上一篇: LeetCode 134. 加油站 II && 贪心算法
下一篇: Redis 5.0数据结构之压缩列表ziplist源码详解(二)
7rulyL1ar
博客等级 码龄7年 25粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

7rulyL1ar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值