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() 尝试将字符串编码为整数
-
支持共享对象以减少内存使用
-
智能的引用计数管理
性能特性
- 原子操作: 所有操作都是原子的
- 内存效率: 智能编码和共享机制
- 批量操作: 支持 MSET/MGET 等批量命令
- 过期时间: 灵活的 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 以及如何布局内存