String(字符串)
底层实现细节:
- 动态字符串(SDS): SDS相比于C语言的原生字符串,提供了自动内存管理和预分配机制。当字符串长度增加时,SDS会预先分配额外的空间,以减少内存重新分配的次数。
- EMBSTR编码: 在Redis 3.2之后,对于小字符串(长度小于44字节),引入了EMBSTR编码。这种编码将字符串和长度信息一起存储在一个连续的内存块中,以减少内存碎片和分配次数。
使用场景细节:
- 存储简单的文本数据。
- 存储JSON格式的数据。
- 存储序列化后的对象。
List(列表)
底层实现细节:
- ziplist(压缩列表): 当列表元素较少且元素本身较小时,Redis使用ziplist。ziplist是一种紧凑的、连续的内存布局,可以存储多个元素。每个元素由前一个元素的大小、元素内容和元素类型组成。
- linkedlist(双向链表): 当列表元素较多或元素本身较大时,Redis使用linkedlist。双向链表提供了快速的插入和删除操作。
使用场景细节:
- 作为消息队列,按插入顺序处理消息。
- 存储文章或新闻列表,按发布时间排序。
- 存储用户关注列表或好友列表。
Hash(哈希)
底层实现细节:
- 哈希表(hashtable): Redis的哈希表使用开放寻址法解决哈希冲突。每个桶包含一个链表,用于存储具有相同哈希值的键值对。当哈希表需要扩展时(负载因子超过一定阈值),Redis会创建一个更大的哈希表,并将原哈希表中的数据重新哈希到新的哈希表中。
使用场景细节:
- 存储对象的属性,如用户信息、商品详情等。
- 实现缓存系统,将键映射到值。
Set(集合)
底层实现细节:
- intset(整数集合): 当集合只包含整数且元素个数较少时,Redis使用intset。intset是一种紧凑的存储方式,直接存储整数值,而不需要额外的键。
- hashtable(哈希表): 当集合包含非整数元素或元素个数较多时,Redis使用hashtable。
使用场景细节:
- 实现去重功能。
- 执行集合运算,如交集、并集和差集。
- 存储标签或兴趣列表。
Zset(有序集合)
底层实现细节:
- skiplist(跳跃表): 跳跃表是一种可以进行二分查找的有序链表。它通过在链表中添加多级索引来提高查找效率。在Zset中,跳跃表用于按分数对元素进行排序。
- hashtable(哈希表): 哈希表用于存储元素到分数的映射关系,以便在O(1)时间复杂度内获取元素的分数。
使用场景细节:
- 实现排行榜,按分数从高到低排序。
- 存储按权重排序的列表,如搜索引擎中的关键词权重。
- 实现范围查询,如查找分数在某个范围内的元素。
通过这些详细的底层实现和使用场景,我们可以看到Redis是如何在满足性能需求的同时,尽可能地节省内存空间的。不同的数据结构和底层实现在不同的使用场景下都有其优势和适用性。