Redis 简介
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写的基于内存的可持久化的Key-Value数据库。
Redis的数据类型
string,list,hash,set,sorted set
String
string是redis最基本的类型,而且string类型是二进制安全的。意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象。
与String相关的常用命令:
- SET:为一个key设置value,可以配合EX/PX参数指定key的有效期,通过NX/XX参数针对key是否存在的情况进行区别操作,时间复杂度O(1)
- GET:获取某个key对应的value,时间复杂度O(1)
- GETSET:为一个key设置value,并返回该key的原value,时间复杂度O(1)
- MSET:为多个key设置value,时间复杂度O(N)
- MSETNX:同MSET,如果指定的key中有任意一个已存在,则不进行任何操作,时间复杂度O(N)
- MGET:获取多个key对应的value,时间复杂度O(N)
如果保存的是整数值并且可以用long表示,那么编码会设置为INT,那么还有额外的命令
- INCR:将key对应的value值自增1,并返回自增后的值。只对可以转换为整型的String数据起作用。时间复杂度O(1)
- INCRBY:将key对应的value值自增指定的整型数值,并返回自增后的值。只对可以转换为整型的String数据起作用。时间复杂度O(1)
- DECR/DECRBY:同INCR/INCRBY,自减函数。
用法1
127.0.0.1:> set test-string hi
OK
127.0.0.1:> get test-string
"hi"
127.0.0.1:> getset test-string2 "how are you"
(nil)
127.0.0.1:> getset test-string2 "how are you"
"how are you"
127.0.0.1:> mset test-string hello test-string2 "good to see you"
OK
127.0.0.1:> get test-string
"hello"
127.0.0.1:> get test-string2
"good to see you"
用法2
127.0.0.1:> mget test-string test-string2
) "hello"
) "good to see you"
127.0.0.1:> append test-string2 "!"
(integer)
127.0.0.1:> get test-string2
"good to see you!"
127.0.0.1:> set test-string2
OK
127.0.0.1:> incr test-string2
(integer)
127.0.0.1:>
string的encoding
字符串对象的编码可以是 INT、RAW 或 EMBSTR。如果保存的是整数值并且可以用long表示,那么编码会设置为INT。当字符串值得长度大于字节使用raw 并且用sds来保存,小于等于39字节使用embstr。
127.0.0.1:> object encoding test-string
"embstr"
127.0.0.1:> object encoding test-string2
"int"
127.0.0.1:>
127.0.0.1:> set l39
OK
127.0.0.1:> object encoding l39
"embstr"
127.0.0.1:> set l40
OK
127.0.0.1:> object encoding l40
"raw"
127.0.0.1:>
encoding的变换
127.0.0.1:> append test-string2 " is a raw"
(integer)
127.0.0.1:> object encoding test-string2
"raw"
向一个保存整数值的字符串对象追加了一个字符串,程序会先将之前保存的整数值 转换为字符串值 , 然后再执行追加操作, 操作的执行结果就是一个 raw
编码的、保存了字符串值的字符串对象。
127.0.0.1:> set test-string2 "I'm a embstr"
OK
127.0.0.1:> set test-string3 "I'm a embstr"
OK
127.0.0.1:> get test-string3
"I'm a embstr"
127.0.0.1:> object encoding test-string3
"embstr"
127.0.0.1:> append test-string3 " I changed to raw"
(integer)
127.0.0.1:> get test-string3
"I'm a embstr I changed to raw"
127.0.0.1:> object encoding test-string3
"raw"
embstr
编码的字符串对象实际上是只读的, 当我们对 embstr
编码的字符串对象执行任何修改命令时, redis会先将encoding从 embstr
转换成 raw
, 然后再执行修改命令; 因为这个原因, embstr
编码的字符串对象在执行修改命令之后, 总会变成一个 raw
编码的字符串对象
源码
先看一下sds
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* used */
uint8_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
/* Create a string object with encoding OBJ_ENCODING_RAW, that is a plain
* string object where o->ptr points to a proper sds string. */
robj *createRawStringObject(const char *ptr, size_t len) {
return createObject(OBJ_STRING, sdsnewlen(ptr,len));
} /* Create a string object with encoding OBJ_ENCODING_EMBSTR, that is
* an object where the sds string is actually an unmodifiable string
* allocated in the same chunk as the object itself. */
robj *createEmbeddedStringObject(const char *ptr, size_t len) {
robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+);
struct sdshdr8 *sh = (void*)(o+); o->type = OBJ_STRING;
o->encoding = OBJ_ENCODING_EMBSTR;
o->ptr = sh+;
o->refcount = ;
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
o->lru = (LFUGetTimeInMinutes()<<) | LFU_INIT_VAL;
} else {
o->lru = LRU_CLOCK();
} sh->len = len;
sh->alloc = len;
sh->flags = SDS_TYPE_8;
if (ptr == SDS_NOINIT)
sh->buf[len] = '\0';
else if (ptr) {
memcpy(sh->buf,ptr,len);
sh->buf[len] = '\0';
} else {
memset(sh->buf,,len+);
}
return o;
} /* Create a string object with EMBSTR encoding if it is smaller than
* OBJ_ENCODING_EMBSTR_SIZE_LIMIT, otherwise the RAW encoding is
* used.
*
* The current limit of 44 is chosen so that the biggest string object
* we allocate as EMBSTR will still fit into the 64 byte arena of jemalloc. */
#define OBJ_ENCODING_EMBSTR_SIZE_LIMIT 44
robj *createStringObject(const char *ptr, size_t len) {
if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT)
return createEmbeddedStringObject(ptr,len);
else
return createRawStringObject(ptr,len);
}