t_string.c 是 Redis 源码中实现字符串数据类型(String)的核心模块,它包含了所有与字符串相关的命令实现

主要功能特性

类别 命令/选项 作用
基础字符串操作 SET / GET 设置/获取字符串值
SETEX / PSETEX 设置值并附带过期时间(秒/毫秒)
SETNX 仅当键不存在时设置值
GETSET 返回旧值并设置新值
扩展字符串操作 GETEX [PERSISTEXPXEXATPXAT] 获取值并可移除/更新 TTL(秒/毫秒/时间戳)
GETDEL 获取值后删除键
MGET / MSET 批量获取/设置
MSETNX 批量设置,要求所有键均不存在
字符串修改操作 APPEND 末尾追加数据
SETRANGE / GETRANGE 按偏移写入/读取子串
STRLEN 返回字符串长度
数值操作 INCR / DECR 对整数值自增/自减
INCRBY / DECRBY 按指定步长自增/自减
INCRBYFLOAT 浮点自增(内部以 SET 传播且保持 TTL)
高级功能 LCS [LENIDXMINMATCHLENWITHMATCHLEN] 计算两个字符串的最长公共子序列,支持返回长度/区间/最小匹配长度等

备注:SET 支持 NX/XX/GET/EX/PX/EXAT/PXAT/KEEPTTL 等选项组合;TTL 单位与时间戳在解析时统一转换为绝对毫秒时间

核心实现特点

通用设置命令 (setGenericCommand)

void setGenericCommand(client *c, int flags, robj *key, robj **valref, 
                      robj *expire, int unit, robj *ok_reply, robj *abort_reply)

实现了所有 SET 系列命令的核心逻辑,支持多种标志:

  • OBJ_SET_NX: 仅当键不存在时设置

  • OBJ_SET_XX: 仅当键存在时设置

  • OBJ_EX/OBJ_PX: 设置过期时间(秒/毫秒)

  • OBJ_KEEPTTL: 保持现有 TTL

  • OBJ_SET_GET: 获取旧值

字符串长度检查

static int checkStringLength(client *c, long long size, long long append)

确保字符串长度不超过配置的最大值,防止内存溢出

扩展参数解析

int parseExtendedStringArgumentsOrReply(client *c, int *flags, int *unit, 
                                       robj **expire, int command_type)

解析 SET 和 GET 命令的扩展参数,如过期时间、条件标志等

内存优化

  • 使用 tryObjectEncoding() 尝试将字符串编码为整数

  • 支持共享对象以减少内存使用

  • 智能的引用计数管理

性能特性

  1. 原子操作: 所有操作都是原子的
  2. 内存效率: 智能编码和共享机制
  3. 批量操作: 支持 MSET/MGET 等批量命令
  4. 过期时间: 灵活的 TTL 设置选项

这个模块是 Redis 最基础和最重要的数据类型实现之一,为其他复杂数据类型提供了基础支持

t_string 和 sds 的关系

graph TD;
  A["Redis 应用层"] --> B["t_string (字符串类型实现)"];
  B --> C["Redis 对象系统 (robj/kvobj)"];
  C --> D["sds(动态字符串,二进制安全,末尾保留 \\0 以兼容)"];
  D --> E["内存分配器/char 缓冲区(zmalloc/alloc)"];

sds 是 Redis 的底层字符串库,提供高效的动态字符串操作

t_string 是 Redis 字符串数据类型的完整实现,基于 sds 构建

t_string 负责:

  • 命令解析和执行
  • 对象生命周期管理
  • 编码优化和类型检查
  • 事务和复制支持

sds 负责:

  • 字符串的内存管理
  • 字符串的基本操作(长度、追加、截取等)
  • 内存分配优化

这种设计实现了关注点分离:sds 专注于字符串操作的高效性,t_string 专注于 Redis 字符串类型的完整功能

核心函数对应关系

t_string 功能 sds 底层实现
stringObjectLen() sdslen()
setrangeCommand() sdsgrowzero()
appendCommand() sdscatlen()
getrangeCommand() sdslen() + 内存访问
字符串创建 sdsnewlen(), sdsnew()
  • redisObject(robj/kvobj) 是 Redis 所有键值对象的统一“外壳”,记录类型、编码、引用计数、LRU 等元数据。

  • t_string 是“字符串类型命令”的实现层,基于 redisObject 操作底层字符串数据。

  • sds 是底层“动态字符串库”,承载字符串的真实内存(追加、扩容、长度/容量管理)。

redisobject、t_string、sds

三者关系:t_string 调用对象层 API 操作 robj/kvobj,而 robj/kvobj->ptr 在字符串场景通常指向一个 sds(或整型立即值/嵌入式 sds)

对象层根据数据规模与特征选择合适的编码(RAW/EMBSTR/INT),决定是否用 sds 以及如何布局内存