原文链接:https://mp.weixin.qq.com/s/bujgyEI6idmh7DOghzG-cQ
今天我们就来开启我们的连载章——Redis字符串对象String,这个对象看起来挺简单,但是Redis做了一些优化,很多细节都需要了解,同时呢,String作为Redis基础的数据对象,也是面试中的高频考点。
1.是什么?
2.适用场景
3.常用操作
3.1 写操作
3.1.1 SET
127.0.0.1:6379> SET strniuniu cat
OK
3.1.2 SETNX
如果对存在的Key,调用SETNX:
127.0.0.1:6379> SETNX strniuniu fish
(integer) 0
对不存在的key,调用SETNX:
127.0.0.1:6379> SETNX strmart fish
(integer) 1
3.1.3 DEL
功能:删除对象,返回值为删除成功了几行。
127.0.0.1:6379> DEL strmart
(integer) 1
3.2 读操作
3.2.1 GET
功能:查询某个key,存在就返回对应的value,如果不存在返回nil。
127.0.0.1:6379> get strniuniu
"cat"
127.0.0.1:6379> get strmart
(nil)
3.2.2 MGET
功能:一次查询多个key,如果某个key不存在,对应位置返回nil。
127.0.0.1:6379> MGET strniuniu strmart
1) "cat"
2) (nil)
4.底层实现
4.1 三种编码方式
这个阈值追溯源码的话,是用常量OBJ_ENCODING_EMBSTR_SIZE_LIMIT来表示,3.2版本之前是39字节,3.2版之后是44字节。
// from Redis 7.0.8
/* 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. */
robj *createStringObject(const char *ptr, size_t len) {
if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT)
return createEmbeddedStringObject(ptr,len);
else
return createRawStringObject(ptr,len);
}
EMBSTR内存:
RAW内存:
4.2 为什么要SDS?
首先,Redis中SDS分为sdshdr8、sdshdr16、sdshdr32、sdshdr64,它们的字段属性都是一样,区别在于应对不同大小的字符串,我们以sdshdr8为例:
// from Redis 7.0.8
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[];
};
其中有两个关键字段,一个是len,表示使用了多少;一个是alloc,表示一共分配了多少内存。这两个字段的差值(alloc-len)就是预留空间的大小。flags则是标记是哪个分类,比如sdshdr8的分类就是: