《Redis 设计与实现》- 第 1 章:数据结构与实现

169 阅读2分钟

@(Redis 笔记)[Redis, 数据库]

Redis 对象

  1. Redis 中使用对象表示数据库中的键和值,每创建一个键值对,至少创建 2 个对象。

  2. 对象的 type 属性记录了对象的类型,有 5 种:

    类型常量 对象
    REDIS_STRING 字符串对象
    REDIS_LIST 列表对象
    REDIS_HASH 哈希对象
    REDIS_SET 集合对象
    REDIS_ZSET 有序集合对象
  3. 编码与底层实现:对象的 ptr 指针指向对象的底层实现数据结构,数据结构由对象的 encoding 属性决定。 encoding 属性记录了对象所使用的编码,即该对象是用什么类型的数据结构决定的。

    类型常量 编码 对象
    REDIS_STRING REDIS_ENCODING_INT 整数值实现的字符串对象
    REDIS_STRING REDIS_ENCODING_EMBSTR 使用 embstr 编码的简单动态字符串实现的字符串对象
    REDIS_STRING REDIS_ENCODING_RAW 简单动态字符串实现的 字符串对象
    -- -- --
    REDIS_LIST REDIS_ENCODING_ZIPLIST 使用压缩列表实现的列表对象
    REDIS_LIST REDIS_ENCODING_LINKEDLIST 使用双端链表列表对象
    -- -- --
    REDIS_HASH REDIS_ENCODING_ZIPLIST 使用压缩列表实现的哈希对象
    REDIS_HASH REDIS_ENCODING_HT 使用字典实现的哈希对象
    -- -- --
    REDIS_SET REDIS_ENCODING_INTSET 使用整数实现的集合对象
    REDIS_SET REDIS_ENCODING_HT 使用字典实现的集合对象
    -- -- --
    REDIS_ZSET REDIS_ENCODING_ZIPLIST 使用压缩列表实现的有序集合对象
    REDIS_ZSET REDIS_ENCODING_SKIPLIST 使用跳跃表实现的有序集合对象

简单动态字符串 SDS

  • Redis 中没有采用 C 字符串,而是自己构建了 SDS
  • C 字符串应用在一些字符串常量值,不需要修改
  1. sds.h/sdshdr 结构表示一个 SDS:
// 总长度为 len + free + 1, 1 用于存储 /0
struct sdshdr {
	// 1. sds 中已使用的字节
	int len;
	// 2. sds 中空闲的字节
	int free;
	// 3. 字符串
	char buf[];
}
  1. SDSC string 区别:
  • SDS 获取字符串长度的时间为 O(1)
  • SDS 记录字符串长度,可以防止缓冲区溢出
  • 减少修改字符串时,导致的内存重分配次数:C 字符串增加元素而数组大小不够时,需要先扩展数组大小,否则会产生内存溢出。在删除元素时,若忘记释放内存,则会导致内存溢出。SDS 通过 lenfree ,解除了字符串长度与底层数组长度之间的关系。可以 实现空间预分配惰性空间释放 两种优化策略。
  • 空间与分配:扩展 SDS 时,会同时分配修改所需要的空间和额外未使用的空间。进行修改之后, SDSlen 将变成 13 字节, 那么程序也会分配 13 字节的未使用空间。
  • 惰性空间释放:缩短 SDS 时,不会直接回收内存,而是用 free 来收集空闲区域。
  • 二进制安全C字符串只能保存文本数据,会忽略 \0 以后的内容。
  • 兼容部分 C 字符串函数