Redis五种数据结构的底层实现

本文深入探讨Redis从3.0版本开始引入的EMBSTR编码方式,详细解释了其如何将字符串与redisObject对象在同一内存块中分配,以及为何字符串长度限制在39(在3.2版本后为44)。分析了此编码方式的优势,包括减少内存分配次数、提高效率和降低内存碎片率。

embstr编码的动态字符串:

  • 从Redis 3.0版本开始字符串引入了EMBSTR编码方式,长度小于OBJ_ENCODING_EMBSTR_SIZE_LIMIT(39)的字符串将以EMBSTR方式存储
  • EMBSTR方式的意思是 embedded string ,字符串的空间将会和redisObject对象的空间一起分配,两者在同一个内存块中
  • Redis中内存分配使用的是 jemalloc,jemalloc 分配内存的时候是按照 8、16、32、64 作为 chunk 的单位进行分配的。
  • 为了保证采用这种编码方式的字符串能被 jemalloc 分配在同一个 chunk 中,该字符串长度不能超过64

  • 故字符串长度限制 OBJ_ENCODING_EMBSTR_SIZE_LIMIT = 64 - sizeof('0') - sizeof(robj) 为16 - sizeof(struct sdshdr)为8 = 39

    • 注意在Redis 3.2之后,就不是以39为分界线,而是以44为分界线。

  • 优势:

    • 采用这个方式可以减少内存分配的次数,提高内存分配的效率,降低内存碎片率。

Redis五种基本数据结构为字符串、hash、set、zset、list,它们的底层实现原理如下: - **字符串**:底层实现采用简单动态字符串(SDS)。SDS是一种可变长度的字符串表示,克服了C语言字符串的一些缺点,如获取长度需要遍历、不支持二进制安全等。它可以高效地进行字符串的追加、修改等操作,同时还能动态调整内存大小以适应不同长度的字符串[^1]。 - **hash**:底层实现主要有压缩列表(ziplist)和字典(dictionary,即hashtable)。压缩列表是为了节约内存而开发的,由连续的内存块组成,减少了内存碎片和指针的内存占用。当哈希对象元素较少且元素值较小时,使用压缩列表;当元素数量较多或元素值较大时,会转换为字典结构。字典是数组 + 链表的结构,采用 OBJ_ENCODING_HT 编码方式,能实现 O(1) 复杂度的读写操作,效率很高 [^2][^3][^5]。 - **set**:底层实现是 hashtable 和 intset。当集合中的元素都是整数且元素数量较少时,使用整数集合(intset);当元素不满足整数条件或元素数量较多时,使用 hashtable。在 Redis 中,集合相当于 Java 语言里的 HashSet,内部键值对无序且唯一,其内部实现的 hashtable 中所有的 value 都是一个值 NULL。当集合中最后一个元素移除之后,数据结构自动删除,内存被回收 [^2][^4]。 - **zset**:底层实现包括压缩列表和跳跃表(skiplist)。当有序集合元素较少且元素值较小时,使用压缩列表;当元素数量较多或元素值较大时,使用跳跃表。跳跃表是一种有序的数据结构,它通过在每个节点中维护多个指向其他节点的指针,从而可以快速地进行查找、插入和删除操作,其平均时间复杂度为 O(logN) [^2]。 - **list**:底层实现主要是压缩列表和链表。压缩列表用于元素较少且元素值较小时,以节省内存。当元素数量较多或元素值较大时,会使用链表。链表在 Redis 中是双向链表,支持在链表两端进行高效的插入和删除操作 [^2][^3]。 ```python # 以下是简单示例代码,用于展示Redis操作 import redis # 连接到Redis r = redis.Redis(host='localhost', port=6379, db=0) # 字符串操作 r.set('mykey', 'Hello Redis') print(r.get('mykey')) # hash操作 r.hset('myhash', 'field1', 'value1') print(r.hget('myhash', 'field1')) # set操作 r.sadd('myset', 'member1', 'member2') print(r.smembers('myset')) # zset操作 r.zadd('myzset', {'element1': 1, 'element2': 2}) print(r.zrange('myzset', 0, -1)) # list操作 r.lpush('mylist', 'item1', 'item2') print(r.lrange('mylist', 0, -1)) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值