Redis简单了解一

本文深入解析Redis中的数据结构,包括简单动态字符串、链表、字典与哈希表、跳跃表、整数集合、压缩列表等,以及这些数据结构如何支持Redis的字符串、列表、哈希、集合和有序集合等数据类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis

简单来说就是,一个键值对类型的单线程内存数据库。

支持String、List、Set、Sorted Set、hashes数据类型。这些都在官网文档有说明

 

数据结构

简单动态字符串sds

 

简单动态字符串(Simple Dynamic String),redis是用C语言写的,但它的简单动态字符串却比C语言的字符串优秀。数据结构如图:

free:分配了但未使用的内存字节长度
len:已经使用的内存字节长度。不含 '\0'

C语言的字符串结构如图:

1. 获取字符串长度复杂的从从 O(N) 变成 O(1)
2. 在操作字符串时可以避免缓冲区溢出
3. 减少了修改字符串引起的内存重分配次数
4. 二进制安全:C语言字符串不能存某些特殊字符串,而简单动态字符串可以

内存策略:

空间预分配:修改时如果需要扩展,分配空间也分配未使用空间。free = min(len + 1MB)。总长度= len + 1byte + free.
惰性空间释放:缩短字符串时,不立即释放空间,而是用free记录数量

 

链表linkedlist

链表是一种常用的数据结构,不过C语言没有内置。实现也简单。

维护表头、表尾指针,表长度及操作表的函数。

 

字典与哈希表dict

字典由两个哈希表组成,其中一个正常情况下是空的,也增加了自己的属性。

内存策略:扩展与收缩,

渐进式rehash

1. 为 ht[1] 分配空间
2. 修改 rehashidx 为0,表示开始 rehash
3. 依次把ht[0] 里的所有键值对 rehash到 ht[1],每rehash 一个,rehashidx 加1
4. 期间 删除、查找、更新在两个哈希表上进行,添加元素则在新哈希表上进行。则最后旧表一定为空
5. 交互 ht[1] ht[0],同时 把 rehashidx 置为0

 

跳跃表skiplist

简单来说,跳跃表是链表的一种变形。在链表的基础上添加层level的概念。

待续

 

整数集合intset

从名字可知,用来存储整数的

contents 数组类型取决于encoding,而encoding取值有:INTSET_ENC_INT16、INTSET_ENC_INT32、INTSET_ENC_INT64,分别代表int16_t、int32_t、int64_t 类型的值。

升级:当新加元素的类型比现有所有元素的类型都长时,先升级整数集合类型,然后添加元素到数组开头或者末尾。
注意:因为新元素引起了升级,因此它肯定比所有元素大(为正数),放末尾;或者比所有元素小(为负数),放开头。

使用升级策略目的:提升整数集合的灵活性,再就是节约内存。
另外,整数集合不支持降级。

 

压缩列表ziplist

压缩列表是redis为了节约内存而开发的,由一系列特殊编码的连续内存块组成的顺序数据结构。包含任何多个节点 entry,每个节点保存一个字节数组或者一个整数值。

注意:跟其他数据结构不同,它不是结构体。严格来说它不是数据结构,只是有组织的数据存储方式而已。

连锁更新:previous_entry_lenght 记录了前一个节点长度,用1或则会5个字节。增加或者删除前一个节点时,当前节点记录的长度发生变化,因此需要扩展空间。依次需要把后边连续的内存空间移动。复杂度O(N).
 

redis对象

所谓redis对象,就是一个结构体对象,让 void *ptr 指向它所使用的上述介绍的各种结构存储。

 

用它包装之前说的数据结构构成redis支持的数据类型:

比如ptr指向简单动态字符串,构成字符串对象:

 

再比如哈希对象:

每种数据类型都有两种数据结构实现,字符串类型有三种。至于redis底层选择哪种,自行了解。这里简单列举下数据类型和结构组合

对象

对应type

可用编码

 

字符串

REDIS_STRING

OBJ_ENCODING_INT 

利用整数值实现的字符串

OBJ_ENCODING_EMBSTR

利用embstr编码的sds实现的字符串对象

OBJ_ENCODING_RAW 

利用简单动态字符串实现的字符串

列表

REDIS_LIST

OBJ_ENCODING_ZIPLIST 

使用压缩列表实现列表对象

OBJ_ENCODING_LINKEDLIST

使用双端列表实现列表对象

哈希对象

REDIS_HASH 

OBJ_ENCODING_ZIPLIST 

使用压缩列表实现哈希对象

OBJ_ENCODING_HT 

集合

REDIS_SET

OBJ_ENCODING_INTSET

使用整数集合实现集合对象

OBJ_ENCODING_HT

使用字典实现集合对象

有序集合

REDIS_ZSET 

OBJ_ENCODING_ZIPLIST

使用压缩列表实现有序集合对象

OBJ_ENCODING_SKIPLIST

使用跳跃表和字典实现有序集合对象

 

 

数据库

redis 服务器就是一个内存数据库。所有数据都保存在redisServer 结构中,其中又分键空间与过期空间两个字典:

服务器上可以有多个数据库,一般我们操作的是db[0],如果需要切换数据库,执行 SELECT x; x是数据库序号

对于每个数据库,都有键空间与过期空间。顾名思义

键空间存储键值对。

过期空间存储过期时间数据,但两个空间是共用键的。

 

客户端

所有客户端都存在list *clients 中,是一个列表。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值