此外,由于SDS中的buf依然运用了C字符串(即以’\0’开头),因此SDS可以运用C字符串库中的部分函数;但是需求留意的是,只要当SDS用来存储文本数据时才可以这样运用,在存储二进制数据时则不行(’\0’不一定是开头)。
(3)SDS与C字符串的运用
Redis在存储对象时,一概运用SDS替代C字符串。例如set hello world命令,hello和world都是以SDS的方式存储的。而sadd myset member1 member2 member3命令,不论是键(”myset”),还是集合中的元素(”member1”、 ”member2”和”member3”),都是以SDS的方式存储。除了存储对象,SDS还用于存储各种缓冲区。
只要在字符串不会改动的状况下,如打印日志时,才会运用C字符串。
四、Redis的对象类型与外部编码
前面曾经说过,Redis支持5种对象类型,而每种结构都有至少两种编码;这样做的益处在于:一方面接口与完成别离,当需求添加或改动外部编码时,用户运用不受影响,另一方面可以依据不同的运用场景切换外部编码,提高效率。
Redis各种对象类型支持的外部编码如下图所示(图中版本是Redis3.0,Redis前面版本中又添加了外部编码,略过不提;本章所引见的外部编码都是基于3.0的):
关于Redis外部编码的转换,都契合以下规律:编码转换在Redis写入数据时完成,且转换进程不可逆,只能从小内存编码向大内存编码转换。
1、字符串
(1)概略
字符串是最基础的类型,由于一切的键都是字符串类型,且字符串之外的其他几种复杂类型的元素也是字符串。
字符串长度不能超过512MB。
(2)外部编码
字符串类型的外部编码有3种,它们的运用场景如下:
int:8个字节的长整型。字符串值是整型时,这个值运用long整型表示。
embstr:<=39字节的字符串。embstr与raw都运用redisObject和sds保存数据,区别在于,embstr的运用只分配一次内存空间(因此redisObject和sds是延续的),而raw需求分配两次内存空间(辨别为redisObject和sds分配空间)。因此与raw相比,embstr的益处在于创立时少分配一次空间,删除时少释放一次空间,以及对象的一切数据连在一同,寻觅方便。而embstr的坏处也很清楚,假设字符串的长度添加需求重新分配内存时,整个redisObject和sds都需求重新分配空间,因此redis中的embstr完成为只读。
raw:大于39个字节的字符串
示例如下图所示:
embstr和raw停止区分的长度,是39;是由于redisObject的长度是16字节,sds的长度是9+字符串长度;因此当字符串长度是39时,embstr的长度正好是16+9+39=64,jemalloc正好可以分配64字节的内存单元。
(3)编码转换
当int数据不再是整数,或大小超过了long的范围时,自动转化为raw。
而关于embstr,由于其完成是只读的,因此在对embstr对象停止修正时,都会先转化为raw再停止修正,因此,只需是修正embstr对象,修正后的对象一定是raw的,无论能否到达了39个字节。示例如下图所示:
2、列表
(1)概略
列表(list)用来存储多个有序的字符串,每个字符串称为元素;一个列表可以存储2^32-1个元素。Redis中的列表支持两端插入和弹出,并可以取得指定位置(或范围)的元素,可以充任数组、队列、栈等。
(2)外部编码
列表的外部编码可以是紧缩列表(ziplist)或双端链表(linkedlist)。
双端链表:由一个list结构和多个listNode结构组成;典型结构如下图所示:
经过图中可以看出,双端链表同时保存了表头指针和表尾指针,并且每个节点都有指向前和指向后的指针;链表中保存了列表的长度;dup、free和match为节点值设置类型特定函数,所以链表可以用于保存各种不同类型的值。而链表中每个节点指向的是type为字符串的redisObject。
紧缩列表:紧缩列表是Redis为了浪费内存而开发的,是由一系列特殊编码的延续内存块(而不是像双端链表一样每个节点是指针)组成的顺序型数据结构;详细结构相比照较复杂,略。与双端链表相比,紧缩列表可以节省内存空间,但是停止修正或增删操作时,复杂度较高;因此当节点数量较少时,可以运用紧缩列表;但是节点数量多时,还是运用双端链表划算。
紧缩列表不只用于完成列表,也用于完成哈希、有序列表;运用十分普遍。
(3)编码转换
只要同时满足下面两个条件时,才会运用紧缩列表:
列表中元素数量小于512个;
列表中一切字符串对象都不足64字节。
假设有一个条件不满足,则运用双端列表;且编码只能够由紧缩列表转化为双端链表,反方向则不能够。
下图展现了列表编码转换的特点:
(责任编辑:admin)