Redis(三)Redis中的String

深入理解 Redis String 数据类型,从底层实现 SDS 结构到编码方式,全面解析字符串的存储机制。

📦 String的定义

字符串是最基础的数据类型,value 可以是:

  • 字符串(简单的字符串、复杂的字符串,例如 JSON、XML)
  • 数字(整数、浮点数)
  • 二进制数据(图片、音频、视频),但最大不能超过 512MB

📋 String的常见命令

🔧 设置键值对

  • SET KEY_NAME VALUE:设置给定 key 的值。如果 key 已经存储其他值,SET 就覆写旧值,且无视类型
  • GETSET KEY_NAME VALUE:设置指定 key 的值,并返回 key 的旧值
  • SETEX KEY_NAME TIMEOUT VALUE:为指定的 key 设置值及其过期时间。如果 key 已经存在,SETEX 命令将会替换旧值
  • MSET key1 value1 key2 value2 .. keyN valueN:同时设置一个或多个 key-value 对

🔍 根据键查找值

  • GET KEY_NAME:返回 key 的值。如果 key 不存在时,返回 nil;如果 key 不是字符串类型,则返回一个错误

📏 获取字符串长度

  • STRLEN KEY_NAME:获取指定 key 所储存的字符串值的长度

🧱 String的底层实现

Redis 中的 String 类型底层实现主要基于 SDS(Simple Dynamic String,简单动态字符串)结构,并结合 int、embstr、raw 等不同的编码方式进行优化存储。

🏗️ SDS的结构

SDS数据结构

SDS 结构包含以下四个成员:

  • len:记录了字符串长度。获取字符串长度时,只需要返回这个成员变量值即可,时间复杂度为 $O(1)$
  • alloc:分配给字符数组的空间长度。通过 alloc - len 可以计算出剩余空间大小,判断是否满足修改需求。如果不满足,SDS 会自动扩容至执行修改所需的大小,因此不需要手动修改空间大小,也不会出现缓冲区溢出问题
  • flags:用来表示不同类型的 SDS。一共设计了 5 种类型,分别是 sdshdr5、sdshdr8、sdshdr16、sdshdr32 和 sdshdr64
  • buf[]:字符数组,用来保存实际数据。不仅可以保存字符串,也可以保存二进制数据

💡 相比于C语言字符串的优势

  • 二进制安全:SDS 不仅可以保存文本数据,还可以保存二进制数据。因为 SDS 使用 len 属性的值而不是空字符来判断字符串是否结束,并且 SDS 的所有 API 都会以处理二进制的方式来处理存放在 buf[] 数组里的数据。所以 SDS 能保存图片、音频、视频、压缩文件这样的二进制数据
  • 常数时间复杂度:SDS 获取字符串长度的时间复杂度是 $O(1)$。因为 C 语言的字符串并不记录自身长度,所以获取长度的复杂度为 $O(n)$;而 SDS 结构里用 len 属性记录了字符串长度,所以复杂度为 $O(1)$
  • 空间自动扩容:Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出。因为 SDS 在拼接字符串之前会检查空间是否满足要求,如果空间不够会自动扩容,所以不会导致缓冲区溢出的问题

⚖️ 编码方式

Redis String 类型会根据字符串的长度和内容选择不同的编码方式:

  • int 编码:如果一个字符串对象保存的是整数值,并且这个整数值可以用 long 类型来表示,那么字符串对象会将整数值保存在字符串对象结构的 ptr 属性里面(将 void 转换成 long),并将编码设置为 int
  • embstr 编码:如果字符串对象保存的是一个短字符串,那么字符串对象将使用 SDS 来保存这个字符串,并将编码设置为 embstrembstr 是专门用于保存短字符串的一种优化编码方式
  • raw 编码:如果字符串对象保存的是一个长字符串,那么字符串对象将使用 SDS 来保存这个字符串,并将编码设置为 raw
最后更新于 2026-05-09 09:22 UTC
그 경기 끝나고 좀 멍하기 있었는데 여러분 이제 살면서 여러가
使用 Hugo 构建
主题 StackJimmy 设计