Redis 数据类型(上)String,List,Set

Redis 数据类型String,List,Set

(String、List、Set 底层实现原理)


一、String 类型(底层结构:RAW、EMBSTR、INT)

String 是 Redis 最基础的类型,底层实现由 RedisObject + SDS 组成。

根据值的大小和类型不同,String 的 encoding 有三种:

1.1 RAW(OBJ_ENCODING_RAW)

适用场景:

  • 长度大于 44 字节的字符串
  • 或者 String 被修改过(embstr 被扩容后自动变 RAW)

结构示意(图 1):

复制代码
RedisObject
 ├ type: OBJ_STRING
 ├ encoding: OBJ_ENCODING_RAW
 ├ lru
 ├ refcount
 └ ptr → SDS

而 SDS 内部结构:

复制代码
len / alloc / flags / buf[]

特点:

  • RedisObject 与 SDS 分开分配(两次 malloc)
  • 适合可变长字符串
  • 支持 SDS 的自动扩容、惰性空间释放

1.2 EMBSTR(OBJ_ENCODING_EMBSTR)

适用条件:

  • 字符串长度 ≤ 44 字节(Redis 6+)
  • 初次创建时满足条件

结构示意:

复制代码
RedisObject + SDS 统一分配在连续内存中

特点:

  • 只 malloc 一次,内存连续
  • 释放时速度更快(一次 free)
  • 更适合短字符串、小 JSON、小 token

但:

  • 一旦修改长度 → 自动转为 RAW

1.3 INT(OBJ_ENCODING_INT)

适用于:

  • 字符串内容为整数
  • 且在 64bit 有符号整数范围内

结构示意:

复制代码
RedisObject
 ├ type: OBJ_STRING
 ├ encoding: OBJ_ENCODING_INT
 └ ptr = 整数值(long long)

特点:

  • 不使用 SDS,直接存整数指针
  • 占用内存最少
  • 性能最高

1.4 String 底层编码转换规则(面试高频)

值类型 编码
整数 INT
短字符串(≤44B) EMBSTR
长字符串 RAW
embstr 被修改后 RAW

二、List 类型(底层结构:quicklist)

从 Redis 3.2 开始,List 的底层实现全部使用:

quicklist = linkedlist + ziplist 的结合体

示意图:

复制代码
RedisObject(type=OBJ_LIST, encoding=OBJ_ENCODING_QUICKLIST)
       ↓
QuickList
       ↓
多个 QuickListNode 节点(双向链表)
       ↓
每个 node 内部保存一个 ziplist

2.1 为什么需要 quicklist?

旧版本的 List 结构:

  • 元素少 → ziplist
  • 元素多 → linkedlist

缺点:

  • linkedlist 内存碎片严重
  • ziplist 大了以后插入/删除效率差

quicklist = ziplist(紧凑内存) + linkedlist(灵活插入删除)


2.2 quicklist 的结构解析

QuickList

复制代码
QuickList
 ├ head
 ├ tail
 ├ count   // 总元素统计
 ├ len     // 节点数量(多少个 ziplist)
 ├ fill    // 每个 ziplist 最大容量策略
 └ compress // 是否开启压缩

QuickListNode

每个 node 是一个 ziplist:

复制代码
QuickListNode
 ├ *pre
 ├ *next
 └ *zl(ziplist)

ziplist 内部结构

复制代码
zlbytes / zltail / zllen / entry... / zlend

2.3 quicklist 的优势

  • 内存紧凑(ziplist)
  • 插入删除效率高(链表 node 跳转)
  • 支持 ziplist 压缩(节省内存)
  • 兼顾性能 & 内存消耗

2.4 quicklist 的使用场景

Redis List 类型操作:

  • LPUSH / RPUSH
  • LPOP / RPOP
  • LRANGE
  • Trim 队列
  • 消息队列(非阻塞场景)

三、Set 类型(底层结构:intset / dict)

