Redis数据类型-Strings
程序员文章站
2022-03-09 13:54:07
Redis 简介 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写的基于内存的可持久化的Key-Value数据库。 Redis的数据类型 string,li ......
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
1 127.0.0.1:6379> set test-string hi 2 ok 3 127.0.0.1:6379> get test-string 4 "hi" 5 127.0.0.1:6379> getset test-string2 "how are you" 6 (nil) 7 127.0.0.1:6379> getset test-string2 "how are you" 8 "how are you" 9 127.0.0.1:6379> mset test-string hello test-string2 "good to see you" 10 ok 11 127.0.0.1:6379> get test-string 12 "hello" 13 127.0.0.1:6379> get test-string2 14 "good to see you"
用法2
1 127.0.0.1:6379> mget test-string test-string2 2 1) "hello" 3 2) "good to see you" 4 127.0.0.1:6379> append test-string2 "!" 5 (integer) 16 6 127.0.0.1:6379> get test-string2 7 "good to see you!" 8 127.0.0.1:6379> set test-string2 20 9 ok 10 127.0.0.1:6379> incr test-string2 11 (integer) 21 12 127.0.0.1:6379>
string的encoding
字符串对象的编码可以是 int、raw 或 embstr。如果保存的是整数值并且可以用long表示,那么编码会设置为int。当字符串值得长度大于39字节使用raw 并且用sds来保存,小于等于39字节使用embstr。
127.0.0.1:6379> object encoding test-string "embstr" 127.0.0.1:6379> object encoding test-string2 "int" 127.0.0.1:6379>
1 127.0.0.1:6379> set l39 111111111122222222223333333333444444444 2 ok 3 127.0.0.1:6379> object encoding l39 4 "embstr" 5 127.0.0.1:6379> set l40 1111111111222222222233333333334444444444 6 ok 7 127.0.0.1:6379> object encoding l40 8 "raw" 9 127.0.0.1:6379>
encoding的变换
1 127.0.0.1:6379> append test-string2 " is a raw" 2 (integer) 11 3 127.0.0.1:6379> object encoding test-string2 4 "raw"
向一个保存整数值的字符串对象追加了一个字符串,程序会先将之前保存的整数值 转换为字符串值 , 然后再执行追加操作, 操作的执行结果就是一个 raw
编码的、保存了字符串值的字符串对象。
1 127.0.0.1:6379> set test-string2 "i'm a embstr" 2 ok 3 127.0.0.1:6379> set test-string3 "i'm a embstr" 4 ok 5 127.0.0.1:6379> get test-string3 6 "i'm a embstr" 7 127.0.0.1:6379> object encoding test-string3 8 "embstr" 9 127.0.0.1:6379> append test-string3 " i changed to raw" 10 (integer) 29 11 127.0.0.1:6379> get test-string3 12 "i'm a embstr i changed to raw" 13 127.0.0.1:6379> object encoding test-string3 14 "raw"
embstr
编码的字符串对象实际上是只读的, 当我们对 embstr
编码的字符串对象执行任何修改命令时, redis会先将encoding从 embstr
转换成 raw
, 然后再执行修改命令; 因为这个原因, embstr
编码的字符串对象在执行修改命令之后, 总会变成一个 raw
编码的字符串对象
源码
先看一下sds
1 struct __attribute__ ((__packed__)) sdshdr5 { 2 unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ 3 char buf[]; 4 }; 5 struct __attribute__ ((__packed__)) sdshdr8 { 6 uint8_t len; /* used */ 7 uint8_t alloc; /* excluding the header and null terminator */ 8 unsigned char flags; /* 3 lsb of type, 5 unused bits */ 9 char buf[]; 10 };
1 /* create a string object with encoding obj_encoding_raw, that is a plain 2 * string object where o->ptr points to a proper sds string. */ 3 robj *createrawstringobject(const char *ptr, size_t len) { 4 return createobject(obj_string, sdsnewlen(ptr,len)); 5 } 6 7 /* create a string object with encoding obj_encoding_embstr, that is 8 * an object where the sds string is actually an unmodifiable string 9 * allocated in the same chunk as the object itself. */ 10 robj *createembeddedstringobject(const char *ptr, size_t len) { 11 robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1); 12 struct sdshdr8 *sh = (void*)(o+1); 13 14 o->type = obj_string; 15 o->encoding = obj_encoding_embstr; 16 o->ptr = sh+1; 17 o->refcount = 1; 18 if (server.maxmemory_policy & maxmemory_flag_lfu) { 19 o->lru = (lfugettimeinminutes()<<8) | lfu_init_val; 20 } else { 21 o->lru = lru_clock(); 22 } 23 24 sh->len = len; 25 sh->alloc = len; 26 sh->flags = sds_type_8; 27 if (ptr == sds_noinit) 28 sh->buf[len] = '\0'; 29 else if (ptr) { 30 memcpy(sh->buf,ptr,len); 31 sh->buf[len] = '\0'; 32 } else { 33 memset(sh->buf,0,len+1); 34 } 35 return o; 36 } 37 38 /* create a string object with embstr encoding if it is smaller than 39 * obj_encoding_embstr_size_limit, otherwise the raw encoding is 40 * used. 41 * 42 * the current limit of 44 is chosen so that the biggest string object 43 * we allocate as embstr will still fit into the 64 byte arena of jemalloc. */ 44 #define obj_encoding_embstr_size_limit 44 45 robj *createstringobject(const char *ptr, size_t len) { 46 if (len <= obj_encoding_embstr_size_limit) 47 return createembeddedstringobject(ptr,len); 48 else 49 return createrawstringobject(ptr,len); 50 }
上一篇: Solr集群常用的操作总结