Redis----五种常见数据类型

前言:Redis底层常见数据结构

String

String类型,底层基于SDS实现,具有三种编码方式 RAW EMBSTR INT 不同的情况采用不同的编码方式。

RAW,当存储的SDS大于44字节,采用RAW编码,先申请RedisObject的内存空间,再申请SDS的内存空间,多次内存申请操作,内存空间不连续,RedisObject占用一块内存空间,指针指向的SDS占据另一块内存,不连续。

EMBSTR,当SDS存储的内存空间小于等于44字节(此时RedisObject刚好不大于64 字节) 采用EMBSTR编码方式,该编码方式会直接申请一块连续的内存空间存储,RedisObject与SDS 因为Redis底层申请内存时都是申请2的n次方的大小,此时占用的内存空间不大于64字节,可以轻易申请到一片连续的内存空间减少内存申请次数,且不易产生内存碎片,减少花在申请内存上的额外性能开销

INT,若存储的字符串是整数数值且大小在范围内,由于整数数值可以直接用二进制位表示,那么RedisObject中原本用来指向SDS的指针,可以直接用来存储数值数据,不再需要SDS的部分

List

可双端访问,内存占用低,可存储较大的数据量,底层采用QuickList

内存占用低: QuickList双端链表,每个节点都是ZipList(每个entry占用内存不固定需要多少占用多少,不存在空间浪费) 且QuickList可以压缩ZipList,首尾访问需求大中间访问需求低,可以对中间的ZipList压缩,进一步节省内存空间

可存储较大的数据量: 数据分片思想,虽然单个ZipList存储的数据量有限(ZipList申请 的都是连续的内存空间 数据量大时难以申请到大片连续内存空间) 将数据分片存储在多个ZipList中,再通过QuickList双端链表将多个ZipList联系起来

Set

无序元素唯一,查询效率高,支持并交集,底层由Dict或Inset实现

当存储的所有数据都是整数,且元素数量不超过限制时会采用InSet编码节省内存,Inset底层查询元素时采用二分查找,当元素过多时查询效率会降低,元素越多效率比Hash结构越低

正常采用Dict hash结构 具备查询效率高的优点。

ZSet

同时具备键值存储,元素唯一,可排序的需求,底层采用SKipList与Dict联合实现

ZSet内部维护了两个指针,一个指向SKipList一个指向Dict,排序以及范围查询时利用SKipList,根据分数查询元素值时利用Dict,内存占用大,同一数据保存两份,牺牲内存空间换取较强的功能性。

问题: 当元素数量不多时Dict与SkipList优势不明显,且内存消耗大,数据量大时才能体现出Dict与SkipList的优势;当数据量不大,元素数量与每个元素占用内存空间都不超过限制时,直接采用ZipList 存储节省内存,ZipList如何同时满足排序与键值查找的需求?

虽然ZipList原生不支持排序与键值保存的功能,但由于ZipList的内存空间是连续的,每两个连在一起的entry作为一个key-value(ele-score)即可,且score越小离队首越近升序排列。

Hash

Hash与ZSet非常类似,Hash只有键值存储的需求,无排序需求,底层采用Dict或ZipList实现即可。

数据量小时采用ZipList存储数据,两两一组模拟键值存储,数据量小遍历查找性能也不会很低;元素数量与某个元素大小超出限制时转变编码方式为Dict。

你可能感兴趣的:(《码破苍穹の八股文修炼手册》,redis,数据库,缓存)