redis五种数据结构特点

redis五种数据结构特点

  • redis-string
    • 介绍
    • SDS内部存储数据结构
    • 三种编码方式
    • 特点总结
  • redis-list
    • 介绍
    • quicklist
    • 特点总结
  • redis-hash
    • 特点总结
  • redis-set
    • 介绍
  • 特点总结
  • redis-zset
    • 介绍
    • 特点总结

redis使用五种数据结构,分别是string(字符串),list(列表),hash(哈希表),set(集合),zset(有序列表)。
下面介绍他们的一些特点

redis-string

介绍

string是redis中最基础的数据结构,就是KV键值对中V值的类型是字符串。

SDS内部存储数据结构

redis没有使用char数组来存储字符串,而是使用SDS(simple dynamic string)来存储字符串。SDS是一种数据结构,定义为:

struct sdshdr {
    //记录buf数组中已使用字节的数量
    //等于sds所保存字符串的长度
    int len;
    
    //记录buf数组中未使用字节的数量
    int free;
    
    //字节数组,用于保存字符串
    char buf[];
}

free属性表示这个SDS未使用的空间;
len属性表示这个SDS保存了一个len字节长的字符串;
buf属性是一个char类型的数组,它是一个柔性数组,前面的字节保存了字符串,最后一个字节则保存了空字符’\0’。(保留这种设计是为了让SDS可以直接重用一部分C字符串函数库里面的函数)

相比于c字符串,SDS的优势:

  1. SDS获取字符串长度的时间复杂度是O(1),c字符串是O(n);
  2. SDS在字符串长度增减时自动处理分配空间,杜绝内存溢出的操作;相比c字符串,减少了内存重分配的次数;
  3. SDS是二进制安全的。C字符串中的字符必须符合某种编码(比如ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾,这些限制使得C字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。而SDS不会出现因为特殊字符导致字符串被截断的问题,SDS的API都是二进制安全的(binary-safe),所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据。

三种编码方式

redis为了更好的节省空间,采用不同方式的存储。

  • 当保存的是 Long 类型整数时,RedisObject 中的指针就直接赋值为整数数据了,这样就不用额外的指针再指向整数了,节省了指针的空间开销。
  • 当保存的是字符串数据,并且字符串小于等于 44 字节时,RedisObject 中的元数据、指针和 SDS 是一块连续的内存区域,这样就可以避免内存碎片。这种布局方式也被称为 embstr 编码方式。
  • 当保存的是字符串数据,并且字符串大于 44 字节时,SDS 的数据量就开始变多了,Redis 就不再把 SDS 和 RedisObject 布局在一起了,而是会给 SDS 分配独立的空间,并用指针指向 SDS 结构。这种布局方式被称为 raw 编码模式。

特点总结

  • 采用SDS数据结构进行存储,相比c字符串效率更高,更安全
  • 当字符串是long类型整数时,直接采用int格式存储;
  • 当字符串是<=44字节的字符串,采用embstr格式存储;
  • 当字符串是>44字节的字符串,采用raw格式存储;

redis-list

介绍

list在redis中代表一种可以双向插入,删除的链表。

quicklist

quicklist是redis中list使用的数据结构,它是由双向链表和ziplist组成的。
其主体是一个双向链表,链表中的每一个元素是一个ziplist,每当ziplist超过list-max-ziplist-size大小的时候(默认8字节),就会新建一个ziplist。
这样设计的好处是即保留了链表头尾插入,删除元素的高效,也使得中间元素的查询变得更加高效。

特点总结

  • 采用quicklist进行存储

redis-hash

特点总结

  • redis中的hash使用ziplist和hashtable作为存储数据结构
  • 使用ziplist的条件:
    – key < 64 bytes
    – value < 64 bytes
    – 元素个数 < 521
    – 否则就会使用hashtable
  • redis中的hashtable是使用dictht实现的 redis五种数据结构特点_第1张图片
    其中,table 结构是一个 dictEntry 类型的数组,而 dictEntry 是一个单向链表中的节点,代表的是 hashtable 中的一条记录,包含了该条记录的 key、value 以及指向下一个节点(下一条记录)的指针(hash 碰撞)。
    dictEntry 中的 key 和 val 都是 void 类型,意味着可以存储任意数据类型。所以,即使 Redis 中一些数据类型本身的底层实现也是 hashtable(set、zset、hash 等),但仍然可以存储在 redisDb 中的 dict 中。
    dictht 中的 size 表示 hashtable 中 bucket 的数量,sizemask 是 size 的位掩码,用于计算对应的 key 应该存储在哪个 bucket 当中(位运算的效率高于取模运算)。而 used 则用来存储当前 hashtable 中实际存储的记录(元素)的数量。

redis-set

介绍

set在redis中代表无序集合,其中元素的key值不可以重复出现。

特点总结

  • set存储结构是两种:intset和hashtable
  • intset使用条件:
    – V值类型是数字
    – 元素个数 < 512
    – 否则使用hashtable来存储

redis-zset

介绍

zset在redis中代表有序集合,其中元素key值不可以重复出现,按照给定的score排序

特点总结

  • zset使用ziplist和skiplist作为存储结构
  • 使用ziplist的条件:
    – 元素个数 < 128
    – key < 64 bytes
    – value < 64bytes
    – 否则使用skiplist

你可能感兴趣的:(redis,数据结构,java)