Redis每种类型使用的数据结构

String

string类型使用的数据结构有三种:int,raw,embstr
当保存的是数字类型的时候,底层存的是int类型。
如图:
image.png
当保存的是一个字符串,并且字符串大于32字节的时候,底层存的是raw类型。
如图:
image.png
当保存的是一个字符串,并且字符串小于等于32字节的时候,底层存的是embstr类型。
image.png

embstr和raw的区别

embstr只需要分配一次内存空间,因为redis对于embstr类型的,会分配一个连续的内存空间,而对于raw类型,则会需要分配两次内存(redisObject和sdshdr分别申请)空间。
embstr格式的全部数据都在一串连续的空间中,所以使用这种格式的数据,更好的利用缓存带来的优势。
image.png

编码的转换

任何append操作,都会使得其他的类型转换成raw类型。
因为embstr格式,redis并没有给它有任何修改的api,所以本质上,embstr是只读的,所以append操作,会直接把其转成raw格式。
image.png
image.png

List

List类型使用的数据结构有两种:ziplist,linkedlist

当列表对象可以同时满足以下两个条件时,列表对象使用ziplist编码:
列表对象保存的所有字符串元素的长度都小于64字节;
列表对象保存的元素数量小于512个;
不能满足这两个条件的列表对象需要使用linkedlist编码。
以上两个条件的上限值是可以修改的,具体请看配置文件中关于list-max-ziplist-value选项和list-max-ziplist-entries选项的说明。

Hash

hash类型使用的数据结构有两种:ziplist和hashtable
image.png

使用ziplist的情况,ziplist里面存的数据如下所示:
image.png
每次hash新增key的时候,key和value按顺序push到list的末尾。

编码使用情况适用

当满足所有以下情况时,hash使用ziplist:

  1. hash保存的key和value的大小都小于64字节
  2. hash里面key的数量小于512个。

使用情况分析

案例1:hash使用的是ziplist(100个key)
在实际使用过程中,hash的数据结构有时候很重要。比如说有一个hash结构,存的key是uid,value是时间戳。
使用hmget这个指令,获取用户的信息。比如说传入的用户有一万个,hash里面存了100个,那么hmget需要遍历是10000*100次。如果是十万个用户,那这个遍历次数更多了。因为ziplist结构,每次查询,都可能遍历100次(大部分uid不存在)。
而如果使用的是hashtable的话,遍历次数就少了100(元素数量)次。
解决方案:如果key的数量较少使用的是ziplist,不使用hmget,而是一次性获取全部的值,在本地构建map去运算。

Set

set使用的数据结构有以下两种:intset和hashtable
首先介绍一下intset的结构。

typedef struct intset{
    //编码方式
    uint32_t encoding;
    //集合包含的元素数量
    uint32_t length;
    //保存元素的数组
    int8_t contents[];
}intset;

如上代码,可以看出,intset是使用contents数组来保存元素的,contents数组是有序的,判断数字是否在可以通过二分查找进行。

set结构上的hashtable跟普通的hashtable的区别就是其value都是null。这跟java中的Set实现很像,在java中,HashSet的底层实现就是HashMap,只不过,value都是无意义的Object对象。
image.png

编码转换

当set同时满足以下条件的时候,set使用intset结构:

  1. set里面存储的元素都是int类型。
  2. set最大数量小于512个。

ZSET

zset使用的数据结构有以下两种:ziplist和skiplist
当使用skiplist结构是,zset实际上是使用dict和skiplist一起实现的。
因为其需要两者的特性,所以需要两者结合在一起使用。比如说,zrange 需要使用跳表的特性,才能快速range,而判断这个成员的分数等,则需要使用dict结构快速定位成员。

typedef struct zset 
{
    zskiplist *zsl;    
     dict *dict;
} zset;

编码转换

当有序集合对象可以同时满足以下两个条件时,对象使用ziplist编码:

  1. zset保存的元素数量小于128个;
  2. zset保存的所有元素成员的长度都小于64字节;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值