Redis的数据结构

Redis的五种数据结构

  1. String 字符串类型
  2. List 列表类型
  3. Set 无序集合类型
  4. ZSet 有序集合类型
  5. Hash 哈希表类型

每种数据结构对应的底层实现:

首先,在Redis中有一个核心对象——redisObject,用来表示所有key和value。redisObject结构体用来表示五种数据类型,结构如下:

typedef struct redisObject {
    // 类型
    unsigned type:4;
    // 对齐位
    unsigned notused:2;
    // 编码方式
    unsigned encoding:4;
    // LRU 时间(相对于 server.lruclock)
    unsigned lru:22;
    // 引用计数
    int refcount;
    // 指向对象的值
    void *ptr;
} robj;

编码方式有如下几种:

REDIS_ENCODING_RAW// 简单动态字符串
REDIS_ENCODING_EMBSTR// 使用embstr编码的简单动态字符串
REDIS_ENCODING_INT// 整数
REDIS_ENCODING_HT// 哈希表
REDIS_ENCODING_ZIPMAP// zipmap
REDIS_ENCODING_LINKEDLIST// 双端链表
REDIS_ENCODING_ZIPLIST// 压缩列表
REDIS_ENCODING_INTSET// 整数集合
REDIS_ENCODING_SKIPLIST// 跳跃表

五种数据结构底层实现是结合多种编码方式实现的:

  1. String类型根据输入的值,如果是整数,采用整数编码,否则判断该字符串是否长度大于32字节,大于则采用简单动态字符串编码(即row)小于等于则采用embstr编码;
  2. Hash类型采用两种编码实现ziplist、hashtable,hashtable计算key值下标方式是先根据hash函数计算出hash值,再用hash值和sizemask属性进行位与操作得到下标,出现冲突,则采用链地址法解决。随着hash表中键值对的增加和减少,这里会有一个rehash的问题,redis为了不影响正常服务,采用的是渐进式rehash方法,主要是借助两个hashtable对象来实现的;ziplist是一组连续的内存构成的数据结构,可以节省空间,压缩列表并没有采用压缩算法把数据进行压缩,而是它表示一组连续的内存空间的使用,从而节省空间,压缩列表使用多个节点存储数据;
  3. List类型采用ziplist和linkedlist实现,redis3.2版本后引入quicklist,linkedlist是一个双向链表,每个节点都有指向前一个和后一个节点的指针,头结点的前一个指向null,尾节点的下一个指向null,所以无环,redis链表有长度信息,获取长度时间复杂度为O(1),其他特性都与普通链表一致;
  4. Set类型采用ht(哈希表)和intset(整数集合)实现,顾名思义,如果写入set集合的元素都是整数,则会采用intset数据结构,否则采用ht数据结构,intset数据结构包含三个属性值:encoding、length、contens[],分别表示编码方式、整数集合的长度、元素内容。encoding有三种:int16_t、int32_t、int64_t,一开始默认采用int16_t编码,在整数集合新增元素时,若超出原集合的长度或者新增的元素大小超过当前编码,则会对集合进行升级,首先扩展底层数组大小(如果需要),数组类型为新元素类型,然后将原数组中的元素转换为新元素类型,并放到新的数组对应的位置,整数集合升级后不会再降级,编码也保持升级后的状态;如果新增的元素不再是整数,则会改成采用哈希表的方式存储;
  5. ZSet类型采用ziplist和skiplist实现,因为要求有序,所以不再使用哈希表,skiplist是一种有序的数据结构,同时查询效率高,当数据量越大时,查询效率越高,和平衡树查询效率差不多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值