Set 是一个无序、不重复的集合,底层结构分两种情况:


3.1 intset(OBJ_ENCODING_INTSET)

当满足两个条件时使用 intset:

  1. 所有元素都是整数
  2. 元素数量 ≤ set-max-intset-entries(默认 512)

结构示意:

复制代码
RedisObject(type=OBJ_SET, encoding=OBJ_ENCODING_INTSET)
      ↓
IntSet
 ├ encoding(int16/int32/int64)
 ├ length
 └ contents[](升序排列整数)

特点:

  • 紧凑高效(连续内存)
  • 查找用二分查找(O(logN))
  • 插入 O(N)
  • 内存使用非常低

适合:

  • 用户 ID、商品 ID 集合
  • 小集合场景

超过阈值或包含非整数 → 自动升级为 dict。


3.2 dict 结构(OBJ_ENCODING_HT)

当不满足 intset 条件时,升级成 hashtable(dict)

结构示意(图 3):

复制代码
RedisObject(type=OBJ_SET, encoding=OBJ_ENCODING_HT)
      ↓
dict
  ↓ ht[0], ht[1](渐进式 rehash)
      ↓
    dictEntry(key=value元素, val=null)

Set 的 value 统一为 null。

dict 特点:

  • 查询 O(1)
  • 支持渐进式 rehash(不会阻塞)
  • 大集合适用

适合:

  • 大规模集合(上万、百万)
  • 频繁添加删除的业务

四、三种数据类型结构对比总结表

数据类型 底层编码 结构特点 使用场景
String INT 直接存 long long 计数器、数字值
EMBSTR RedisObject + SDS 连续内存 短字符串、高性能
RAW RedisObject 与 SDS 分离 长字符串、大 JSON
List quicklist ziplist + linkedlist 队列、日志、分页读取
Set intset 升序数组 + 二分查找 小整数集合
dict 哈希表 大规模集合

五、常考面试点总结

1. String 为什么有三种编码?

因为:

  • 整数更省内存(int)
  • 短字符串更快(embstr)
  • 长字符串更灵活(raw)

2. List 为什么使用 quicklist?

因为:

  • ziplist 内存紧凑但扩容慢
  • linkedlist 插入快但浪费空间
  • quicklist 结合两者优点

3. Set 为什么用 intset/dict 两种?

因为:

  • 小整数集合 → intset(内存极其小)
  • 大集合/复杂元素 → dict(复杂度 O(1))

4. Set 如何从 intset 切换到 dict?

触发条件:

  • 插入非整数
  • 集合大小超过阈值 (默认 512)

六、总结(背诵版)

String:RAW / EMBSTR / INT

  • INT:整数
  • EMBSTR:短字符串(一次分配)
  • RAW:长字符串(两次分配,可扩容)

List:quicklist

  • 链表节点 + 每个节点是 ziplist
  • 内存节省、插入删除快

Set:intset / dict

  • 小整数集合 → intset
  • 大集合或非整数 → dict
相关推荐
X***C8621 小时前
【Oracle11g SQL详解】UPDATE 和 DELETE 操作的正确使用
数据库·sql
爬山算法1 小时前
Redis(156)Redis的延迟问题如何解决?
数据库·redis·缓存
v***91301 小时前
Windows版Redis本地后台启动
数据库·windows·redis
x***44011 小时前
【prometheus】监控MySQL并实现可视化
数据库·mysql·prometheus
h***04771 小时前
MySQL 的 INSERT(插入数据)详解
android·数据库·mysql
u***27611 小时前
【MySQL】数据库和表的操作
数据库·mysql·oracle
煎蛋学姐1 小时前
SSM青岛恒星科技学院机房管理系统0k0u9(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·机房管理系统·青岛恒星科技学院·高校信息化
爬山算法1 小时前
Redis(157)Redis的连接问题如何解决?
数据库·redis·bootstrap