源码位置:t_string.c/server.h
字符串是redis中最常用的数据结构,在对象系统object一文中我们提到,字符串数据结构根据场景会有三种编码类型:OBJ_ENCODING_RAW、OBJ_ENCODING_INT、OBJ_ENCODING_EMBSTR,分别对应底层数据结构:sds、int、sds。下面说说这三种编码类型的使用场景。
根据redisObject数据结构可以得知,一般创建object对象时,object和数据本身在内存中是分开的,要进行两次内存分配。  
1  | typedef struct redisObject {  | 
而OBJ_ENCODING_EMBSTR的做法是,创建object之前,先计算object和数据的大小总和,然后一次性申请足够的内存空间,数据直接跟在object对象后面。这种编码是有大小限制的,因为redis采用jemalloc内存分配器,可以分配8,16,32,64字节大小的内存空间,所以申请内存时,redisObject占用16字节,sdshdr8占用3字节,数据结尾’\0’占用1字节,那么实际数据的长度限制为:64-16-8-1=44字节。
1  | 
所以当数据长度小于44时,用EMBSTR编码,否则使用OBJ_ENCODING_RAW编码。如果一个字符串对象保存的是整数值,并且可以用long类型来表示,则将字符串对象转为long,设置编码类型为OBJ_ENCODING_INT。
下面让我们看看实例:
INT和EMBSTR编码的字符串对象在条件满足的情况下,会转换为RAW编码。
比如INT编码对象在执行APPEND命令追加一段字符串时,将会转换为RAW编码,因为追加操作只支持字符串值,所以会把之前保存的整数值转为字符串后,再执行追加操作,这时就会转为RAW编码。
而redis没有提供对EMBSTR编码的字符串对象的修改操作,所以当进行追加操作时,也会先转为RAW编码,然后再进行追加。
| 命令 | 功能 | 时间复杂度 | 
|---|---|---|
| GET | 获取key对应的value | O(1) | 
| MGET | 获取多个keys对应的values | O(N),N为key的数量 | 
| GETRANGE | 返回key对应的字符串value的子串,由start和end位移决定 | O(N),N为字符串长度 | 
| SET | 设置一个key的value值 | O(1) | 
| MSET | 设置多个keys的values值 | O(1) | 
| SETNX | key不存在时才设置value值(可通过set命令+NX参数实现) | O(1) | 
| MSETNX | keys不存在时才设置values值 | O(1) | 
| SETEX | key存在时才设置值,到期时间以秒为单位(可通过set命令+XX参数实现) | O(1) | 
| PSETEX | 和setex唯一的区别是到期时间以毫秒为单位(可通过set命令+XX+PX参数实现) | O(1) | 
| SETRANGE | 覆盖key对应的string的一部分,从指定长度offset处开始,覆盖value的长度 | O(1) | 
| APPEND | 指定key的值结尾追加字符串 | O(1) | 
| GETSET | 自动将key对应到value并且返回原来key对应的value | O(1) | 
| INCR | 对存储在指定key的数值执行原子的加1操作 | O(1) | 
| INCRBY | 将key对应的数字加上指定的整数值 | O(1) | 
| INCRBYFLOAT | 将key对应的数字加上指定的浮点数值 | O(1) | 
| DECR | 对key对应的数字做减1操作 | O(1) | 
| DECRBY | 将key对应的数字减去指定的整数值 | O(1) | 
| STRLEN | 获取指定key对应value的长度 | O(1) | 
函数功能总览
1  | void setCommand(client *c); // set命令  | 
Redis命令实现
插入命令:
1  | SET key value [NX] [XX] [KEEPTTL] [EX <seconds>] [PX <milliseconds>]  | 
参数含义:
- EX seconds – 设置键key的过期时间,单位时秒
 - PX milliseconds – 设置键key的过期时间,单位时毫秒
 - NX – 只有键key不存在的时候才会设置key的值
 - XX – 只有键key存在的时候才会设置key的值
 
代码:
1  | void setCommand(client *c) {  | 
其他与set相关的命令不做代码解析了,可以自行查看源码。
1  | SETNX key value  | 
获取命令:
1  | GET key  | 
代码:
1  | void getCommand(client *c) {  | 
其他与set相关的命令不做代码解析了,可以自行查看源码。
1  | MGET key [key ...]  | 
自增自减命令:
1  | INCR key  | 
代码:
1  | // INCR  | 
其他与INCR和DECR相关的命令不做代码解析了,可以自行查看源码。
1  | INCRBY key increment  | 
</br>
获取字符串长度命令:
1  | STRLEN key  | 
代码:
1  | void strlenCommand(client *c) {  | 


