redis基本类型对象编码

本文详细解读了字符串、列表、哈希和集合对象在Redis中的不同编码方式,包括int、embstr、raw、ziplist、linkedlist、hashtable和intset等,并介绍了编码策略的变化及其适用场景。

字符串对象

对象编码方式有三种:
int: 当值为小的整数值,使用long类型存储
embstr:值为简短的字节数组(同样也是SDS,仅调用一次内存分配函数,分配的连续空间,空间中包含redisObject和sdshdr)
raw:底层采用SDS字符串存储(调用两次内存分配函数,分配给redisObject和sdshdr)

编码变更:
在这里插入图片描述
在这里插入图片描述

列表对象

对象编码方式有三种:
ziplist:列表中所有字符串元素的长度小于64;元素的数量小于512个,使用ziplist
linkedlist:当ziplist中两个条件有一个不满足时,就会转换为linkedlist。

local:0>rpush blah "hello" "word" "again"
"3"

local:0>object encoding blah
"ziplist"

local:0>rpush blah "wwwwwwwwwwwwwwwwwwwwwmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmlocal:0>"
"5"

local:0>object encoding blah
"linkedlist"

哈希对象

编码方式有两种:
ziplist:压缩列表,当哈希对象保存的所有键值对的字符串的长度都小于64字节;键值对的数量小于512个。
hashtable:哈希表编码,当不满足上述条件之一,就会转换为hashtable存储。

local:0>hset studeng name "wang"
"1"

local:0>object encoding studeng
"ziplist"
# 键值对的值的长度大于了64字节,转换为hashtable
local:0>hset studeng desc "dfijfdoiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiilocal:0>fsooooooooooooooooooooooooooooooooooooooooo"
"1"

local:0>object encoding studeng
"hashtable"

集合对象

集合对象的编码有两种:
intset:整数集合,所有 元素都是整数值;元素数量不超过512个;满足两个条件的话,集合对象将采用整数集合编码存储(两个条件的上限值都可以修改)。
hashtable:哈希表,不满足上述条件,将使用hashtable存储。

local:0>sadd number 1 3 5 76
"4"

local:0>object encoding number
"intset"

local:0>sadd number 'aaa'
"1"

local:0>object encoding number
"hashtable"

有序集合对象

有序集合编码:
ziplist:压缩列表,每个集合元素使用两个紧挨在一起的压缩节点保存,第一个节点为元素的成员,第二个元素为元素的分值。需要满足:元素数量小于128个,元素成员的长度小于64字节
skiplist:跳跃表,按照分值从小到大保存集合元素,zset通常使用字典和跳跃表一起使用,字典负责在O(1)时间内,查看到元素和分数的映射,跳跃表可以进行范围查询。

local:0>eval "for i=1, 128 do redis.call('zadd',KEYS[1], i,i) end" 1 numbers
"null"
local:0>object encoding numbers
"ziplist"
local:0>zadd numbers 3.14 pi
"1"
local:0>object encoding numbers
"skiplist"
local:0>zcard numbers
"129"
### Redis基本数据类型的底层实现原理 Redis 是一种高性能的键值存储系统,其底层实现依赖于多种数据结构和编码方式,这些设计使得 Redis 在内存使用效率和数据操作性能之间取得了良好的平衡。以下是 Redis 基本数据类型的底层实现详解: #### 1. **String 类型** String 是 Redis 最基础的数据类型,其实现基于两种编码方式:`int` 和 `embstr`/`raw`。 - 当字符串值可以表示为整数时,Redis 使用 `int` 编码来存储该值[^3]。 - 对于较小的字符串(通常小于 44 字节),Redis 使用 `embstr` 编码,这是一种优化后的编码方式,将字符串对象和值合并为一个连续的内存块,减少了内存分配次数[^2]。 - 对于较大的字符串或动态变化的字符串,Redis 使用 `raw` 编码,允许字符串值动态扩展。 ```c // 示例:Redis 中 String 的实现 struct redisObject { unsigned type:4; // 数据类型标识 unsigned encoding:4; // 编码方式 void *ptr; // 指向实际数据的指针 }; ``` #### 2. **List 类型** List 类型Redis 中通过双端链表(`linked list`)或压缩列表(`ziplist`)实现。 - 当列表元素较少且每个元素较小时,Redis 使用 `ziplist` 编码以节省内存。 - 当列表元素较多或元素较大时,Redis 转而使用 `linkedlist` 编码,其中每个节点包含一个指向下一个节点的指针[^3]。 ```python # 示例:操作 Redis List 类型 db.ListLeftPush("mylist", "world") # 插入到列表左侧 db.ListRightPush("mylist", "!") # 插入到列表右侧 ``` #### 3. **Hash 类型** Hash 类型用于存储键值对集合,其底层实现基于哈希表(`hashtable`)或压缩列表(`ziplist`)。 - 当 Hash 中的字段和值较少时,Redis 使用 `ziplist` 编码以减少内存开销[^2]。 - 当字段和值增多时,Redis 切换到 `hashtable` 编码,提供更高效的查找和插入性能[^3]。 #### 4. **Set 类型** Set 类型用于存储无序且唯一的元素集合,其底层实现基于整数集合(`intset`)或哈希表(`hashtable`)。 - 如果 Set 中的所有元素都是整数且数量较少,Redis 使用 `intset` 编码,这是一种紧凑的整数集合实现[^2]。 - 如果 Set 包含非整数元素或元素数量较多,Redis 使用 `hashtable` 编码[^3]。 #### 5. **Sorted Set 类型** Sorted Set 是一种有序集合,其底层实现基于跳跃表(`skiplist`)和字典(`dict`)。 - 跳跃表用于按分值排序的快速范围查询。 - 字典用于快速查找特定成员的分值[^2]。 ```c // 示例:Redis 中 Sorted Set 的实现 typedef struct zset { dict *dict; // 用于快速查找成员 zskiplist *zsl; // 用于按分值排序的跳跃表 } zset; ``` ### 总结 Redis基本数据类型通过灵活选择不同的编码方式,在内存占用和性能之间实现了良好的权衡。理解这些底层实现有助于开发者更好地优化 Redis 的使用场景[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值