Redis 字符串键的实现(t_string)
1. 字符串命令介绍
redis中的所有字符串命令如下:字符串类型命令详解
序号命令及描述
1SET key value:设置指定 key 的值
2GET key: 获取指定 key 的值。
3GETRANGE key start end: 返回 key 中字符串值的子字符
4GETSET key value:将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
5GETBIT key offset:对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
6MGET key1 [key2..]:获取所有(一个或多个)给定 key 的值。
7SETBIT key offset value:对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
8SETEX key seconds value:将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
9SETNX key value:只有在 key 不存在时设置 key 的值。
10SETRANGE key offset value:用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
11STRLEN key:返回 key 所储存的字符串值的长度。
12MSET key value [key value …]:同时设置一个或多个 key-value 对。
13MSETNX key value [key value …]:同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
14PSETEX key milliseconds value:这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
15INCR key:将 key 中储存的数字值增一。
16INCRBY key increment将 key: 所储存的值加上给定的增量值(increment) 。
17INCRBYFLOAT key increment:将 key 所储存的值加上给定的浮点增量值(increment) 。
18DECR key:将 key 中储存的数字值减一。
19DECRBY key decrementkey: 所储存的值减去给定的减量值(decrement) 。
20APPEND key value:如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。
2. 字符串命令的实现
字符串命令底层数据结构为 简单动态字符串SDS 。对于字符串命令,无论是命令本身还是参数,都是作为成一个对象对待的。关于redis的对象系统,请参考文章:redis对象系统源码剖析和注释。
在redis的对象系统中,字符串对象的底层实现类型有如下三种:
因此,一个字符串对象的结构定义如下:
typedef struct redisObject { //对象的数据类型,字符串对象应该为 OBJ_STRING unsigned type:4; //对象的编码类型,分别为OBJ_STRING、OBJ_ENCODING_INT或OBJ_ENCODING_EMBSTR unsigned encoding:4; //暂且不关心该成员 unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */ //引用计数 int refcount; //指向底层数据实现的指针 void *ptr;} robj;
我们假设一个key的值为”Hello World” ,因此它的空间结构如图所示:
3. 字符串命令源码注释
所有命令详细实现可以上github下载:t_string.c注释。这里列出重要的命令。
3.1 SET 一类命令的最底层实现
#define OBJ_SET_NO_FLAGS 0#define OBJ_SET_NX (1<<0) /* Set if key not exists. */ //在key不存在的情况下才会设置#define OBJ_SET_XX (1<<1) /* Set if key exists. */ //在key存在的情况下才会设置#define OBJ_SET_EX (1<<2) /* Set if time in seconds is given */ //以秒(s)为单位设置键的key过期时间#define OBJ_SET_PX (1<<3) /* Set if time in ms in given */ //以毫秒(ms)为单位设置键的key过期时间//setGenericCommand()函数是以下命令: SET, SETEX, PSETEX, SETNX.的最底层实现//flags 可以是NX或XX,由上面的宏提供//expire 定义key的过期时间,格式由unit指定//ok_reply和abort_reply保存着回复client的内容,NX和XX也会改变回复//如果ok_reply为空,则使用 "+OK"//如果abort_reply为空,则使用 "$-1"void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) { long long milliseconds = 0; /* initialized to avoid any harmness warning */ //初始化,避免错误 //如果定义了key的过期时间 if (expire) { //从expire对象中取出值,保存在milliseconds中,如果出错发送默认的信息给client if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK) return; // 如果过期时间小于等于0,则发送错误信息给client if (milliseconds <= 0) { addReplyErrorFormat(c,"invalid expire time in %s